Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterownik go-mssqldb automatycznie konwertuje typy Go na typy SQL Server po przekazaniu parametrów, a podczas skanowania wyników przekształca typy SQL Server z powrotem na typy Go. Ten artykuł dokumentuje domyślne konwersje oraz specyficzne dla sterowników typy dostępne do jawnej kontroli.
Przykłady w tym artykule porównane są z przykładową bazą danych AdventureWorks2025 . Przykłady zorientowane na odczyt zapytania do wbudowanych obiektów, takich jak Production.Product i Sales.vSalesPerson. Przykłady zorientowane na zapis skierowane do HumanResources.Department i Production.ProductCategory.
Przejdź do mapowania parametrów SQL Server
Gdy przekazujesz wartości jako parametry zapytania, sterownik konwertuje typy Go na typy SQL Server:
| typ Go | Typ programu SQL Server | Notatki |
|---|---|---|
string |
nvarchar | Ciąg unicode. Zastosowanie mssql.VarChar dla varcharów nie-Unicode. |
[]byte |
varbinary | Dane binarne. |
int64 |
bigint | |
float64 |
float | 64-bitowy float. |
bool |
bit | |
time.Time |
datetimeoffset | Zachowuje przesunięcie strefy czasowej. Wykorzystanie mssql.DateTime1 na randkę. Zastosowanie mssql.DateTimeOffset do wyraźnej kontroli przesunięcia. |
int32 |
int | |
int16 |
smallint | |
int8 |
tinyint | |
float32 |
prawdziwy | 32-bitowy float. |
mssql.TVP |
Parametr z wartością tabeli | Zobacz parametry tabelowe. |
Typy specyficzne dla kierowców
Używaj tych typów z pakietumssql, gdy potrzebujesz wyraźnej kontroli nad typem SQL Server:
| Typ sterownika | Typ programu SQL Server | Description |
|---|---|---|
mssql.VarChar |
varchar | Ciąg nie-Unicode. Opakuj wartość string . |
mssql.NVarCharMax |
nvarchar(max) | Duży ciąg znaków w Unicode. |
mssql.VarCharMax |
varchar(max) | Nie-Unicode duży ciąg znaków. |
mssql.NChar |
nchar | Ciąg Unicode o stałej długości. Opakuj wartość string . |
mssql.DateTime1 |
datetime | Starszy czas randkowy bez przesunięcia. |
mssql.DateTimeOffset |
datetimeoffset | Wyraźna kontrola offsetu. |
mssql.NullDate |
date | Wartość nulowalna tylko na datę. |
mssql.NullTime |
time | Wartość tylko czasowa do unieważnienia. |
mssql.NullDateTime |
datetime2 | Wartość data i czasu do zerowania bez konwersji stref czasowych. |
mssql.UniqueIdentifier |
uniqueidentifier | Wartość identyfikatora GUID. |
mssql.TVP |
Typ tabeli zdefiniowany przez użytkownika | Struktura parametrów tabelowych. |
Używaj nullable date-and-time helperów, gdy potrzebujesz semantyki tylko daty lub czasu w SQL Server, a parametr lub cel skanowania może być NULL.
Przykład: varchar kontra nvarchar
Domyślnie string parametry są wysyłane jako nvarchar. Zamiast tego można użyć varchar :
import "github.com/microsoft/go-mssqldb"
// Sends as nvarchar (default)
db.QueryContext(ctx, "SELECT * FROM Production.Product WHERE Name = @p1", "Adjustable Race")
// Sends as varchar
db.QueryContext(ctx, "SELECT * FROM Production.Product WHERE Name = @p1", mssql.VarChar("Adjustable Race"))
Przykład: unikalny identyfikator
Użyj czcionki mssql.UniqueIdentifier do skanowania uniqueidentifier kolumn:
import "github.com/microsoft/go-mssqldb"
var id mssql.UniqueIdentifier
err := db.QueryRowContext(ctx, "SELECT rowguid FROM Production.Product WHERE Name = @p1",
sql.Named("p1", "Adjustable Race")).Scan(&id)
Mapowania wyników SQL Server to Go
Podczas skanowania wyników zapytań sterownik konwertuje typy SQL Server na typy Go:
| Typ programu SQL Server | typ Go | Notatki |
|---|---|---|
| int, bigint, smallint, tinyint | int64 |
Wszystkie typy liczb całkowitych skanują do .int64 Rzucaj według potrzeby. |
| Float, real | float64 |
|
| dziesiętne, liczbowe, pieniądze, drobne pieniądze |
[]byte lub string |
Nie ma natywnego typu dziesiętnego w Go. Skanuj lub korzystaj z string zewnętrznej biblioteki dziesiętnej. |
| bit | bool |
|
| Char, Varchar, tekst | string |
|
| nchar, nvarchar, ntext | string |
|
| binarny, varbinary, obraz | []byte |
|
| randka, randka,randka2,mała randkagodzina | time.Time |
|
| datetimeoffset | time.Time |
Przesunięcie strefy czasowej jest zachowane. |
| time | time.Time |
Składowa daty to 0001-01-01. |
| uniqueidentifier |
[]byte lub mssql.UniqueIdentifier |
Domyślnie skanuje do surowych bajtów. Zastosowanie mssql.UniqueIdentifier do formatowanego wyjścia GUID. |
| sql_variant | interface{} |
Konkretny typ Go zależy od zapisanej wartości SQL Server. |
| xml | string |
Nazwane parametry
Użycie sql.Named do tworzenia nazwanych parametrów:
rows, err := db.QueryContext(ctx,
"SELECT * FROM Sales.vSalesPerson WHERE CountryRegionName = @location AND FirstName = @name",
sql.Named("location", "Australia"),
sql.Named("name", "Jared"))
Note
Parametry pozycyjne (@p1, @p2) również działają. Sterownik przypisuje nazwy porządkowe na podstawie kolejności argumentów.
Obsługa wartości NULL
Kolumny SQL Server, które pozwalają na NULL, wymagają specjalnej obsługi w Go. Standardowy database/sql pakiet zapewnia typy nullable do tego celu.
SQL. Typy zerowe
Użyj sql.NullString, sql.NullInt64, sql.NullFloat64, sql.NullBool, oraz sql.NullTime do obsługi kolumn, które mogą być NULL. Dla wartości daty, godziny i datetime2 w SQL Server, które chcesz oddzielić od domyślnych ustawień Gotime.Time, użyj mssql.NullDate, mssql.NullTime, oraz mssql.NullDateTime:
var name sql.NullString
var color sql.NullString
var weight sql.NullFloat64
var sellStartDate sql.NullTime
var sellEndDate sql.NullTime
err := db.QueryRowContext(ctx,
"SELECT Name, Color, Weight, SellStartDate, SellEndDate FROM Production.Product WHERE ProductID = @id",
sql.Named("id", 1)).Scan(&name, &color, &weight, &sellStartDate, &sellEndDate)
if err != nil {
log.Fatal(err)
}
if name.Valid {
fmt.Println("Name:", name.String)
} else {
fmt.Println("Name: NULL")
}
if weight.Valid {
fmt.Printf("Weight: %.2f\n", weight.Float64)
}
Obsługa NULL za pomocą wskaźników
Zamiast sql.Null typów, używaj wskaźników.
nil Wskaźnik oznacza NULL:
var name *string
var color *string
err := db.QueryRowContext(ctx,
"SELECT Name, Color FROM Production.Product WHERE ProductID = @id",
sql.Named("id", 1)).Scan(&name, &color)
if name != nil {
fmt.Println("Name:", *name)
} else {
fmt.Println("Name: NULL")
}
Wskazówka
Obsługa NULL za pomocą wskaźników jest bardziej zwięzła, ale sql.Null typy sprawiają, że intencja NULL jest bardziej wyraźna w definicjach struktur. Wybierz wzorzec, który preferuje Twój zespół i stosuj go konsekwentnie.
Wyślij wartości NULL jako parametry
Przejdź, nil aby wysłać wartość NULL jako parametr:
// Insert a row with a NULL Color.
_, err := db.ExecContext(ctx,
"INSERT INTO Production.ProductCategory (Name) VALUES (@name)",
sql.Named("name", "Custom Parts"))
Precyzja dziesiętna i numeryczna
SQL Server decimal i typy obsługują numeric do 38 cyfr precyzyjności. Go float64 podaje tylko około 15-16 cyfr znaczących. Skanowanie wysokoprecyzyjnych wartości powoduje float64 cichą utratę precyzji.
Skanowanie do łańcucha
Najbezpieczniejszym i najprostszym rozwiązaniem jest zeskanowanie decimal/numeric/money/smallmoney kolumn do string, a następnie konwersja za pomocą precyzyjnie bezpiecznej biblioteki:
var priceStr string
err := db.QueryRowContext(ctx,
"SELECT ListPrice FROM Production.Product WHERE ProductID = @id",
sql.Named("id", 1)).Scan(&priceStr)
if err != nil {
log.Fatal(err)
}
fmt.Println("Price:", priceStr) // "12345.678901234567890"
Dla ścieżek zależnych od wydajności możesz skanować i []byte analizować bezpośrednio z biblioteką dziesiętną, aby zmniejszyć alokację ciągów znaków.
Użyj sprężyny/dziesiętnej do arytmetyki
Biblioteka shopspring/decimal oferuje arytmetykę dziesiętną o dowolnej precyzji:
import "github.com/shopspring/decimal"
var priceStr string
err := db.QueryRowContext(ctx,
"SELECT ListPrice FROM Production.Product WHERE ProductID = @id",
sql.Named("id", 1)).Scan(&priceStr)
if err != nil {
log.Fatal(err)
}
price, err := decimal.NewFromString(priceStr)
if err != nil {
log.Fatal(err)
}
tax := price.Mul(decimal.NewFromFloat(0.08))
total := price.Add(tax)
fmt.Println("Total:", total.StringFixed(2))
Uwaga
Nigdy nie skanuj money ani decimal nie wkraczaj do float64 kolumn, gdy dokładna precyzja ma znaczenie (obliczenia finansowe, waluta, podatek). Użyj skanowania wartości dokładnej (stringlub []byte) z lub shopspring/decimal zamiast cockroachdb/apd tego.
Wyślij wartości dziesiętne jako parametry
Wysyłając wartości dziesiętne jako parametry, używaj string , aby uniknąć utraty precyzji pływającej:
price := "12345.678901234567890"
_, err := db.ExecContext(ctx,
"UPDATE Production.Product SET ListPrice = @price WHERE ProductID = @id",
sql.Named("price", price),
sql.Named("id", 1)) // String is converted to decimal by SQL Server.
Typy dat i godzin
Czas. Mapowanie czasu
Domyślnie kierowca mapuje Go time.Time na datetimeoffset Gon, co zachowuje przesunięcie strefy czasowej. Używaj typów specyficznych dla sterowników dla innych formatów czasu datowego:
| Warto go | Typ programu SQL Server | Kiedy stosować |
|---|---|---|
time.Time |
datetimeoffset |
Domyślne. Używaj, gdy strefa czasowa ma znaczenie. |
mssql.DateTime1(t) |
datetime |
Kolumny dziedziczonego, które nie obsługują offsetu. |
mssql.DateTimeOffset(t) |
datetimeoffset |
Wyraźna kontrola offsetu. |
Najlepsze praktyki UTC
Czas przechowywania w UTC i konwersja na czas lokalny w warstwie aplikacji:
now := time.Now().UTC()
_, err := db.ExecContext(ctx,
"INSERT INTO Production.ScrapReason (Name, ModifiedDate) VALUES (@name, @modified)",
sql.Named("name", "Operator error"),
sql.Named("modified", now))
wzorce unikalnych identyfikatorów (GUID)
SQL Server przechowuje uniqueidentifier wartości z pierwszych trzech grup w kolejności bajtów little-endian (znanej również jako mieszany endian lub GUID w kolejności bajtów). Jeśli zeskanujesz kolumnę uniqueidentifier do []byte, surowe bajty nie odpowiadają standardowej reprezentacji ciągów znaków. Zamiast tego używaj mssql.UniqueIdentifier , który automatycznie obsługuje konwersję kolejności bajtów.
Skanuj za pomocą mssql. UniqueIdentifier
Domyślnie uniqueidentifier kolumny skanują do []byte. Zastosowanie mssql.UniqueIdentifier do formatowanych ciągów GUID:
var id mssql.UniqueIdentifier
err := db.QueryRowContext(ctx,
"SELECT rowguid FROM Production.Product WHERE Name = @name",
sql.Named("name", "Adjustable Race")).Scan(&id)
if err != nil {
log.Fatal(err)
}
fmt.Println("ID:", id) // "6F9619FF-8B86-D011-B42D-00C04FC964FF"
Generuj i wysyłaj GUIDy
Użyj NEWID() na serwerze lub generuj w Go:
// Server-side generation
var newID mssql.UniqueIdentifier
err := db.QueryRowContext(ctx,
"INSERT INTO Production.ProductCategory (Name) OUTPUT INSERTED.rowguid VALUES (@name)",
sql.Named("name", "Custom Parts")).Scan(&newID)
Generowanie po stronie klienta z pakietem google/uuid :
import "github.com/google/uuid"
id := mssql.UniqueIdentifier(uuid.New())
_, err := db.ExecContext(ctx,
"UPDATE Production.ProductCategory SET rowguid = @id WHERE Name = @name",
sql.Named("id", id),
sql.Named("name", "Custom Parts"))
Lista kontrolna mapowania typów
| Scenario | Zalecane podejście |
|---|---|
| Kolumny unieważniające | Użyj sql.NullStringtypów , sql.NullInt64, sql.NullFloat64, sql.NullBool, sql.NullTime, lub wskaźników. |
| Wartości finansowe/dziesiętne | Skanuj do string, użyj shopspring/decimal do arytmetyki. |
| Daty związane ze strefami czasowymi | Użyj time.Time (domyślnie mapuje na datetimeoffset ). |
| Starsze kolumny datetime | Używaj przy mssql.DateTime1 wysyłaniu parametrów. |
| Identyfikatory GUID | Skanuj z wyjściem mssql.UniqueIdentifier formatowanym. |
| Ciągi nie-Unicode | Używaj, mssql.VarChar by uniknąć ukrytej nvarchar konwersji. |
| Kolumny JSON | Skanuj do string, unmarshal z encoding/json. Zobacz dane JSON i XML. |
| Kolumny XML | Skanuj do string, unmarshal z encoding/xml. Zobacz dane JSON i XML. |