Parametri a valori di tabella con go-mssqldb

I parametri a valori di tabella (TVP) ti permettono di passare più righe di dati strutturati a una procedura memorizzata o a una query parametrizzata. Il driver go-mssqldb supporta i TVP tramite il tipo mssql.TVP.

Usa i TVP quando devi passare un insieme di righe con tipizzazione forte a una stored procedure o a un comando e mantenere la struttura a livello delle colonne. Per il percorso a maggiore throughput in una tabella di destinazione, utilizza operazioni in blocco. Se il tuo payload è annidato o già a forma JSON nel livello applicativo, usa dati JSON e XML.

Prerequisiti

Crea un tipo di tabella definito dall'utente e una stored procedure che lo accetti:

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

Definisci una struttura Go per le righe TVP

Crea un tipo di struct Go che corrisponda alle colonne nel tipo di tabella definito dall'utente:

type DepartmentRow struct {
    Name      string
    GroupName string
}

Passare un TVP a una procedura memorizzata

Crea un mssql.TVP valore con il nome del tipo e una fetta di struct, poi passalo come parametro:

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
}

Chiama la funzione:

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)

Mappatura colonna-campo

Il driver mappa le colonne TVP ai campi della struct in base alla posizione (non al nome). Il primo campo struct si mappa alla prima colonna del tipo di tabella, il secondo campo alla seconda colonna, il terzo campo alla terza colonna, e così via per tutte le colonne del tipo di tabella.

Per saltare una colonna, non puoi usare i tag struct. Riordina o ristruttura il tipo Go per adattarlo all'ordine delle colonne nel tipo di tabella definito dall'utente.

Tipi di campo supportati

I campi delle struct TVP supportano gli stessi tipi Go dei normali parametri:

Tipo di campo in Go Tipo di colonna SQL Server
string nvarchar
mssql.VarChar varchar
int64, int32, int16int8 bigint, int, smallinttinyint
float64, float32 float, real
bool bit
time.Time datetimeoffset
[]byte varbinary
mssql.UniqueIdentifier uniqueidentifier

TVP vuoto

Puoi passare una slice vuota. La procedura memorizzata riceve una tabella con zero righe:

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

Nome del tipo qualificato dallo schema

TypeName deve essere il nome del tipo di tabella definito dall'utente (non il nome della tabella di destinazione o il nome della procedura memorizzata). Se il tipo di tabella appartiene a uno schema non predefinito, includere lo schema in TypeName:

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