Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
GORM är en populär Go-ORM som stöder SQL Server via dialekten gorm.io/driver/sqlserver, som internt använder go-mssqldb. GORM hanterar schema-skillnader, frågegenerering och typmappning så att du kan arbeta med Go-structs istället för att skriva rå SQL.
Den här artikeln behandlar GORM-mönster som är specifika för SQL Server. För allmän användning av GORM, se GORM-dokumentationen.
Exempel i denna artikel körs mot AdventureWorks2025 :s exempeldatabas.
Installera GORM och SQL Server-dialekten
Skapa eller öppna en Go-modul, lägg sedan till GORM och SQL Server-dialekten:
mkdir go-gorm-sqlserver
cd go-gorm-sqlserver
go mod init example.com/go-gorm-sqlserver
go get gorm.io/gorm
go get gorm.io/driver/sqlserver
Ansluta till SQL Server
Öppna en GORM-session genom att skicka ett sqlserver:// DSN till dialekten:
package main
import (
"fmt"
"log"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
func main() {
// Replace <server>, <user>, and <password> with your own values.
// In production, load credentials from environment variables or a secret store.
dsn := "sqlserver://<user>:<password>@<server>.database.windows.net:1433?database=AdventureWorks2025&encrypt=true&TrustServerCertificate=false"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
sqlDB, err := db.DB()
if err != nil {
log.Fatal(err)
}
defer sqlDB.Close()
fmt.Println("Connected to SQL Server with GORM")
}
Dialekten använder drivrutinen go-mssqldb i bakgrunden, så alla anslutningsalternativ från Anslutningssträngar och Anslutningsalternativ gäller även för DSN:en.
Kartmodeller till befintliga tabeller
GORM:s standardnamngivningskonvention använder små plural tabellnamn (till exempel products), vilket inte stämmer överens med SQL Server-konventionerna. Använd TableName() metoden för att binda en modell till en befintlig schema-kvalificerad tabell:
type Product struct {
ProductID int32 `gorm:"column:ProductID;primaryKey"`
Name string `gorm:"column:Name"`
ProductLine *string `gorm:"column:ProductLine"`
ListPrice float64 `gorm:"column:ListPrice"`
}
func (Product) TableName() string {
return "Production.Product"
}
Tip
Definiera TableName() alltid när du arbetar med befintliga SQL Server-databaser. Att förlita sig på GORM:s automatiska pluralisering leder till fel av typen ”ogiltigt objektnamn” för tabeller som följer SQL Servers namngivningskonventioner.
Fråga efter data
Efter att du definierat en modell, använd GORM:s frågemetoder för att läsa data:
Hitta rader med en WHERE-klausul
Filtrera, sortera och begränsa resultat med hjälp av Where, Order, och Limit:
var products []Product
result := db.Where("ListPrice > ?", 1000).
Order("ListPrice DESC").
Limit(5).
Find(&products)
if result.Error != nil {
log.Fatal(result.Error)
}
for _, p := range products {
fmt.Printf("%-35s $%.2f\n", p.Name, p.ListPrice)
}
Hämta en enda rad
Använd First med ett villkor för att ladda en post:
var product Product
if err := db.First(&product, "ProductID = ?", 680).Error; err != nil {
log.Fatal(err)
}
fmt.Printf("%s: $%.2f\n", product.Name, product.ListPrice)
Antal rader
Använd Count på modellens scope för att få antalet rader:
var count int64
db.Model(&Product{}).Where("ListPrice > ?", 0).Count(&count)
fmt.Printf("Products with a list price: %d\n", count)
Lägg till, uppdatera och ta bort rader
Skrivoperationer använder samma modellstrukturer. Exemplen i det här avsnittet är inriktade på Production.ScrapReason så att de inte påverkar kritiska tabeller.
type ScrapReason struct {
ScrapReasonID int16 `gorm:"column:ScrapReasonID;primaryKey;autoIncrement"`
Name string `gorm:"column:Name"`
ModifiedDate time.Time `gorm:"column:ModifiedDate"`
}
func (ScrapReason) TableName() string {
return "Production.ScrapReason"
}
Lägg in en rad
Skicka en ifylld struktur till Create för att infoga en rad och fyll i den automatiskt genererade primärnyckeln:
reason := ScrapReason{Name: "GORM test scrap", ModifiedDate: time.Now()}
if err := db.Create(&reason).Error; err != nil {
log.Fatal(err)
}
fmt.Printf("Inserted ScrapReasonID: %d\n", reason.ScrapReasonID)
// Clean up
db.Delete(&reason)
Uppdatera en rad
Använd Model med Update för att ändra ett kolumnvärde:
reason := ScrapReason{Name: "GORM update test", ModifiedDate: time.Now()}
db.Create(&reason)
db.Model(&reason).Update("Name", "GORM updated scrap")
var updated ScrapReason
db.First(&updated, reason.ScrapReasonID)
fmt.Printf("Updated name: %s\n", updated.Name)
// Clean up
db.Delete(&reason)
Ta bort en rad
Skicka en struktur med en befolkad primärnyckel till Delete:
reason := ScrapReason{Name: "GORM delete test", ModifiedDate: time.Now()}
db.Create(&reason)
id := reason.ScrapReasonID
db.Delete(&reason)
var count int64
db.Model(&ScrapReason{}).Where("ScrapReasonID = ?", id).Count(&count)
fmt.Printf("Rows remaining with that ID: %d\n", count)
Satsvis infogning och gränsen på 2 100 parametrar
SQL Server begränsar sp_executesql till 2 100 parametrar per sats. GORM:s batchinsats genererar en flerradsklausul VALUES där varje kolumn använder en parameter, så en tabell med 10 kolumner når gränsen vid ungefär 210 rader per batch.
Ange CreateBatchSize för sessionen för att hålla dig inom gränsen:
reasons := make([]ScrapReason, 50)
for i := range reasons {
reasons[i] = ScrapReason{
Name: fmt.Sprintf("Batch scrap %d", i+1),
ModifiedDate: time.Now(),
}
}
// 2 inserted columns per row (Name, ModifiedDate; the autoIncrement ID is excluded),
// so batches of 500 are well within the 2,100-parameter limit.
result := db.CreateInBatches(&reasons, 500)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Printf("Inserted %d rows in batches\n", result.RowsAffected)
// Clean up
for _, r := range reasons {
db.Delete(&r)
}
För tabeller med många kolumner, minska batchstorleken proportionellt. En säker formel: batch size = floor(2100 / number of inserted columns).
Transactions
Omslut flera operationer i en GORM-transaktion:
err := db.Transaction(func(tx *gorm.DB) error {
r1 := ScrapReason{Name: "TX scrap 1", ModifiedDate: time.Now()}
if err := tx.Create(&r1).Error; err != nil {
return err
}
r2 := ScrapReason{Name: "TX scrap 2", ModifiedDate: time.Now()}
if err := tx.Create(&r2).Error; err != nil {
return err
}
// Both inserts commit together.
fmt.Printf("Inserted IDs: %d, %d\n", r1.ScrapReasonID, r2.ScrapReasonID)
// Clean up inside the same transaction.
tx.Delete(&r1)
tx.Delete(&r2)
return nil
})
if err != nil {
log.Fatal(err)
}
fmt.Println("Transaction committed")
Om callbacken returnerar ett felmeddelande rullas GORM automatiskt tillbaka.
Rå SQL-reservlösning
När GORM:s frågebyggare inte genererar den SQL Server-syntax du behöver, gå över till rå SQL medan du fortfarande använder GORM-sessionen:
var results []struct {
Name string
ListPrice float64
}
result := db.Raw("SELECT TOP 5 Name, ListPrice FROM Production.Product WHERE ListPrice > @price ORDER BY ListPrice DESC",
sql.Named("price", 1000)).Scan(&results)
if result.Error != nil {
log.Fatal(result.Error)
}
for _, r := range results {
fmt.Printf("%-35s $%.2f\n", r.Name, r.ListPrice)
}
Råa frågor använder samma anslutningspool som hanteras av GORM, så poolinställningarna från db.DB() gäller fortfarande.
Konfigurera anslutningspoolen
Åtkomst till underliggande *sql.DB för att sätta poolparametrar:
sqlDB, err := db.DB()
if err != nil {
log.Fatal(err)
}
sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(5 * time.Minute)
För information om dimensionering av pooler, se Anslutningspooler.
Överväganden för AutoMigrate
AutoMigrate skapar eller ändrar tabeller för att matcha dina modelldefinitioner. Det fungerar med SQL Server, men var medveten om dessa beteenden:
-
AutoMigrateskapar tabeller i standardschemat (dbo) om du inte åsidosätterTableName()med ett schemaprefix. - Den lägger till saknade kolumner och skapar index men tar inte bort kolumner eller ändrar befintliga kolumntyper.
- SQL Server har en gräns på 128 tecken för indexnamn. GORM:s genererade indexnamn kan överstiga denna gräns på tabeller med långa namn eller sammansatta index. Använd explicita taggar
gorm:"index:idx_short_name"om du når denna gräns.
För produktionsdatabaser med hanterade scheman föredrar du migreringsverktyg framför AutoMigrate.