Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der Treiber go-mssqldb wandelt Go-Typen automatisch in SQL Server-Typen um, wenn man Parameter übergibt, und wandelt SQL Server-Typen beim Scannen der Ergebnisse wieder in Go-Typen um. Dieser Artikel dokumentiert die Standard-Konvertierungen und die treiberspezifischen Typen, die explizit gesteuert werden können.
Beispiele in diesem Artikel laufen gegen die AdventureWorks2025-Beispieldatenbank . Leseorientierte Beispiele fragen eingebaute Objekte wie Production.Product und Sales.vSalesPersonab. Schreiborientierte Beispiele zielen HumanResources.Department auf und Production.ProductCategory.
Gehe zu SQL Server Parameterabbildungen
Wenn Sie Werte als Abfrageparameter übergeben, wandelt der Treiber Go-Typen in SQL Server-Typen um:
| Go-Type | SQL Server-Typ | Hinweise |
|---|---|---|
string |
nvarchar | Unicode-Zeichenkette. Verwendung mssql.VarChar für nicht-Unicode-Varchar. |
[]byte |
varbinary | Binäre Daten. |
int64 |
bigint | |
float64 |
float | 64-Bit-Float. |
bool |
Bit | |
time.Time |
datetimeoffset | Bewahrt die Zeitzonenverschiebung. Nutze mssql.DateTime1 sie für das Date-Time.
mssql.DateTimeOffset Verwendung für explizite Offset-Kontrolle. |
int32 |
int | |
int16 |
smallint | |
int8 |
tinyint | |
float32 |
real | 32-Bit-Float. |
mssql.TVP |
tabellenwertiger Parameter | Siehe Tabellenwerte Parameter. |
Fahrerspezifische Typen
Verwenden Sie diese Typen aus dem mssql Paket, wenn Sie explizite Kontrolle über den SQL Server-Typ benötigen:
| Treibertyp | SQL Server-Typ | Beschreibung |
|---|---|---|
mssql.VarChar |
varchar | Kein Unicode-String. Wickle einen string Wert ein. |
mssql.NVarCharMax |
nvarchar(max) | Unicode-Zeichenkette. |
mssql.VarCharMax |
varchar(max) | Nicht Unicode-große Zeichenkette. |
mssql.NChar |
nchar | Unicode-String mit fester Länge. Wickle einen string Wert ein. |
mssql.DateTime1 |
datetime | Legacy-Datumszeit ohne Offset. |
mssql.DateTimeOffset |
datetimeoffset | Explizite Offset-Kontrolle. |
mssql.NullDate |
date | Nullierbarer, nur datierter Wert. |
mssql.NullTime |
Zeit | Nullierbarer Zeit-Only-Wert. |
mssql.NullDateTime |
datetime2 | Nullierbarer Datums- und Zeitwert ohne Zeitzonenumrechnung. |
mssql.UniqueIdentifier |
uniqueidentifier | GUID-Wert. |
mssql.TVP |
Benutzerdefinierter Tabellentyp | Tabellenwertige Parameterstruktur. |
Verwenden Sie die nullablen Datums- und Uhrzeit-Helfertypen, wenn Sie SQL Server nur Datum- oder Zeit-Semantik benötigen und der Parameter oder das Scan-Ziel möglicherweise NULL ist.
Beispiel: Varchar vs. Nvarchar
Standardmäßig string werden die Parameter als nvarchargesendet. Stattdessen verwenden 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"))
Beispiel: Uniqueidentifier
Verwenden Sie den Typ mssql.UniqueIdentifier , um Spalten zu scannen uniqueidentifier :
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)
SQL Server to Go Ergebniszuordnungen
Wenn Sie die Ergebnisse abfragen, wandelt der Treiber SQL Server-Typen in Go-Typen um:
| SQL Server-Typ | Go-Type | Hinweise |
|---|---|---|
| int, bigint, smallint, tinyint | int64 |
Alle ganzzahligen Typen scannen nach int64. Zaubern Sie nach Bedarf. |
| schweben, echt | float64 |
|
| Dezimal-, Numerisch-, Geld-, Kleingeld-, |
[]byte oder string |
Kein nativer Go-Dezimaltyp. Scannen Sie in string oder verwenden Sie eine Dezimalbibliothek von Drittanbietern. |
| Bit | bool |
|
| Char, Varchar, Text | string |
|
| nchar, nvarchar, ntext | string |
|
| Binär,Varbinär, Bild | []byte |
|
| Date, Datetime, Datetime2, Smalldatetime | time.Time |
|
| datetimeoffset | time.Time |
Zeitzonenversatz bleibt erhalten. |
| Zeit | time.Time |
Die Date-Komponente ist 0001-01-01. |
| uniqueidentifier |
[]byte oder mssql.UniqueIdentifier |
Scannt standardmäßig auf Rohbytes.
mssql.UniqueIdentifier Verwendung für formatierte GUID-Ausgaben. |
| sql_variant | interface{} |
Der konkrete Go-Typ hängt vom gespeicherten Wert des SQL Server ab. |
| xml | string |
Benannte Parameter
Verwenden sql.Named Sie, um benannte Parameter zu erstellen:
rows, err := db.QueryContext(ctx,
"SELECT * FROM Sales.vSalesPerson WHERE CountryRegionName = @location AND FirstName = @name",
sql.Named("location", "Australia"),
sql.Named("name", "Jared"))
Hinweis
Positionsparameter (@p1, @p2) funktionieren ebenfalls. Der Treiber weist Ordinalnamen basierend auf der Reihenfolge der Argumente zu.
Handle NULL-Werte
SQL Server-Spalten, die NULL erlauben, erfordern eine spezielle Behandlung in Go. Das Standardpaket database/sql stellt für diesen Zweck nullbare Typen bereit.
SQL. Nulltypen
Verwenden sql.NullStringSie , sql.NullInt64, sql.NullFloat64, sql.NullBool, und sql.NullTime um Spalten zu handhaben, die NULL sein können. Für SQL Server Datum-, Uhrzeit- und Datumzeit2-Werte, die Sie von Gos time.Time Standardwerten getrennt halten möchten, verwenden mssql.NullDateSie , mssql.NullTime, und 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)
}
Pointerbasierte NULL-Handhabung
Verwenden Sie als Alternative zu sql.Null Typen Zeiger. Ein nil Zeiger repräsentiert 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")
}
Tip
Die zeigerbasierte NULL-Behandlung ist prägnanter, aber sql.Null die Typen machen die NULL-Absicht in Strukturdefinitionen expliziter. Wählen Sie das Muster, das Ihr Team bevorzugt, und verwenden Sie es konsequent.
Senden Sie NULL-Werte als Parameter
Pass, nil um einen NULL-Wert als Parameter zu senden:
// Insert a row with a NULL Color.
_, err := db.ExecContext(ctx,
"INSERT INTO Production.ProductCategory (Name) VALUES (@name)",
sql.Named("name", "Custom Parts"))
Dezimal- und numerische Genauigkeit
SQL Server decimal und numeric -Typen unterstützen eine Präzision von bis zu 38 Ziffern. Go's float64 liefert nur etwa 15–16 signifikante Ziffern. Das Scannen hochpräziser Werte verursacht float64 einen stillen Präzisionsverlust.
Scannen auf die Saite
Der sicherste und einfachste Ansatz ist es, Spalten in zu scannendecimal/numeric/money/smallmoney, und dann mit einer präzisionssicheren Bibliothek zu konvertieren:string
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"
Für leistungsempfindliche Pfade kannst du direkt in []byte deine Dezimalbibliothek einscannen und diese parsen, um die Zuweisung von Strings zu reduzieren.
Verwenden Sie shopspring/dezimal für die Arithmetik
Die Bibliothek shopspring/decimal bietet dezimale Arithmetik mit beliebiger Genauigkeit:
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))
Achtung
Scanne money oder decimal spalte niemals in float64 den Punkt, an dem genaue Genauigkeit wichtig ist (Finanzberechnungen, Währung, Steuern). Verwenden Sie das exakt-Wert-Scannen (string oder []byte) mit shopspring/decimal oder cockroachdb/apd stattdessen.
Senden Sie Dezimalwerte als Parameter
Beim Senden von Dezimalwerten als Parameter verwenden string Sie, um einen Verlust der Float-Präzision zu vermeiden:
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.
Datums- und Uhrzeittypen
Zeit. Zeitabbildung
Der Fahrer ordnet Go's standardmäßig zutime.Time, wodurch der Zeitzonen-Offset datetimeoffset erhalten bleibt. Verwenden Sie treiberspezifische Typen für andere Date-Time-Formate:
| Go-Wert | SQL Server-Typ | Wann verwenden? |
|---|---|---|
time.Time |
datetimeoffset |
Standard. Benutze sie, wenn die Zeitzone wichtig ist. |
mssql.DateTime1(t) |
datetime |
Legacy-Kolumnen, die keinen Offset unterstützen. |
mssql.DateTimeOffset(t) |
datetimeoffset |
Explizite Offset-Kontrolle. |
UTC Best Practice
Speichern der Zeiten in UTC und in der Anwendungsschicht in lokale Zeit umwandeln:
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))
Uniqueidentifier (GUID) Muster
SQL Server speichert uniqueidentifier Werte mit den ersten drei Gruppen in Little-Endian-Byte-Reihenfolge (auch bekannt als mixed-Endian- oder GUID-Byte-Ordnung). Wenn du eine Spalte uniqueidentifier in []bytescannst, stimmen die Rohbytes nicht mit der Standard-String-Darstellung überein.
mssql.UniqueIdentifier Use instead, das die Byte-Order-Umwandlung automatisch übernimmt.
Scanne mit mssql. UniqueIdentifier
Standardmäßig uniqueidentifier scannen die Spalten auf []byte. Verwendung mssql.UniqueIdentifier für formatierte GUID-Zeichenfolgen:
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"
Erstellen und senden Sie GUIDs
Auf dem Server verwenden NEWID() oder in Go generieren:
// 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)
Client-seitige Generierung mit dem google/uuid Paket:
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"))
Checkliste zur Typabbildung
| Szenario | Empfohlener Ansatz |
|---|---|
| Nullierbare Spalten | Verwenden sql.NullStringSie , sql.NullInt64, sql.NullFloat64, , sql.NullBool, sql.NullTime, oder Zeigertypen. |
| Finanzielle/dezimale Werte | Scanne zu, stringverwenden shopspring/decimal Sie für die Rechentechnik. |
| Daten mit Zeitzonen | Verwenden time.Time (standardmäßig zugeordnet datetimeoffset ). |
| Legacy-Datumszeit-Spalten | Verwenden mssql.DateTime1 Sie beim Senden von Parametern. |
| GUIDs | Scanne mit mssql.UniqueIdentifier für formatierte Ausgaben. |
| Nicht-Unicode-Zeichenketten | Nutze sie, mssql.VarChar um implizite nvarchar Umwandlung zu vermeiden. |
| JSON-Spalten | Scanne auf string, unmarshal mit encoding/json. Siehe JSON- und XML-Daten. |
| XML-Spalten | Scanne auf string, unmarshal mit encoding/xml. Siehe JSON- und XML-Daten. |