Migrace na go-mssqldb z jiných ovladačů

Tento průvodce pomáhá vývojářům Go migrovat z PostgreSQL, MySQL a dalších ovladačů databáze na go-mssqldb SQL Server. Zahrnuje rozdíly v syntaxi SQL, změny specifické pro ovladače a ekvivalentní vzory pro běžné operace.

Note

Příklady v tomto článku jsou porovnány s databází AdventureWorks2025 .

Proč migrovat na SQL Server s go-mssqldb

funkce SQL Server pro go-mssqldb
Zabezpečení podniku Vždy šifrováno, bezpečnost na úrovni řádků, dynamické maskování dat, transparentní šifrování dat (TDE).
Autentizace Microsoft Entra ID (dříve Azure AD), managed identity, Windows authentication, Kerberos.
integrace Azure Nativní podpora Azure SQL Database s automatickým šifrováním, bezheslovými připojeními a řešením failoveru.
Performance Sloupcové indexy, OLTP v paměti, úložiště dotazů pro automatické opravy plánu.
Formáty dat Vestavěná podpora JSON a XML s indexováním a dotazováním na straně serveru.
Tooling SQL Server Management Studio (SSMS), Azure Data Studio, Visual Studio Code SQL extensions.

Kontrolní seznam pro migraci

Předtím, než začnete přenášet dotazy řádek po řádku, projděte si tyto položky:

Consideration Co změnit
Syntax zástupných symbolů se liší od syntaxe používané v mnoha ovladačích Go. Nahraďte ?, $1 a podobné zástupné symboly prvky @name nebo @p1 a poté předejte argumenty sql.Named(), kde je to vhodné.
LastInsertId() není podporováno. Použijte OUTPUT INSERTED.<column> nebo SELECT SCOPE_IDENTITY() místo toho.
Hodnoty Go string se ve výchozím nastavení mapují na typy Unicode. Očekávejte nvarchar sémantiku, pokud si nevyberete typ specifický pro ovladač, například mssql.VarChar pro data mimo Unicode.
Dočasné tabulky mají rozsah omezený na fyzické připojení. Logiku vytváření a používání dočasné tabulky zachovejte ve stejném připojení nebo v rámci stejné transakce, pokud na ní závisejí následné příkazy.
Autentizace Microsoft Entra používá jinou registraci ovladače. Importujte github.com/microsoft/go-mssqldb/azuread, použijte sql.Open("azuresql", ...) a explicitně nastavte možnosti TLS pro Azure SQL pomocí encrypt=true&TrustServerCertificate=false.

Pro podrobnější informace v těchto oblastech viz Dotazy a příkazy, Omezení, mapování datových typů, autentizace Microsoft Entra ID a Řešení problémů.

Migrace z lib/pq (PostgreSQL)

Změňte import a název ovladače

Nahraďte lib/pq import a název ovladače za go-mssqldb.

import _ "github.com/lib/pq"
db, err := sql.Open("postgres", connString)

// After (SQL Server with go-mssqldb):
import _ "github.com/microsoft/go-mssqldb"
db, err := sql.Open("sqlserver", connString)

Změňte formát připojovacího řetězce

Převeďte formát klíč–hodnota databáze PostgreSQL na adresu URL serveru SQL Server:

// lib/pq connection string:
"host=<server> port=5432 user=<user> password=<password> dbname=AdventureWorks2025 sslmode=require"

// go-mssqldb connection string:
"sqlserver://<user>:<password>@<server>:1433?database=AdventureWorks2025&encrypt=true"

Změň zástupce parametrů

PostgreSQL používá poziční zástupné symboly $1, $2. SQL Server používá pojmenované parametry s @:

// PostgreSQL (lib/pq):
db.QueryContext(ctx, "SELECT * FROM users WHERE id = $1 AND status = $2", id, status)

// SQL Server (go-mssqldb):
db.QueryContext(ctx, "SELECT ProductID, Name FROM Production.Product WHERE ProductID = @id AND Color = @color",
    sql.Named("id", id),
    sql.Named("color", color))

Změny syntaxe SQL

Operation PostgreSQL SQL Server
Automatické zvyšování SERIAL nebo GENERATED ALWAYS AS IDENTITY IDENTITY(1,1)
Vložte ID RETURNING id OUTPUT INSERTED.id nebo SELECT SCOPE_IDENTITY()
Booleovský (logický) typ BOOLEAN BIT
Zřetězení řetězců \|\| + nebo CONCAT()
Aktuální časové razítko NOW() nebo CURRENT_TIMESTAMP GETUTCDATE() nebo SYSDATETIMEOFFSET()
Omezit počet řádků LIMIT 10 OFFSET 20 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Typ řetězce TEXT nebo VARCHAR NVARCHAR(MAX) nebo NVARCHAR(n)
Extrakce JSON column->>'key' JSON_VALUE(column, '$.key')
Upsert INSERT ... ON CONFLICT DO UPDATE Prohlášení MERGE
Typ pole INTEGER[] Žádná nativní pole. Používejte parametry s tabulkovými hodnotami.
Citlivost na velikost písmen Výchozí rozlišení na velká písmena Výchozí nastavení není citlivé na velká písmena (záleží na třídění).

Získejte ID vloženého záznamu

Nahraďte klauzuli PostgreSQL RETURNING klauzulí SQL Serveru OUTPUT:

var id int
err := db.QueryRowContext(ctx,
    "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id",
    name, email).Scan(&id)

// SQL Server (go-mssqldb) using OUTPUT:
var id int
err := db.QueryRowContext(ctx,
    "INSERT INTO HumanResources.Department (Name, GroupName) OUTPUT INSERTED.DepartmentID VALUES (@name, @groupName)",
    sql.Named("name", name),
    sql.Named("groupName", groupName)).Scan(&id)

Pagination

Nahraďte syntaxi LIMIT/OFFSET syntaxí OFFSET/FETCH NEXT.

// PostgreSQL:
"SELECT * FROM employees ORDER BY id LIMIT $1 OFFSET $2"

// SQL Server (requires ORDER BY):
"SELECT ProductID, Name, ListPrice FROM Production.Product ORDER BY ProductID OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY"

Migrace z pgx (PostgreSQL)

Ovladač pgx používá vlastní skupinu připojení a API, které se liší od database/sql. Pro migraci přepněte na standardní database/sql rozhraní.

Přechod z pgx poolu na databázové/sql

Nahraďte pgxpool API standardním database/sql rozhraním.

// Before (pgx):
import "github.com/jackc/pgx/v5/pgxpool"
pool, err := pgxpool.New(ctx, "postgres://user:pass@<server>:5432/AdventureWorks2025")
defer pool.Close()
rows, err := pool.Query(ctx, "SELECT * FROM users WHERE id = $1", id)

// After (go-mssqldb with database/sql):
import (
    "database/sql"
    _ "github.com/microsoft/go-mssqldb"
)
db, err := sql.Open("sqlserver", "sqlserver://user:pass@<server>:1433?database=AdventureWorks2025")
defer db.Close()
rows, err := db.QueryContext(ctx,
    "SELECT ProductID, Name FROM Production.Product WHERE ProductID = @id", sql.Named("id", id))

Nahraďte funkce specifické pro pgx

Funkce PGX Go-mssqldb ekvivalent
pgx.CollectRows Ruční rows.Next() a rows.Scan() smyčka.
pgx.RowToStructByName Ručně rows.Scan do členů struktury.
Dávkové dotazy (pgx.Batch) Vícenásobná volání ExecContext nebo uložené procedury.
COPY FROM pro hromadné vložení mssql.CopyIn pro hromadné vkládání.
pgx.ConnConfig msdsn.Config nebo řetězce spojení založené na URL.
pgxpool.Pool sql.DB s SetMaxOpenConns a SetMaxIdleConns.

Přechod z go-sql-driver/mysql (MySQL)

Vyměňte import a název ovladače MySQL

Nahraďte import a název ovladače do MySQL za go-mssqldb.

// Before (MySQL):
import _ "github.com/go-sql-driver/mysql"
db, err := sql.Open("mysql", connString)

// After (SQL Server):
import _ "github.com/microsoft/go-mssqldb"
db, err := sql.Open("sqlserver", connString)

Převod formátu MySQL DSN

Převeďte formát MySQL DSN na URL SQL Server.

// MySQL DSN:
"user:password@tcp(<server>:3306)/AdventureWorks2025?tls=true"

// go-mssqldb URL:
"sqlserver://user:password@<server>:1433?database=AdventureWorks2025&encrypt=true"

Nahraďte zástupné symboly otazníku

MySQL používá ? poziční zástupné symboly.

// MySQL:
db.QueryContext(ctx, "SELECT * FROM users WHERE id = ? AND status = ?", id, status)

// SQL Server:
db.QueryContext(ctx, "SELECT ProductID, Name FROM Production.Product WHERE ProductID = @id AND Color = @color",
    sql.Named("id", id),
    sql.Named("color", color))

Porovnejte syntaxi MySQL a SQL Server

Operation MySQL SQL Server
Automatické zvyšování AUTO_INCREMENT IDENTITY(1,1)
Vložte ID LAST_INSERT_ID() SCOPE_IDENTITY() nebo OUTPUT INSERTED.id
Omezit počet řádků LIMIT 10 OFFSET 20 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Aktuální časové razítko NOW() GETUTCDATE()
Pokud nulová IFNULL(expr, default) ISNULL(expr, default) nebo COALESCE(expr, default)
Délka řetězce LENGTH(str) LEN(str)
Podřetězec SUBSTRING(str, start, len) SUBSTRING(str, start, len) (stejné)
Formát dat DATE_FORMAT(d, '%Y-%m-%d') FORMAT(d, 'yyyy-MM-dd') nebo CONVERT(VARCHAR, d, 23)
Upsert INSERT ... ON DUPLICATE KEY UPDATE Prohlášení MERGE
Backtick citace `column` [column]

Nahraďte syntaxi specifickou pro MySQL

Syntaxe MySQL Ekvivalent pro SQL Server
AUTO_INCREMENT IDENTITY(1,1)
LIMIT n OFFSET m OFFSET m ROWS FETCH NEXT n ROWS ONLY (vyžaduje ORDER BY)

AUTO_INCREMENT do IDENTITY:

-- MySQL:
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

-- SQL Server:
CREATE TABLE HumanResources.NewDepartment (
    DepartmentID SMALLINT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(50) NOT NULL
);

LIMIT to OFFSET/FETCH:

-- MySQL:
SELECT * FROM users LIMIT 10 OFFSET 20;

-- SQL Server:
SELECT ProductID, Name, ListPrice
FROM Production.Product
ORDER BY ProductID
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

Běžné vzory migrace

Získejte poslední vloženou identitu

Použijte klauzuli OUTPUT nebo SCOPE_IDENTITY() k získání identity vloženého řádku:

// Pattern 1: OUTPUT clause (recommended, works with batch inserts).
var id int64
err := db.QueryRowContext(ctx,
    "INSERT INTO HumanResources.Department (Name, GroupName) OUTPUT INSERTED.DepartmentID VALUES (@name, @groupName)",
    sql.Named("name", "Engineering"),
    sql.Named("groupName", "Research and Development")).Scan(&id)

// Pattern 2: SCOPE_IDENTITY (works with single-row inserts).
var id int64
err := db.QueryRowContext(ctx,
    "INSERT INTO HumanResources.Department (Name, GroupName) VALUES (@name, @groupName); SELECT SCOPE_IDENTITY()",
    sql.Named("name", "Engineering"),
    sql.Named("groupName", "Research and Development")).Scan(&id)

Tip

Upřednostňujeme klauzuli OUTPUT před SCOPE_IDENTITY(). Doložka OUTPUT funguje s dávkovým vkládáním a nezávisí na pořadí příkazů.

Upsert (vložit nebo aktualizovat záznam)

PostgreSQL ON CONFLICT a MySQL ON DUPLICATE KEY UPDATE odpovídají v SQL Serveru MERGE:

_, err := db.ExecContext(ctx, `
    MERGE HumanResources.Department AS target
    USING (SELECT @id AS DepartmentID, @name AS Name, @groupName AS GroupName) AS source
    ON target.DepartmentID = source.DepartmentID
    WHEN MATCHED THEN
        UPDATE SET Name = source.Name, GroupName = source.GroupName, ModifiedDate = GETDATE()
    WHEN NOT MATCHED THEN
        INSERT (Name, GroupName, ModifiedDate) VALUES (source.Name, source.GroupName, GETDATE());`,
    sql.Named("id", dept.ID),
    sql.Named("name", dept.Name),
    sql.Named("groupName", dept.GroupName))

Hromadné vložení

Nahraďte PostgreSQL COPY nebo MySQL LOAD DATA za mssql.CopyIn.

import mssql "github.com/microsoft/go-mssqldb"

stmt, err := db.Prepare(mssql.CopyIn("HumanResources.Department", mssql.BulkOptions{}, "Name", "GroupName", "ModifiedDate"))
if err != nil {
    return err
}

for _, dept := range departments {
    _, err = stmt.Exec(dept.Name, dept.GroupName, time.Now())
    if err != nil {
        return err
    }
}

// Flush the buffer.
_, err = stmt.Exec()
if err != nil {
    return err
}
stmt.Close()

Zpracovat hodnoty NULL

Všechny ovladače databáze Go zpracovávají hodnoty NULL stejným způsobem, protože používají typy database/sql .

var color sql.NullString
err := db.QueryRowContext(ctx,
    "SELECT Color FROM Production.Product WHERE ProductID = @id",
    sql.Named("id", 1)).Scan(&color)

if color.Valid {
    fmt.Println(color.String)
} else {
    fmt.Println("NULL")
}

Transactions

Všechny ovladače databáze Go používají stejné database/sql transakční API.

tx, err := db.BeginTx(ctx, nil)
if err != nil {
    return err
}
defer tx.Rollback()

_, err = tx.ExecContext(ctx,
    "UPDATE Production.ProductInventory SET Quantity = Quantity - @qty WHERE ProductID = @pid AND LocationID = @fromLoc",
    sql.Named("qty", qty),
    sql.Named("pid", productID),
    sql.Named("fromLoc", fromLocationID))
if err != nil {
    return err
}

_, err = tx.ExecContext(ctx,
    "UPDATE Production.ProductInventory SET Quantity = Quantity + @qty WHERE ProductID = @pid AND LocationID = @toLoc",
    sql.Named("qty", qty),
    sql.Named("pid", productID),
    sql.Named("toLoc", toLocationID))
if err != nil {
    return err
}

return tx.Commit()

Kontrolní seznam pro migraci

Krok Action
Instalace ovladače go get github.com/microsoft/go-mssqldb
Změnit importy Nahraďte starý import ovladačů za _ "github.com/microsoft/go-mssqldb".
Aktualizujte připojovací řetězce Změna formátu URL na SQL Server: sqlserver://user:pass@host?database=db.
Nahraďte zástupce parametrů Změňte $1/$2 nebo ? na @name pomocí sql.Named.
Aktualizovat syntaxi SQL Změňte LIMIT/OFFSET, RETURNING, NOW(), SERIAL a další SQL specifické pro danou databázi.
Nahrazení hromadných operací Změň COPY nebo LOAD DATA na mssql.CopyIn.
Aktualizace schématu DDL Změňte SERIAL/AUTO_INCREMENT na IDENTITY, TEXT na NVARCHAR, BOOLEAN na .BIT
Otestujte všechny dotazy Spusť testovací sadu na instanci SQL Server, abys zachytil rozdíly v syntaxi.
Konfigurace šifrování Přidejte encrypt=true (nebo se spolehněte na automatické rozpoznání Azure) pro produkční nasazení.
Nastavení ověřování Konfigurujte Microsoft Entra ID pro Azure nebo SQL Server autentizaci pro on-premises.