go-mssqldb 的表值參數

表格值參數(TVP)允許您將多列結構化資料傳遞給儲存程序或參數化查詢。 驅動程式 go-mssqldb 透過該 mssql.TVP 類型支援 TVP。

當你需要將強型別的列集傳入儲存程序或指令並保留欄位層級結構時,可以使用 TVP。 若要以最高吞吐量將資料寫入目的地資料表,請使用 大量作業。 如果您的承載資料具有巢狀結構,或在應用層中已是 JSON 格式,請使用 JSON 與 XML 資料

先決條件

建立一個使用者定義的表格型別及一個接受該資料表的儲存程序:

CREATE TYPE dbo.DepartmentType AS TABLE (
    Name NVARCHAR(50),
    GroupName NVARCHAR(50)
);
GO

CREATE PROCEDURE dbo.InsertDepartments
    @departments dbo.DepartmentType READONLY
AS
BEGIN
    INSERT INTO HumanResources.Department (Name, GroupName)
    SELECT Name, GroupName FROM @departments;
END;
GO

為 TVP 列定義一個 Go 結構

建立一個與使用者自訂資料表類型欄位相符的 Go 結構型別:

type DepartmentRow struct {
    Name      string
    GroupName string
}

將 TVP 傳給儲存程序

建立值 mssql.TVP,其中包含型別名稱和結構體切片,然後將其作為參數傳遞:

import (
    "context"
    "database/sql"

    "github.com/microsoft/go-mssqldb"
)

func insertDepartments(ctx context.Context, db *sql.DB, departments []DepartmentRow) error {
    tvp := mssql.TVP{
        TypeName: "dbo.DepartmentType",
        Value:    departments,
    }

    _, err := db.ExecContext(ctx, "dbo.InsertDepartments",
        sql.Named("departments", tvp))
    return err
}

呼叫函數:

departments := []DepartmentRow{
    {Name: "Data Science", GroupName: "Research and Development"},
    {Name: "Cloud Ops", GroupName: "Information Technology"},
    {Name: "Developer Relations", GroupName: "Sales and Marketing"},
}
err := insertDepartments(ctx, db, departments)

欄位到欄位映射

驅動程式會依位置(而非名稱)將 TVP 欄位映射到 struct 欄位。 第一個結構體欄位對應到資料表類型的第一欄,第二個欄位對應到第二欄,第三個欄位對應到第三欄,依此類推適用於表格類型中的所有欄位。

要跳過欄位,你不能使用結構標籤。 重新排序或重組你的 Go 類型,使其與使用者自訂表格類型的欄位順序相符。

支援的欄位類型

TVP 結構體欄位支援與一般參數相同的 Go 類型:

圍棋場型 SQL Server 欄位類型
string nvarchar
mssql.VarChar varchar
int64int32int16int8 bigintintsmallinttinyint
float64float32 floatreal
bool bit
time.Time datetimeoffset
[]byte varbinary
mssql.UniqueIdentifier uniqueidentifier

空的 TVP

你可以傳入空切片。 儲存程序接收到一個列為零的表格:

tvp := mssql.TVP{
    TypeName: "dbo.DepartmentType",
    Value:    []DepartmentRow{},
}

結構限定型別名稱

TypeName 必須是使用者定義的表格類型名稱(而非目的表格名稱或儲存程序名稱)。 若資料表類型為非預設結構,則將該結構包含於 TypeName

tvp := mssql.TVP{
    TypeName: "HumanResources.DepartmentType",
    Value:    departments,
}