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.
GORM to popularny ORM dla Go, który obsługuje SQL Server za pośrednictwem dialektu gorm.io/driver/sqlserver, wewnętrznie korzystającego z go-mssqldb. GORM obsługuje różnice w schematach, generowanie zapytań i mapowanie typów, dzięki czemu możesz pracować ze strukturami Go zamiast pisać surowy SQL.
Ten artykuł omawia wzorce GORM specyficzne dla SQL Server. Dla ogólnego zastosowania GORM zobacz dokumentację GORM.
Przykłady w tym artykule porównane są z przykładową bazą danych AdventureWorks2025 .
Zainstaluj GORM i dialekt SQL Server
Stwórz lub otwórz moduł Go, a następnie dodaj GORM i dialekt SQL Server:
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
Nawiązywanie połączenia z programem SQL Server
Otwórz sesję GORM, przekazując do dialektu parametr DSN sqlserver://:
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")
}
Dialekt korzysta wewnętrznie ze sterownika go-mssqldb, więc wszystkie opcje połączenia z Parametry połączenia i Opcje połączenia mają zastosowanie do DSN.
Przypisz modele do istniejących tabel
Domyślna konwencja nazewnictwa w GORM używa nazw tabel pisanych małymi literami w liczbie mnogiej (na przykład products), co nie jest zgodne z konwencjami stosowanymi w SQL Server. Użyj TableName() metody do powiązania modelu z istniejącą tabelą kwalifikowaną przez schemat:
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"
}
Wskazówka
Zawsze określajTableName(), kiedy pracujesz z istniejącymi bazami SQL Server. Poleganie na automatycznym tworzeniu liczby mnogiej przez GORM powoduje błędy „invalid object name” w przypadku tabel zgodnych z konwencjami nazewnictwa SQL Server.
Wyszukaj dane
Po zdefiniowaniu modelu użyj metod zapytań GORM do odczytu danych:
Znajdź wiersze za pomocą klauzuli WHERE
Filtruj, sortuj i ograniczaj wyniki za pomocą Where, Order, oraz 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)
}
Pobierz pojedynczy wiersz
Użyj First z warunkiem ładowania jednego rekordu:
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)
Zlicz wiersze
Użyj Count w zakresie modelu, aby uzyskać liczbę wierszy:
var count int64
db.Model(&Product{}).Where("ListPrice > ?", 0).Count(&count)
fmt.Printf("Products with a list price: %d\n", count)
Wstawiaj, aktualizuj i usuwaj wiersze
Operacje zapisu wykorzystują te same struktury modelu. Przykłady w tej sekcji są skierowane na Production.ScrapReason, dzięki czemu nie modyfikują kluczowych tabel.
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"
}
Wstaw wiersz
Przekaż do Create strukturę z wypełnionymi polami, aby wstawić wiersz i uzupełnić automatycznie wygenerowany klucz podstawowy:
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)
Zaktualizuj wiersz
Użyj Model z Update, aby zmienić wartość kolumny:
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)
Usuwanie wiersza
Przekaż strukturę z zasiedlonym kluczem głównym do 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)
Wstawka wsadowa i limit 2100 parametrów
SQL Server ogranicza liczbę parametrów w instrukcji sp_executesql do 2 100. Wstawka wsadowa w GORM generuje klauzulę wielowierszową VALUES , gdzie każda kolumna zajmuje jeden parametr, więc tabela z 10 kolumnami osiąga limit około 210 wierszy na partię.
Ustaw CreateBatchSize dla tej sesji, aby pozostać w limicie:
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)
}
Dla tabel z wieloma kolumnami proporcjonalnie zmniejszaj rozmiar partii. Bezpieczna formuła: batch size = floor(2100 / number of inserted columns).
Transactions
Opakuj wiele operacji w transakcji GORM:
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")
Jeśli callback zwraca błąd, GORM automatycznie wycofuje transakcję.
Awaryjne użycie surowego SQL
Gdy kreator zapytań GORM nie generuje potrzebnej składni SQL Server, przejdź do surowego SQL, nadal korzystając z sesji GORM:
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)
}
Surowe zapytania korzystają z tej samej puli połączeń zarządzanej przez GORM, więc ustawienia puli z db.DB() nadal mają zastosowanie.
Konfiguruj pulę połączeń
Uzyskaj dostęp do bazowego elementu *sql.DB, aby ustawić parametry puli:
sqlDB, err := db.DB()
if err != nil {
log.Fatal(err)
}
sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(5 * time.Minute)
Wskazówki dotyczące określania rozmiaru puli można znaleźć w sekcji Buforowanie połączeń.
Rozważania dotyczące AutoMigrate
AutoMigrate Tworzy lub modyfikuje tabele, aby pasowały do definicji modelu. Działa z SQL Server, ale zwróć uwagę na następujące zachowania:
-
AutoMigratetworzy tabele w domyślnym schemacie (dbo), chyba że poprzedziszTableName()prefiksem schematu. - Dodaje brakujące kolumny i tworzy indeksy, ale nie usuwa kolumn ani nie zmienia istniejących typów kolumn.
- SQL Server ma limit 128 znaków na nazwy indeksów. Generowane przez GORM nazwy indeksów mogą przekraczać ten limit dla tabel o długich nazwach lub indeksów złożonych. Używaj tagów jawnych
gorm:"index:idx_short_name", jeśli osiągniesz ten limit.
W przypadku baz produkcyjnych z zarządzanymi schematami preferuj narzędzia migracji zamiast AutoMigrate.