Vektordatentyp (ODBC)

In diesem Artikel wird der Sql-Vektordatentyp wie vom Microsoft ODBC-Treiber für SQL Server ab Version 18.6.1.1 implementiert. In diesem Dokument wird das Verhalten des Microsoft-Treibers für den Vektor beschrieben, und es werden Verwendungsanleitungen, API-spezifische Notizen und Codeausschnitte bereitgestellt. Eine Übersicht über Vektordatentypen finden Sie unter Vector-Datentyp.

Überblick

Der Microsoft ODBC-Treiber für SQL Server unterstützt den Vektordatentyp nativ. Anwendungen können numerische Einbettungen mit fester Dimension effizient speichern, abrufen und verarbeiten, die häufig in Machine Learning- und KI-Workloads verwendet werden. Der Treiber macht die Vektorunterstützung über standardmäßige ODBC-APIs und C-Datentypen verfügbar. Anwendungen können mit SQL Server-Vektorspalten zusammenarbeiten, ohne vorhandene ODBC-Workflows zu ändern.

Gilt für: Microsoft ODBC-Treiber für SQL Server 18.6.1.1 und höhere Versionen. Die Unterstützung für den float16 Basistyp erfordert Version 18.7.1.1 oder neuer.

Die Vektor-Unterstützung ist standardmäßig deaktiviert und muss explizit aktiviert sein.

Basiselementtypen

Eine Vektorspalte deklariert einen Basiselementtyp. Der Treiber unterstützt beide Typen, die SQL Server definiert.

Basistyp Typindikator Bytes pro Element auf dem Draht Maximale Dimension Treiberversion
float32 SQL_VECTOR_TYPE_FLOAT32 (0) 4 1,998 18.6.1.1
float16 SQL_VECTOR_TYPE_FLOAT16 (1) 2 3,996 18.7.1.1

float32 ist der Standardwert. Um Halbpräzisionsspeicher zu verwenden, deklarieren Sie die Spalte oder den Parameter als VECTOR(<dimensions>, float16). Da ein Element float16 die Hälfte der Bytes auf dem Draht einnimmt, hält ein Vektor float16 doppelt so viele Dimensionen innerhalb desselben 8.000-Byte-Nutzlastlimits.

Important

Der Anwendungspuffer ist immer ein Array von float (4 Bytes pro Element) für beide Basistypen. Der Treiber wechselt zwischen halber Genauigkeit auf dem Draht und Einzelpräzision im Puffer. Dimensioniere jeden Puffer mit sizeof(float), niemals mit 2 Bytes pro Element, selbst für eine Spalte float16 .

Da float16 weniger Mantissen-Bits float32als hat, ist eine Hin- und Herumfahrt durch eine Spalte float16 verlustbehaftet. Werte werden auf den nächstgelegenen repräsentierbaren Halbpräzisionswert beim Einfügen abgerundet, und der zurückgelesene Wert ist die float32 Entwicklung dieses abgerundeten Werts.

Auf dem Server float16 benötigt er SQL Server 2025 (17.x) mit aktivierter PREVIEW_FEATURES Datenbank-Scoped-Konfiguration. Weitere Informationen finden Sie unter Halbpräzisions-Float-Unterstützung im Vektordatentyp.

Native C-Darstellung

Wenn die Vektorunterstützung aktiviert ist, werden Vektorspalten mithilfe einer typierten C-Struktur mit dem Namen SQL_SS_VECTOR_STRUCTausgetauscht.

    typedef enum
    {
        SQL_VECTOR_TYPE_FLOAT32 = 0,  /* 32-bit floating point */
        SQL_VECTOR_TYPE_FLOAT16 = 1   /* 16-bit floating point */
    } SQLVECTORTYPE;

    typedef struct tagSS_VECTOR_STRUCT {
        SQLSMALLINT   dimension;  /* Number of elements */
        SQLVECTORTYPE type;       /* Element base type indicator */
        union data {
            float* f32;           /* Pointer to float32 data */
            float* f16;           /* Pointer to float16 data */
        } data;
    } SQL_SS_VECTOR_STRUCT;
  • dimension: beschreibt die Anzahl der Elemente im Vektor.
  • type: identifiziert den Basiselementtyp, SQL_VECTOR_TYPE_FLOAT32 oder SQL_VECTOR_TYPE_FLOAT16
  • data.f32 / data.f16: zeigt auf den Anwendungspuffer mit Vektorwerten

Beide Union-Mitglieder sind als float* deklariert und austauschbar, da der clientseitige Puffer Werte für beide Basistypen enthält float32 . Verwenden Sie das Mitglied, das Ihre Absicht dokumentiert.

Aktivierung des Vektor-Support

Das vectorTypeSupport Schlüsselwort Verbindungszeichenfolge wählt das Niveau der nativen Vektorunterstützung, das die Verbindung aushandelt.

Wert Behavior
off (Standardwert) Vektorspalten erscheinen als varchar(max) mit JSON-Arrays.
v1 Native Vektorunterstützung für den float32 Basistyp.
v2 Native Vektorunterstützung sowohl für den Typ als auch float16 für den float32 Basistyp. Benötigt die Treiberversion 18.7.1.1 oder neuer.

Du kannst auch das Level nach der Zuweisung des Verbindungshandles und vor der Verbindung mit dem SQL_COPT_SS_VECTOR_TYPE_SUPPORT Pre-Connect-Attribut einstellen.

  • Der Microsoft-Treiber bietet eine treiberspezifische C-Bindung SQL_C_SS_VECTOR und unterstützt SQL_C_BINARY Vektorausgaben. Praktisch:

    • Wenn du oder v2aktivierstvectorTypeSupport=v1, können Abruf-APIs (zum Beispiel SQLGetData und SQLBindCol) Vektorspalten wie entweder SQL_C_SS_VECTOR oder SQL_C_BINARYzurückgeben. SQL_C_SS_VECTOR gibt den Vektor in einem kompakten, getypten Format zurück. SQL_C_BINARY gibt eine varbinäre Nutzlast zurück.

    • Für Eingabe- oder Parameterbindung unterstützt der Treiber sowohl SQL_C_SS_VECTOR als auch SQL_C_BINARY. SQL_C_SS_VECTOR stellt eine typierte, kompakte Eingabebindung bereit. SQL_C_BINARY ist gleichwertig und portierbar. Verwenden Sie diese Option SQL_C_SS_VECTOR , wenn der Treiber die Nutzlast als systemeigenen Vektortyp behandeln soll.

    • Wenn vectorTypeSupport=off, Vektorspalten als varchar(max) mit JSON-Arrays angezeigt werden.

v2ist eine Übermenge von v1, sodass eine bei ausgehandelte Verbindung v2 Spalten genau so v1 behandelt float32 wie t. Das Senden eines float16 Werts auf eine verhandelte Verbindung v1 schlägt mit Requested vector base type is not supported for the negotiated vector version. Use v2 fehl, wann immer die Anwendung auf eine Spalte float16 stoßen könnte.

Anwendungen müssen auch die ODBC-Version auf ODBC 3.8 festlegen, bevor vektorspezifische Typen verwendet werden:

    SQLSetEnvAttr(
    hEnv,
    SQL_ATTR_ODBC_VERSION,
    (SQLPOINTER)SQL_OV_ODBC3_80,
    0);

Unterstützte Bindungsformate

Native Vektorbindung

C-Typ: SQL_C_SS_VECTOR

Dieses Format wird für leistungskritische Anwendungen empfohlen.

Binäre Bindung

C-Typ: SQL_C_BINARY

Vektoren werden mit demselben Layout zurückgegeben wie SQL_C_SS_VECTOR. Anwendungen können dieses Format für Interoperabilitätsszenarien auf niedriger Ebene verwenden. Der Datenzeigerpuffer kann zusammenhängend oder nicht zusammenhängend mit der Strukturspeicheradresse sein.

ODBC-API-Leitfaden

In diesem Abschnitt wird beschrieben, wie ODBC-APIs mit SQL Server-Vektordaten interagieren, einschließlich Pufferlayoutanforderungen, NULL Behandlung und unterstützte Datendarstellungen. Alle Verhaltensweisen gelten, wenn vectorTypeSupport auf oder v2 gesetzt v1 ist und die Umgebung für ODBC 3.8 konfiguriert ist.

Jede Puffergrößenformel in diesem Abschnitt verwendet sizeof(float) pro Element für beide Basistypen, da der clientseitige Puffer immer Werte enthält float32 . Eine Spalte verändert die Bytes auf dem Kabel, nicht das Layout deines Puffers float16 .

SQLBindCol

Dient SQLBindCol zum Binden von Vektorspalten in einem Resultset an Anwendungspuffer.

  • Typischer Anruf:
    SQLRETURN SQLBindCol(
      SQLHSTMT       StatementHandle,
      SQLUSMALLINT   ColumnNumber,
      SQLSMALLINT    TargetType,
      SQLPOINTER     TargetValuePtr,
      SQLLEN         BufferLength,
      SQLLEN *       StrLen_or_IndPtr);
  • TargetType: verwenden SQL_C_SS_VECTOR oder SQL_C_BINARY.

  • TargetValuePtr: Zeiger auf ein SQL_SS_VECTOR_STRUCT mit einem Float-Array, wenn TargetType gleich SQL_C_SS_VECTOR ist; andernfalls Zeiger auf einen Puffer mit der Größe gemäß dem Wert in StrLen_or_IndPtr.

  • BufferLength: sizeof(SQL_SS_VECTOR_STRUCT) + die Anzahl der Bytes, die für den Spaltenpuffer zugeordnet sind (Dimension * 4).

  • StrLen_or_IndPtr: Zeiger, der die Bytelänge des zurückgegebenen Vektors (SQL_DESC_OCTET_LENGTH) empfängt. Der Wert ist sizeof(SQL_SS_VECTOR_STRUCT) + die Float-Arraygröße (Dimension * 4).

Diese Größen sind bei einer float16 Säule gleich. Der Treiber erweitert jedes halbpräzise Element zu a, float während es den Puffer füllt, und meldet die erweiterte Länge.

Erwartungen an das Pufferlayout

Nicht zusammenhängender Puffer (empfohlen)

  • Die Anwendung weist eine SQL_SS_VECTOR_STRUCT pro Zeile zu.
  • Die Anwendung weist Arbeitsspeicher für data.f32 zu.
  • Der Treiber füllt Vektormetadaten und schreibt Elementwerte in den bereitgestellten Float-Puffer .
    SQLLEN numberOfRow = 1000; // set to SQL_ATTR_ROW_ARRAY_SIZE
    SQLULEN columnSize = x; // use SQLDescribeCol or SQLColAttributeW or sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * 4)
    SQL_SS_VECTOR_STRUCT vecBuffer[numberOfRow]
    std::vector<SQLLEN> indicator(numberOfRow, 0);
    for (int i = 0; i < numberOfRow; i++)
    {
        vecBuffer[i].dimension = static_cast<SQLUSMALLINT>((columnSizes[col - 1] - sizeof(SQL_SS_VECTOR_STRUCT)) / 4);
        vecBuffer[i].type = SQL_VECTOR_TYPE_FLOAT32; // or SQL_VECTOR_TYPE_FLOAT16
        vecBuffer[i].data.f32 = (float*)malloc(vecBuffer[i].dimension * sizeof(float));
        if (!vecBuffer[i].data.f32) {
            std::cerr << "Memory allocation failed for vector data." << std::endl;
            return SQL_ERROR;
        }
    }
    SQLBindCol(hStmt, col, SQL_C_SS_VECTOR, vecBuffer, columnSize, indicators.data());

Zusammenhängender Puffer

  • Die Anwendung weist einen einzelnen Puffer zu und ODBC füllt ihn entsprechend aus.
  • Das Float-Array muss unmittelbar nach der Struktur beginnen.
  • Der Treiber setzt data.f32 so, dass es auf diesen zusammenhängenden Bereich zeigt.
    SQLLEN numberOfRow = 1000; // set to SQL_ATTR_ROW_ARRAY_SIZE
    SQLULEN columnSize = x; // use SQLDescribeCol or SQLColAttributeW or sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * 4)
    std::vector<BYTE> vecBuffer;
    std::vector<SQLLEN> indicator(numberOfRow, 0);
    vecBuffer.resize(numberOfRow * columnSize);
    SQLBindCol(hStmt, col, SQL_C_BINARY, vecBuffer.data(), columnSize, indicators.data());

NULL-Behandlung für SQLBindCol

Wenn der Spaltenwert NULL ist, setzt der Treiber *StrLen_or_IndPtr auf SQL_NULL_DATA und füllt den Puffer nicht auf. Überprüfen Sie immer den Indikator, bevor Sie auf Vektorinhalte zugreifen.

Hinweis

Das Lese- und Zeilenabrufverhalten für Vektorspalten wird ausführlich unter SQLFetch und SQLFetchScroll (siehe diese API-Verweise für Abrufsemantik und Array-Fetch-Beispiele) beschrieben.

SQLGetData

Verwenden Sie SQLGetData, um Vektordaten aus ungebundenen Spalten abzurufen.

  • Typischer Anruf:
    SQLRETURN SQLGetData(
      SQLHSTMT       StatementHandle,
      SQLUSMALLINT   Col_or_Param_Num,
      SQLSMALLINT    TargetType,
      SQLPOINTER     TargetValuePtr,
      SQLLEN         BufferLength,
      SQLLEN *       StrLen_or_IndPtr);
  • TargetType: verwenden SQL_C_SS_VECTOR oder SQL_C_BINARY.

  • TargetValuePtr: Zeiger auf ein SQL_SS_VECTOR_STRUCT mit einem Float-Array, wenn TargetType gleich SQL_C_SS_VECTOR ist; andernfalls Zeiger auf einen Puffer mit der Größe gemäß dem Wert in StrLen_or_IndPtr.

  • BufferLength: sizeof(SQL_SS_VECTOR_STRUCT) + die Anzahl der Bytes, die für den Spaltenpuffer zugeordnet sind (Dimension * 4).

  • StrLen_or_IndPtr: Zeiger, der die Bytelänge des zurückgegebenen Vektors (SQL_DESC_OCTET_LENGTH) empfängt. Der Wert ist sizeof(SQL_SS_VECTOR_STRUCT) + die Float-Arraygröße (Dimension * 4).

Der gestückelte Abruf wird nicht unterstützt. Sie müssen den gesamten Vektor in einem Aufruf abrufen.

Beispiel (nativer Vektor):

    SQLLEN dataLen = 0;
    SQL_SS_VECTOR_STRUCT vec = {};
    vec.data.f32 = (float*)malloc(x * sizeof(float)); // x is the dimension
    if (!vec.data.f32) {
        std::cerr << "Memory allocation failed for vector data." << std::endl;
        return SQL_ERROR;
    }
    SQLGetData(hStmt, col, SQL_C_SS_VECTOR, &vec, sizeof(vec) + sizeof(float) * vec.dimension, &dataLen);

NULL-Behandlung für SQLGetData

Wenn der Spaltenwert NULL ist, setzt der Treiber *StrLen_or_IndPtr auf SQL_NULL_DATA und füllt den Puffer nicht auf. Überprüfen Sie immer den Indikator, bevor Sie auf Vektorinhalte zugreifen.

Hinweis

Das Lese- und Zeilenabrufverhalten für Vektorspalten wird ausführlich unter SQLFetch und SQLFetchScroll (siehe diese API-Verweise für Abrufsemantik und Array-Fetch-Beispiele) beschrieben.

SQLFetch

Verwenden Sie SQLFetch, um die nächste Zeile abzurufen und alle gebundenen SqlVector Spalten ordnungsgemäß zu materialisieren.

  • Typischer Anruf:
    SQLRETURN SQLFetch(
     SQLHSTMT     StatementHandle);

Rufen Sie SQLFetch in der Standardschleife auf, wobei die Spalten SqlVector bereits durch SQLBindCol gebunden sind. Oder verwenden Sie SQLGetData, um Daten in den Anwendungspuffer abzurufen.

Beispiel (nativer Vektor):

    while ((ret = SQLFetch(hStmt)) == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        // if SQLBindCol was used directly jump to read buffer
        // else use SQLGetData and than read buffer.
        std::cout << "  data: [";
        if (dataLen != SQL_NULL_DATA)
        {
            for (SQLUSMALLINT d = 0; d < vec.dimension; ++d) {
                std::cout << vec.data.f32[d];
                if (d + 1 < vec.dimension) std::cout << ", ";
            }
        }
        std::cout << "]" << std::endl;
    }

SQLFetchScroll

Dient SQLFetchScroll zum Abrufen von Rowsets gemäß einer angegebenen Ausrichtung (next, prior, absolute, relative, bookmark). Der Treiber kopiert Vektordaten ordnungsgemäß in Anwendungspuffer.

  • Typischer Anruf:
    SQLRETURN SQLFetchScroll(
      SQLHSTMT      StatementHandle,
      SQLSMALLINT   FetchOrientation,
      SQLLEN        FetchOffset);

Beispiel (nativer Vektor):

    // Fetch rows in batches
    while ((ret = SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 0)) != SQL_NO_DATA) {
        for (SQLULEN i = 0; i < numRowsFetched; i++) {
            // In case of Contiguous Buffer
                SQL_SS_VECTOR_STRUCT* vecptr = reinterpret_cast<SQL_SS_VECTOR_STRUCT*>(
                vecBuffer.data() + (i * columnSizes[col - 1]));
                float* floats = reinterpret_cast<float*>(
                reinterpret_cast<char*>(vecptr) + sizeof(SQL_SS_VECTOR_STRUCT)
            );
            // in Case of non-contiguous Buffer
            SQL_SS_VECTOR_STRUCT* vecptr = &vecBuffer[i];
            float* floats = vecptr->data.f32;

            if (indicators[i] != SQL_NULL_DATA)
            {
                for (SQLUSMALLINT d = 0; d < vecptr->dimension; ++d) {
                    std::cout << floats[d];
                    if (d + 1 < vecptr->dimension) std::cout << ", ";
                }
            }
            std::cout << "]" << std::endl;
        }
    }

SQLBindParameter

Wird SQLBindParameter verwendet, um Vektorwerte an SQL Server zu senden.

  • Typischer Anruf:
    SQLRETURN SQLBindParameter(
        SQLHSTMT        StatementHandle,
        SQLUSMALLINT    ParameterNumber,
        SQLSMALLINT     InputOutputType,
        SQLSMALLINT     ValueType,
        SQLSMALLINT     ParameterType,
        SQLULEN         ColumnSize,
        SQLSMALLINT     DecimalDigits,
        SQLPOINTER      ParameterValuePtr,
        SQLLEN          BufferLength,
        SQLLEN *        StrLen_or_IndPtr);
  • ParameterValuePtr: verweist auf eine ausgefüllte SQL_SS_VECTOR_STRUCT
  • ColumnSize: wird für Eingabeparameter ignoriert. Geben Sie für Ausgabeparameter und Daten bei Ausführungsszenarien die Gesamtvektorgröße an: sizeof(SQL_SS_VECTOR_STRUCT) + (Float-Arraygröße )
  • DecimalDigits: wird für Eingabeparameter ignoriert. Geben Sie für Ausgabeparameter und Daten bei Ausführungsszenarien den Vektorbasistyp an.
  • BufferLength: ≥ sizeof(SQL_SS_VECTOR_STRUCT) + (Dimension * sizeof(float))
  • *StrLen_or_IndPtr: muss dieselbe Gesamtgröße enthalten

Woher der Basistyp stammt

Der Treiber liest den Basiselementtyp je nach Parameterrichtung von einem anderen Ort aus. Ein Fehler ist die häufigste Ursache für Invalid vector dimension Fehler bei Provided buffer length too small/large einem float16 Parameter.

Parameterart Basistyp Quelle Dimensionsquelle
Eingang und Eingang/Ausgabe Das Feld type des SQL_SS_VECTOR_STRUCT You Pass Das Feld dimension derselben Struktur
Reiner Ausgang DecimalDigits Abgeleitet von ColumnSize als (ColumnSize - sizeof(SQL_SS_VECTOR_STRUCT)) / sizeof(float)
Daten bei der Ausführung DecimalDigits Abgeleitet von ColumnSize, und mit der Länge abgeglichen auf SQL_LEN_DATA_AT_EXEC

Für einen Eingangsparameter BufferLength muss sizeof(SQL_SS_VECTOR_STRUCT) genau gleich + (Dimension * sizeof(float)) sein. Ein größerer oder kleiner Wert scheitert, anstatt toleriert zu werden.

Beispiel (nativer Vektor, float32):

    float values[3] = {1.0f, 2.0f, 3.0f};
    SQL_SS_VECTOR_STRUCT vec;
    SQLLEN cb;

    vec.dimension = 3;
    vec.type = SQL_VECTOR_TYPE_FLOAT32;
    vec.data.f32 = values;

    cb = sizeof(vec) + sizeof(values);

    SQLBindParameter(
        hStmt, 1, SQL_PARAM_INPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR, 0, 0, &vec, cb, &cb);

Beispiel (nativer Vektor, float16):

Nur das Spielfeld type ändert sich. Das Wert-Array bleibt ein Array float und cb wird auf die gleiche Weise berechnet.

    float values[3] = {1.0f, 2.0f, 3.0f};
    SQL_SS_VECTOR_STRUCT vec;
    SQLLEN cb;

    vec.dimension = 3;
    vec.type = SQL_VECTOR_TYPE_FLOAT16;
    vec.data.f16 = values; /* still a float32 array */

    cb = sizeof(vec) + sizeof(values);

    SQLBindParameter(
        hStmt, 1, SQL_PARAM_INPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR, 0, 0, &vec, cb, &cb);

Beispiel (float16 Ausgabeparameter):

Ein reiner Ausgabeparameter trägt keine Eingabestruktur, daher wird der Basistyp eingereicht DecimalDigits und die Dimension aus ColumnSizeabgeleitet.

    SQL_SS_VECTOR_STRUCT vec = {};
    float values[3] = {};
    vec.data.f16 = values;

    SQLULEN columnSize = sizeof(SQL_SS_VECTOR_STRUCT) + 3 * sizeof(float);
    SQLLEN cb = (SQLLEN)columnSize;

    SQLBindParameter(
        hStmt, 1, SQL_PARAM_OUTPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR,
        columnSize, SQL_VECTOR_TYPE_FLOAT16, &vec, cb, &cb);

NULL-Behandlung für SQLBindParameter

Anwendungen können einen Vektor mit einem der beiden unterstützten Ansätze angeben:

  • Setzen *StrLen_or_IndPtr auf SQL_NULL_DATA und übergeben NULL als ParameterValuePtr

  • Stellen Sie ein SQL_SS_VECTOR_STRUCT bereit:

    Dimensionsmengentyp auf den Basistyp der Spalte gesetzt data.f32 = NULL

SQLPutData

Der Treiber unterstützt SQLPutData für Vektorparameter mit folgenden Einschränkungen:

  • Sie müssen den gesamten Vektor im ersten Aufruf angeben.

  • Der Treiber unterstützt keine gestückelte oder inkrementelle Vektorübertragung.

  • NULL die Behandlung folgt den gleichen Regeln wie SQLBindParameter.

  • Typischer Anruf:

    SQLRETURN SQLPutData(
        SQLHSTMT     StatementHandle,
        SQLPOINTER   DataPtr,
        SQLLEN       StrLen_or_Ind);
  • DataPtr: verweist auf eine ausgefüllte SQL_SS_VECTOR_STRUCT
  • StrLen_or_Ind: sizeof(SQL_SS_VECTOR_STRUCT) + (Dimension * sizeof(float))

Beispiel (nativer Vektor):

    std::vector<float> floatArray = { 1.0f, 2.0f, 3.0f };

    SQL_SS_VECTOR_STRUCT vectorValue = {0};
    vectorValue.type = SQL_VECTOR_TYPE_FLOAT32; // or SQL_VECTOR_TYPE_FLOAT16
    vectorValue.dimension = (SQLUSMALLINT)floatArray.size();
    vectorValue.data.f32 = floatArray.data();

    // Tell ODBC this parameter will be supplied at execution time
    SQLLEN cbVectorLen = SQL_LEN_DATA_AT_EXEC(
        (SQLLEN)(sizeof(SQL_SS_VECTOR_STRUCT) + floatArray.size() * sizeof(float))
    );

    // Optional token to identify which parameter needs data
    SQLPOINTER token = (SQLPOINTER)1;

    // Bind as DATA_AT_EXEC: BufferLength is 0, value pointer can be a token
    SQLRETURN rc = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR, 0, 0, token, 0, &cbVectorLen);

    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
        // handle error
    }

    rc = SQLExecute(hStmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NEED_DATA) {
        // handle error
    }

    SQLPOINTER pParamToken = NULL;
    rc = SQLParamData(hStmt, &pParamToken);

    if (rc == SQL_NEED_DATA) {
        // Provide entire vector in first SQLPutData call (no chunking)
        rc = SQLPutData(
            hStmt,
            (SQLPOINTER)&vectorValue,
            (SQLLEN)(sizeof(SQL_SS_VECTOR_STRUCT) + floatArray.size() * sizeof(float))
        );

        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
            // handle error
        }

        // Finalize parameter transfer
        rc = SQLParamData(hStmt, &pParamToken);
    }

Deskriptormetadaten

Wenn Sie die Vektorunterstützung aktivieren, macht der Microsoft ODBC-Treiber für SQL Server Vektormetadaten über standardmäßige ODBC-Deskriptor-APIs verfügbar. Anwendungen können Deskriptorinformationen verwenden, um Vektorschemadetails zu ermitteln, Puffergrößen zu berechnen und Bindungen für Parameter und Resultsets ordnungsgemäß zu konfigurieren.

Deskriptorfeldwerte für den Vektor

Die folgende Tabelle enthält eine Zusammenfassung der Deskriptorfeldwerte für SQL Server-Vektorspalten und -Parameter.

Deskriptorfeld Wert Description
SQL_DESC_TYPE SQL_SS_VECTOR (-156) Basis-SQL-Datentypbezeichner
SQL_DESC_CONCISE_TYPE SQL_SS_VECTOR Präziser SQL-Datentyp
SQL_DESC_TYPE_NAME vector SQL-Typname
SQL_DESC_LOCAL_TYPE_NAME vector Name des lokalen Treibertyps
SQL_DESC_LENGTH sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * sizeof(float)) Logische Größe des Vektorwerts
SQL_DESC_OCTET_LENGTH Identisch mit SQL_DESC_LENGTH Physische Größe in Byte
SQL_DESC_PRECISION Identisch mit SQL_DESC_LENGTH Wird verwendet, um die Größe des Vektors zu melden
SQL_DESC_SCALE SQL_VECTOR_TYPE_FLOAT32 oder SQL_VECTOR_TYPE_FLOAT16 Vektorbasiselementtyp
SQL_CA_SS_VECTOR_DIMENSION dimension Anzahl der Elemente im Vektor
SQL_DESC_DISPLAY_SIZE dimension * VECTOR_FLOAT32_TO_CHAR_JSON_MAX_SIZE Maximale JSON-Anzeigelänge
SQL_DESC_FIXED_PREC_SCALE SQL_FALSE Vektor hat keine feste Genauigkeit/Skalierung
SQL_DESC_NULLABLE SQL_NULLABLE Vektorspalten erlauben NULL Werte
SQL_DESC_NUM_PREC_RADIX 0 Nicht numerischer Typ
SQL_DESC_SEARCHABLE SQL_PRED_NONE Nicht verwendbar in Prädikaten
SQL_DESC_UNSIGNED SQL_TRUE Elementtyp ist nicht signiert
SQL_DESC_AUTO_UNIQUE_VALUE SQL_FALSE Nicht autounique
SQL_DESC_CASE_SENSITIVE SQL_FALSE Groß-/Kleinschreibung nicht beachtet
SQL_DESC_UPDATABLE SQL_ATTR_READWRITE_UNKNOWN Aktualisierbarkeit unbekannt

SQL_DESC_LENGTH, SQL_DESC_OCTET_LENGTH, und SQL_DESC_PRECISION alle beschreiben den clientseitigen Puffer, sodass sie + (Dimension * sizeof(float)) sowohl für eine float16 Spalte als auch für eine float32 Eins melden sizeof(SQL_SS_VECTOR_STRUCT) . Die beiden unterscheiden sich nur in der Anzahl der Bytes, die SQL Server speichert und überträgt.

SQL_DESC_SCALE ist das einzige Deskriptorfeld, das die Basistypen unterscheidet. Durch das Lesen erkennt eine Anwendung heraus, ob eine Spalte oder float32float16ist.

SQLColAttribute für Vektordimension

Ab Version 18.7.1.1 SQL_CA_SS_VECTOR_DIMENSION wird die Elementanzahl einer Vektorspalte direkt zurückgegeben, sodass eine Anwendung sie nicht mehr aus einem Längenfeld ableiten muss:

    SQLLEN dimension = 0;
    SQLColAttribute(hStmt, col, SQL_CA_SS_VECTOR_DIMENSION, NULL, 0, NULL, &dimension);

    SQLLEN baseType = 0;
    SQLColAttribute(hStmt, col, SQL_DESC_SCALE, NULL, 0, NULL, &baseType);
    /* baseType is SQL_VECTOR_TYPE_FLOAT32 or SQL_VECTOR_TYPE_FLOAT16 */

Du kannst auch einen Anwendungsdeskriptor oder den IPD für einen Vektorparameter einstellen SQL_CA_SS_VECTOR_DIMENSION . Setzt man sie auf einen anderen Parametertyp, erhält man einen Fehler mit einem ungültigen Deskriptorfeld.

SQLDescribeCol

Wenn Sie SQLDescribeCol für eine Vektorspalte aufrufen:

  • DataType ist SQL_SS_VECTOR
  • ColumnSize entspricht SQL_DESC_PRECISION
  • DecimalDigits ist der Basiselementtypindikator, keine numerische Skala: 0 für float32 und 1 für float16
  • Nullable ist SQL_NULLABLE

Die gemeldete Spaltengröße stellt die systemeigene Nutzlastgröße des Vektors dar: sizeof(SQL_SS_VECTOR_STRUCT) + (Dimension * sizeof(float))

SQLDescribeParam

Wenn Sie SQLDescribeParam für einen Vektorparameter verwenden:

  • DataType ist SQL_SS_VECTOR
  • ColumnSize entspricht der Größe der nativen Vektornutzlast
  • DecimalDigits ist der Basiselementtypindikator, keine numerische Skala: 0 für float32 und 1 für float16
  • Nullable ist SQL_NULLABLE

Mit diesen Informationen können Anwendungen Parameterpuffer vor der Bindung richtig zuordnen.

SQLColAttribute

  • Verwenden Sie SQLColAttribute(hstmt, ColumnNumber, SQL_DESC_OCTET_LENGTH, ...), um die genaue Bytelänge der Vektornutzlast abzurufen. SQL_DESC_LENGTH und SQL_DESC_PRECISION können treiberspezifische Werte enthalten. Bevorzugen Sie für die Byteanzahl SQL_DESC_OCTET_LENGTH.

    • NULL-Handhabung: Wenn eine Spalte NULL ist, wird SQLColAttribute (oder der StrLen_or_IndPtr, der mit SQLBindCol verwendet wird) SQL_NULL_DATA zurückgegeben. Überprüfen Sie, ob SQL_NULL_DATA vorhanden ist, bevor Sie zurückgegebene Längen oder Puffer verwenden.

Massenkopie (BCP)

Sie können Vektorspalten über BCP-Dateien und die bcp_bind API wie andere Datentypen massenimportieren und exportieren. Derzeit unterstützt der Vektorimport und -export nur systemeigenes Format (SQLVECTOR) oder varbinary (SQLBINARY), jedoch kein Zeichenformat. Die Konvertierung zwischen dem Vektortyp und dem Zeichentyp wird nicht unterstützt.

Der Bulk-Copy berücksichtigt das gleiche Unterstützungsniveau wie der Rest des Treibers. Eine Spalte erfordert eine Verbindung, die float16 bei ausgehandelt wird vectorTypeSupport=v2. Im BCP-Utility verwenden -z0 Sie für float32 und -z1 für float16. Weitere Informationen finden Sie im Bcp-Hilfsprogramm.

Weitere Informationen zum Typtoken, zur Standardpräfixlänge und zur Standardfeldlänge für den Vektor finden Sie unter "Dateispeichertyp", "Präfixlänge" und " Feldlänge".

bcp_gettypename

Wenn Sie bcp_gettypename verwenden, um den SQL-Typnamen des Vektors zu erhalten, wird das BCP-Typtoken (SQLVECTOR) und "vector" zurückgegeben.

bcp_bind

Verwenden Sie bcp_bind, um Programmvariablen in eine Vektorspalte einzufügen.

Typischer Anruf:

RETCODE bcp_bind (
        HDBC hdbc,
        LPCBYTE pData,
        INT cbIndicator,
        DBINT cbData,
        LPCBYTE pTerm,
        INT cbTerm,
        INT eDataType,
        INT idxServerCol);
  • pData: wenn cbIndicator null ist, enthält einen Zeiger auf SQL_SS_VECTOR_STRUCT Daten, mit Float-Arraydaten darin (vectorStruct.data.f32 Feld). Wenn cbIndicator ungleich null ist, wird der Indikator direkt vor den Daten im Arbeitsspeicher angezeigt. Verweist also pData auf einen Puffer, der zuerst über einen in cbIndicator Bytes angegebenen Längenindikator verfügt, gefolgt von der Vektorstruktur.
  • cbData: wenn angegeben, muss der Wert genau gleich - sizeof(SQL_SS_VECTOR_STRUCT) + (sizeof(float) * Dimension) sein. Wenn dies nicht der Fall ist, tritt ein Fehler auf. Dies gilt für beide Basistypen, da der gebundene Puffer in beide Richtungen Werte enthält float32 .
  • eDataType: SQLVECTOR oder SQLBINARY

Setze das type Feld der Struktur auf den Basistyp der Säule. Für eine float16 Spalte wandelt der Treiber das gebundene float32 Array beim Erstellen der Drahtnutzlast auf halbe Genauigkeit um, sodass eine Datendatei im nativen Format zwei Bytes pro Element enthält.

Beim Importieren von Daten in eine Vektorspalte, indem Sie bcp_bind verwenden, setzen Sie eDataType auf SQLVECTOR oder SQLBINARY. In beiden Fällen müssen Sie Daten in Form von SQL_SS_VECTOR_STRUCT.

Problembehandlung und Tipps

  • Wenn SQLGetTypeInfoVECTORnicht auflistet, sollten Sie als Alternative die Vektoren als varchar speichern.
  • Requested vector base type is not supported for the negotiated vector version. bedeutet, dass ein float16 Wert auf eine Verbindung verwendet wurde, die bei ausgehandelt wurde vectorTypeSupport=v1. Verbinden Sie sich wieder mit v2.
  • Provided buffer length too small/large.Die Mittel BufferLength stimmten nicht exakt mit + (Dimension * sizeof(float)) überein sizeof(SQL_SS_VECTOR_STRUCT) . Überprüfen Sie, dass der Puffer mit sizeof(float) einer Spalte statt zwei Bytes pro Element belegt ist.float16
  • Invalid vector dimension bedeutet, die Dimension ist null oder übersteigt das Maximum für den Basistyp: 1.998 für float32 und 3.996 für float16.
  • Invalid vector base type bedeutet, dass das type Feld einen anderen Wert als SQL_VECTOR_TYPE_FLOAT32 oder SQL_VECTOR_TYPE_FLOAT16hatte. Eine null-initialisierte Struktur setzt standardmäßig auf float32.
  • Wenn eine float16 Spalte als varchar(max) mit einem JSON-Array gemeldet wird, hat der Server die PREVIEW_FEATURES Datenbank-Scoped-Konfiguration nicht aktiviert oder die Verbindung wurde um eine Ebene niedriger als v2ausgehandelt.