テーブルバリューパラメータ(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 の列を名前ではなく位置に基づいて構造体のフィールドにマッピングします。 最初の構造体フィールドはテーブルタイプの最初の列に、2番目のフィールドは2列目、3番目のフィールドは3番目の列にマッピングされ、このようにテーブルタイプのすべての列に対して対応します。
列をスキップするには、structタグを使うことはできません。 ユーザー定義テーブル型の列順に合わせて、Go 型を並べ替えるか再構成してください。
サポートされているフィールドの種類
TVPの構造体フィールドは通常のパラメータと同じGoタイプをサポートしています:
| 囲碁フィールドタイプ | SQL Server カラムタイプ |
|---|---|
string |
nvarchar |
mssql.VarChar |
varchar |
int64、int32、int16、int8 |
bigint、int、smallint、tinyint |
float64、float32 |
float、real |
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,
}