Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Sürücü, go-mssqldb giriş parametreleri, çıkış parametreleri ve dönüş durum değerleriyle birlikte saklanan prosedürleri çağırmayı destekler. Bu makale yaygın kalıpları ele almaktadır.
Bu makaledeki kod parçacıklarının çoğu, alışılmış database/sql yapılandırmasının zaten mevcut olduğunu, database/sql öğesinin sql olarak içe aktarıldığını, bir ctx değerinin kullanılabilir olduğunu ve db öğesinin başlatıldığını varsayar. Kod parçacıkları, yalnızca context, fmt, log, os veya github.com/microsoft/go-mssqldb gibi ek paketler eklediklerinde import blokları içerir. Bir kod bloğu kasıtlı olarak aynı örneği sürdürdüğünde, o örnekte önceden ilan edilmiş değerler için kullanılır = ; bağımsız kesitlerde taze bildirimler için kullanılır := .
Saklı yordam çağırmak
Prosedür adını doğrudan ExecContext veya QueryContext ile kullanın:
_, err := db.ExecContext(ctx, "dbo.uspGetEmployeeManagers",
sql.Named("BusinessEntityID", 6))
Sıradan işlem çağrıları için prosedür adı ve parametreleri tercih edin. Açık bir EXECUTE ... diziyi yalnızca çağrıyı daha büyük bir Transact-SQL (T-SQL) partisine gömmeniz gerektiğinde veya parametrelerle sql.Named temsil edilmeyen sözdizimi kullanmanız gerektiğinde kullanın.
Çıkış parametreleri
Çıkış parametresi değerlerini almak için sql.Named öğesini sql.Out ile kullanın:
import (
"context"
"database/sql"
"fmt"
"log"
)
ctx := context.Background()
var employeeCount int64
_, err := db.ExecContext(ctx, "dbo.GetEmployeeCount",
sql.Named("count", sql.Out{Dest: &employeeCount}))
if err != nil {
log.Fatal(err)
}
fmt.Println("Employee count:", employeeCount)
İlgili T-SQL prosedürü:
CREATE PROCEDURE dbo.GetEmployeeCount
@count INT OUTPUT
AS
BEGIN
SELECT @count = COUNT(*) FROM HumanResources.Employee;
END;
Giriş/çıkış parametreleri
Hem giriş hem de çıkış olan parametreler için, sql.Out yapısında In: true ayarlayın:
var result int64 = 10
_, err := db.ExecContext(ctx, "dbo.DoubleValue",
sql.Named("value", sql.Out{Dest: &result, In: true}))
if err != nil {
log.Fatal(err)
}
fmt.Println("Doubled:", result)
İade durumu
Saklanan bir prosedürün tamsayı dönüş değerini yakalamak için kullanılır mssql.ReturnStatus . Bu örnek AdventureWorks dbo.uspGetEmployeeManagers prosedürünü kullanır:
import (
"database/sql"
"fmt"
"log"
mssql "github.com/microsoft/go-mssqldb"
)
var returnStatus mssql.ReturnStatus
rows, err := db.QueryContext(ctx, "dbo.uspGetEmployeeManagers",
sql.Named("BusinessEntityID", 6),
&returnStatus)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
fmt.Println("Return status:", returnStatus)
ReturnStatus, ExecContext ve QueryContext ile çalışır, ancak QueryRowContext ile çalışmaz.
Prosedür parametreleriyle birleştirebilirsiniz ReturnStatus . Bu örnek, önceki örneğin devamıdır; bu nedenle daha önce gösterilen mssql içe aktarmasını yeniden kullanır ve AdventureWorks dbo.uspGetEmployeeManagers yordamını kullanır:
var returnStatus mssql.ReturnStatus
rows, err := db.QueryContext(ctx, "dbo.uspGetEmployeeManagers",
sql.Named("BusinessEntityID", 6),
&returnStatus)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
Depolanan prosedürlerden sonuç kümeleri
Eğer saklanan prosedür sonuç kümelerini döndürüyorsa, :QueryContext
rows, err := db.QueryContext(ctx, "dbo.uspGetEmployeeManagers", sql.Named("BusinessEntityID", 6))
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var reportingLevel int
var employeeID int
var employeeFirstName string
var employeeLastName string
var organizationNode string
var managerFirstName string
var managerLastName string
if err := rows.Scan(&reportingLevel, &employeeID, &employeeFirstName, &employeeLastName, &organizationNode, &managerFirstName, &managerLastName); err != nil {
log.Fatal(err)
}
fmt.Printf("Level %d: %d %s %s (manager: %s %s)\n",
reportingLevel, employeeID, employeeFirstName, employeeLastName, managerFirstName, managerLastName)
_ = organizationNode
}
Birden çok sonuç kümesi döndüren yordamlar için rows.NextResultSet() kullanın. Daha fazla bilgi için Sorgular ve ifadeler bölümüne bakınız.
Çıkış parametreleri veya dönüş durumunu kullanmadan önce tüm satırları okuyun
SQL Server, sonuç setleri bittikten sonra çıktı parametreleri gönderir ve durum değerlerini döndürür. Tüm satırları tüketmeden önce bir çıktı değişkenini okursanız, değer yine eksik olabilir.
Bu örnek, önceki örneğin devamıdır ve daha önce gösterilen mssql içe aktarmasını yeniden kullanır.
Satır verisini yazdırmıyor. Döngü sadece sonuç kümesini tüketir, bu yüzden returnStatus sorgu bittikten sonra kullanılabilir.
var returnStatus mssql.ReturnStatus
rows, err := db.QueryContext(ctx, "dbo.uspGetEmployeeManagers",
sql.Named("BusinessEntityID", 6),
&returnStatus)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var reportingLevel int
var employeeID int
var employeeFirstName string
var employeeLastName string
var organizationNode string
var managerFirstName string
var managerLastName string
if err := rows.Scan(&reportingLevel, &employeeID, &employeeFirstName, &employeeLastName, &organizationNode, &managerFirstName, &managerLastName); err != nil {
log.Fatal(err)
}
_ = organizationNode
_ = managerFirstName
_ = managerLastName
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
fmt.Println("Return status:", returnStatus)
Prosedür satır döndürmediğinde ExecContext kullanın. Eğer prosedür satır döndürürse, çıkış parametrelerini veya dönüş durumunu okumadan önce tüm satırlar ve sonuç kümeleri tüketilene kadar bekleyin.
Geçici tablolar ve saklanan prosedürler
Geçici bir tablo oluşturup ayrı çağrılarla sorguladığınızda, işlemler havuzdan farklı bağlantılarda çalışabilir. Geçici tablolar yalnızca tek bir bağlantıyla sınırlı olduğundan, ikinci çağrı tabloyu göremeyebilir.
Geçici tablolarla çalışmak için tek bağlantı yaklaşımı kullanın:
conn, err := db.Conn(ctx)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
_, err = conn.ExecContext(ctx, "CREATE TABLE #TempItems (Id INT, Name NVARCHAR(50))")
if err != nil {
log.Fatal(err)
}
_, err = conn.ExecContext(ctx, "INSERT INTO #TempItems VALUES (1, N'Item A')")
if err != nil {
log.Fatal(err)
}
rows, err := conn.QueryContext(ctx, "SELECT * FROM #TempItems")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
Alternatif olarak, işlemleri bir işlem içinde gerçekleştirin; böylece otomatik olarak aynı bağlantıya sabitlenirler.
PRINT ve RAISERROR mesajlarını yakalayın
SQL Server PRINT ifadeleri ve RAISERROR 0-10 şiddetinde olan bilgi mesajları Go hatası olarak geri dönmez. Bu mesajları yakalamak için, bağlantı parametresini bayrak log (mesajlar) ile etkinleştirin2:
sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=2
Günlük kaydı etkinleştirildiğinde, sürücü PRINT çıktısını ve düşük önem dereceli RAISERROR mesajlarını Go'nun standart log paketine yazar. Bunları programatik olarak yakalamak için, bağlantıyı açmadan önce özel bir logger ayarlayın:
import (
"database/sql"
"log"
"os"
mssql "github.com/microsoft/go-mssqldb"
)
// Direct driver messages to a custom logger.
mssql.SetLogger(log.New(os.Stdout, "mssql: ", log.LstdFlags))
db, err := sql.Open("sqlserver",
"sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=2")
Ardından, PRINT veya RAISERROR(..., 0, 1) kullanan herhangi bir saklı yordam, mesajlarını günlük kaydedicinize gönderir.
Uyarı
RAISERROR 11 veya daha yüksek şiddette ise normal hata kontrolüyle halledilebilecek bir Go hatası üretir. Yalnızca önem derecesi 0-10 olan iletilerin yakalanması için log parametresi gerekir.
Günlük kaydı bayrakları ve program aracılığıyla günlük yakalama hakkında daha fazla bilgi için Günlük kaydı ve tanılama bölümüne bakın.