Diğer sürücülerden go-mssqldb'ye geçiş

Bu rehber, Go geliştiricilerinin PostgreSQL, MySQL ve diğer veritabanı sürücülerinden go-mssqldb for SQL Server'a geçişlerine yardımcı olur. SQL sözdizimi farklılıklarını, sürücüye özgü değişiklikleri ve yaygın işlemler için eşdeğer kalıpları kapsar.

Uyarı

Bu makaledeki örnekler AdventureWorks2025 örnek veritabanıyla karşılaştırılıyor.

Neden go-mssqldb ile SQL Server'a geçiş yapılıyor

Özellik go-mssqldb ile SQL Server
Kurumsal güvenlik Her zaman şifreli, satır seviyesinde güvenlik, dinamik veri maskeleme, şeffaf veri şifreleme (TDE).
Authentication Microsoft Entra ID (eski adıyla Azure AD), managed identity, Windows authentication, Kerberos.
Azure tümleştirmesi Otomatik şifreleme, parolasız bağlantılar ve yük devretme işlemleriyle Azure SQL Veritabanı için yerel destek.
Performance Columnstore indeksleri, bellek içi OLTP, otomatik plan düzeltmesi için sorgu deposu.
Veri biçimleri Sunucu tarafı indeksleme ve sorgulama ile yerleşik JSON ve XML desteği.
Tooling SQL Server Management Studio (SSMS), Azure Data Studio, Visual Studio Code SQL extensions.

Göç değerlendirmeleri kontrol listesi

Sorguları satır satır taşımaya başlamadan önce bu maddeleri gözden geçirin:

Consideration Değiştirilmesi gerekenler
Yer tutucu sözdizimi birçok Go sürücüsünden farklıdır. , ?, ve benzeri yer tutucuları $1 veya @nameile değiştirin@p1, ardından uygun olduğunda argümanları iletinsql.Named().
LastInsertId() desteklenmez. Bunun yerine OUTPUT INSERTED.<column> veya SELECT SCOPE_IDENTITY() kullanın.
Go string değerleri varsayılan olarak Unicode tiplerine eşler. Unicode dışı veriler için mssql.VarChar gibi sürücüye özgü bir tür seçmediğiniz sürece nvarchar semantiğini bekleyin.
Geçici tablolar fiziksel bağlantıyla sınırlıdır. Sonraki komutlar bu tabloya bağlıysa, geçici tablonun oluşturulması ve kullanılması mantığını aynı bağlantıda veya aynı işlem içinde tutun.
Microsoft Entra doğrulaması farklı bir sürücü kaydı kullanır. github.com/microsoft/go-mssqldb/azuread içe aktarın, sql.Open("azuresql", ...) kullanın ve Azure SQL TLS seçeneklerini encrypt=true&TrustServerCertificate=false ile açıkça ayarlayın.

Bu alanlar hakkında daha derin rehberlik için Sorgular ve ifadeler, Sınırlamalar, Veri tipi eşlemeleri, Microsoft Entra ID doğrulaması ve Sorun Giderme bölümlerine bakabilirsiniz.

lib/pq'dan geçiş yapın (PostgreSQL)

İçe aktarma ve sürücü adını değiştirin

lib/pq içe aktarma öğesini ve sürücü adını go-mssqldb ile değiştirin:

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)

bağlantı dizesi formatını değiştirin

PostgreSQL anahtar-değer formatını SQL Server URL'sine dönüştürün:

// 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"

Parametre yer tutucularını değiştir

PostgreSQL, $1, $2 konumsal yer tutucuları kullanır. SQL Server, @ ile adlandırılmış parametreler kullanır:

// 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))

SQL sözdizimi değişiklikleri

Operation PostgreSQL SQL Server
Otomatik artırma SERIAL veya GENERATED ALWAYS AS IDENTITY IDENTITY(1,1)
Eklenen kimliği alın RETURNING id OUTPUT INSERTED.id veya SELECT SCOPE_IDENTITY()
Boole türü BOOLEAN BIT
Dize birleştirme \|\| + veya CONCAT()
Geçerli zaman damgası NOW() veya CURRENT_TIMESTAMP GETUTCDATE() veya SYSDATETIMEOFFSET()
Satırları sınırla LIMIT 10 OFFSET 20 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Dize türü TEXT veya VARCHAR NVARCHAR(MAX) veya NVARCHAR(n)
JSON çıkarımı column->>'key' JSON_VALUE(column, '$.key')
Upsert INSERT ... ON CONFLICT DO UPDATE MERGE açıklama
Dizi tipi INTEGER[] Yerleşik diziler yok. Tablo değerli parametreleri kullanın.
Büyük/küçük harfe duyarlı Varsayılan olarak büyük/küçük harfe duyarlı Varsayılan olarak büyük/küçük harf duyarsızdır (karşılaştırma düzenine bağlıdır).

Girilen ID'yi alın

PostgreSQL'in maddesini RETURNING SQL Server'ın maddesiyle OUTPUT değiştirin:

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

LIMIT / OFFSET sözdizimini OFFSET/FETCH NEXT sözdizimiyle değiştirin.

// 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"

pgx'ten geçiş (PostgreSQL)

pgx sürücüsü, database/sql’den farklı olan kendi bağlantı havuzunu ve API’sini kullanır. Geçiş için standart database/sql arayüze geçin.

PGX havuzundan veritabanı/sql'ye geçiş

API'yi pgxpool standart database/sql arayüzle değiştirin.

// 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))

PGX'e özgü özellikleri değiştirin

PGX özelliği go-mssqldb eşdeğeri
pgx.CollectRows Manuel rows.Next() ve rows.Scan() döngü.
pgx.RowToStructByName rows.Scan öğesinin struct alanlarına manuel olarak eşlenmesi.
Toplu sorgular (pgx.Batch) Birden fazla ExecContext çağrı veya kayıtlı prosedür.
COPY FROM toplu ekleme için mssql.CopyIn toplu ekleme için.
pgx.ConnConfig msdsn.Config veya URL tabanlı bağlantı dizeleri.
pgxpool.Pool sql.DB, SetMaxOpenConns ve SetMaxIdleConns ile.

go-sql-driver/mysql (MySQL) üzerinden geçiş

MySQL içe aktarma ve sürücü adını değiştirin

MySQL içe aktarma ve sürücü adını go-mssqldb ile değiştirin.

// 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)

MySQL DSN formatını dönüştürün

MySQL DSN formatını SQL Server URL'sine dönüştürün.

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

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

Soru işareti yer tutucularını değiştirin

MySQL ? konumsal yer tutucular kullanır.

// 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))

MySQL ve SQL Server sözdizimini karşılaştırın

Operation MySQL SQL Server
Otomatik artırma AUTO_INCREMENT IDENTITY(1,1)
Eklenen kimliği alın LAST_INSERT_ID() SCOPE_IDENTITY() veya OUTPUT INSERTED.id
Satırları sınırla LIMIT 10 OFFSET 20 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Geçerli zaman damgası NOW() GETUTCDATE()
Null ise IFNULL(expr, default) ISNULL(expr, default) veya COALESCE(expr, default)
Dize uzunluğu LENGTH(str) LEN(str)
Dize SUBSTRING(str, start, len) SUBSTRING(str, start, len) (aynı)
Tarih biçimi DATE_FORMAT(d, '%Y-%m-%d') FORMAT(d, 'yyyy-MM-dd') veya CONVERT(VARCHAR, d, 23)
Upsert INSERT ... ON DUPLICATE KEY UPDATE MERGE açıklama
Backtick alıntısı `column` [column]

MySQL'e özgü sözdizimi Değiştir

MySQL sözdizimi SQL Server karşılığı
AUTO_INCREMENT IDENTITY(1,1)
LIMIT n OFFSET m OFFSET m ROWS FETCH NEXT n ROWS ONLY (ORDER BY gerektirir)

AUTO_INCREMENT için 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
);

OFSET/GETIR SINIRI:

-- 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;

Yaygın geçiş desenleri

Son girilen kimliği alın

Eklenen satırın kimlik değerini almak için OUTPUT yan tümcesini veya SCOPE_IDENTITY() kullanın:

// 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)

Tavsiye

SCOPE_IDENTITY() yerine OUTPUT yan tümcesini tercih edin. Bu OUTPUT madde toplu eklemelerle çalışır ve ifade sıralamasına bağlı değildir.

Upsert (ekle veya güncelle)

PostgreSQL'deki ON CONFLICT ve MySQL'deki ON DUPLICATE KEY UPDATE, SQL Server'daki MERGE öğesine karşılık gelir:

_, 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))

Toplu ekleme

PostgreSQL'in COPY veya MySQL'in LOAD DATA öğesini mssql.CopyIn ile değiştirin.

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()

NULL değerleri işle

Tüm Go veritabanı sürücüleri NULL değerleri aynı şekilde işliyor çünkü bu database/sql tür kullanıyorlar.

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

Tüm Go veritabanı sürücüleri aynı database/sql işlem API'sini kullanır.

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()

Geçiş denetim listesi

Step Action
Sürücüyü yükleme go get github.com/microsoft/go-mssqldb
İçe aktarılanları değiştir Eski sürücü içe aktarmasını _ "github.com/microsoft/go-mssqldb" ile değiştirin.
Bağlantı dizelerini güncelleyin SQL Server URL formatına geçiş: sqlserver://user:pass@host?database=db.
Parametre yer tutucularını değiştirin $1 / $2 veya ? öğesini, sql.Named ile @name olarak değiştirin.
SQL sözdizimini güncelle Değiştirin LIMIT/OFFSET, RETURNING, NOW(), SERIAL, ve diğer veritabanına özgü SQL.
Toptan işlemleri değiştirin COPY veya LOAD DATA öğesini mssql.CopyIn olarak değiştirin.
Şema güncelleme DDL SERIAL / AUTO_INCREMENT öğesini IDENTITY olarak, TEXT öğesini NVARCHAR olarak, BOOLEAN öğesini BIT olarak değiştirin.
Tüm sorguları test et Sözdizimi farklarını yakalamak için test kümenizi bir SQL Server örneğine karşı çalıştırın.
Şifrelemeyi yapılandırma Üretimde encrypt=true ekleyin (veya Azure’un otomatik algılamasını kullanın).
Kimlik doğrulamayı ayarlama Azure için Microsoft Entra ID'yi veya on-premises için SQL Server doğrulamasını configure edin.