Verwendungen von ODBC-Tabellenwertparametern

Gilt für: SQL Server Azure SQL-Datenbank Azure SQL verwaltete Instanz Azure Synapse Analytics Analytics Platform System (PDW)

In diesem Thema werden die wichtigsten Benutzerszenarien für die Verwendung von Tabellenwertparametern mit ODBC erläutert:

  • Tabellenwertparameter mit vollständig gebundenen mehrzeiligen Puffern (Senden von Daten als Tabellenwertparameter mit allen Werten im Arbeitsspeicher)

  • Tabellenwertparameter mit Zeilenstreaming (Senden von Daten als Tabellenwertparameter mithilfe von Data-at-Execution)

  • Abrufen von Tabellenwertparameter-Metadaten aus dem Systemkatalog

  • Abrufen von Tabellenwertparameter-Metadaten für eine vorbereitete Anweisung

Tabellenwertparameter mit vollständig gebundenen mehrzeiligen Puffern (Senden von Daten als Tabellenwertparameter mit allen Werten im Arbeitsspeicher)

Bei der Verwendung mit vollständig gebundenen mehrzeiligen Puffern sind alle Parameterwerte im Arbeitsspeicher verfügbar. Dies ist beispielsweise für eine OLTP-Transaktion typisch, bei der Tabellenwertparameter in eine einzeln gespeicherte Prozedur gepackt werden können. Ohne Tabellenwertparameter wären mehrere Serveraufrufe oder die dynamische Generierung eines komplexen Batches mit mehreren Anweisungen erforderlich.

Der Parameter mit Tabellenwert selbst wird zusammen mit den anderen Parametern mithilfe von SQLBindParameter gebunden. Nachdem alle Parameter gebunden wurden, legt die Anwendung das Parameterfokusattribut SQL_SOPT_SS_PARAM_FOCUS für jeden Tabellenwertparameter fest und ruft SQLBindParameter für die Spalten des Tabellenwertparameters auf.

Der Servertyp für einen Tabellenwertparameter ist ein neuer SQL Server-spezifischer Typ, SQL_SS_TABLE. Der C-Bindungstyp für SQL_SS_TABLE muss stets SQL_C_DEFAULT sein. Für den gebundenen Parameter des Tabellenwertparameters werden keine Daten übertragen. Dieser wird zur Übergabe von Tabellenmetadaten und zur Steuerung der Datenübergabe in die einzelnen Spalten des Tabellenwertparameters verwendet.

Die Länge des Tabellenwertparameters ist auf die Anzahl der an den Server gesendeten Zeilen festgelegt. Der Parameter ColumnSize von SQLBindParameter für einen Parameter mit Tabellenwert gibt die maximale Anzahl von Zeilen an, die gesendet werden können. Dies ist die Arraygröße der Spaltenpuffer. ParameterValuePtr ist der Parameterpuffer. Für einen Tabellenwertparameter in SQLBindParameter werden ParameterValuePtr und dessen zugeordneter BufferLength verwendet, um den Typnamen des Tabellenwertparameters bei Bedarf zu übergeben. Der Typname wird nicht für gespeicherte Prozeduraufrufe benötigt, er ist jedoch für SQL-Anweisungen erforderlich.

Wenn ein Tabellenwert-Parametertypname für einen Aufruf von SQLBindParameter angegeben wird, muss er immer als Unicode-Wert angegeben werden, auch in Anwendungen, die als ANSI-Anwendungen erstellt werden. Wenn Sie einen Tabellenwert-Parametertypnamen mithilfe von SQLSetDescField angeben, können Sie ein Literal verwenden, das der Art und Weise entspricht, wie die Anwendung erstellt wird. Der ODBC-Treiber-Manager führt die eventuell erforderliche Unicode-Konvertierung aus.

Metadaten für Tabellenwertparameter und Tabellenwertparameterspalten können einzeln und explizit mithilfe von SQLGetDescRec, SQLSetDescRec, SQLGetDescField, SQLGetDescField und SQLSetDescField bearbeitet werden. Das Überladen von SQLBindParameter ist jedoch in der Regel praktischer und erfordert in den meisten Fällen keinen expliziten Deskriptorzugriff. Dieser Ansatz entspricht der Definition von SQLBindParameter für andere Datentypen, mit der Ausnahme, dass für einen Tabellenwertparameter die betroffenen Deskriptorfelder geringfügig unterschiedlich sind.

Manchmal verwendet eine Anwendung einen Tabellenwertparameter mit dynamischem SQL, und der Name des Tabellenwertparameters muss bereitgestellt werden. Wenn dies der Fall ist und der Parameter mit Tabellenwert nicht im aktuellen Standardschema für die Verbindung definiert ist, muss SQL_CA_SS_SCHEMA_NAME mithilfe von SQLSetDescField festgelegt werden. Da Tabellentypdefinitionen und Tabellenwertparameter in derselben Datenbank enthalten sein müssen, darf SQL_CA_SS_CATALOG_NAME nicht festgelegt werden, wenn die Anwendung Tabellenwertparameter verwendet. Andernfalls meldet SQLSetDescField einen Fehler.

Beispielcode für dieses Szenario befindet sich in der Prozedur demo_fixed_TVP_binding in "Table-Valued Parameters (ODBC)".

Tabellenwertparameter mit Zeilenstreaming (Senden von Daten als Tabellenwertparameter mithilfe von Data-at-Execution)

In diesem Szenario stellt die Anwendung dem Treiber Zeilen nach Anforderung bereit. Diese werden an den Server gestreamt. Hierdurch wird das Puffern aller Zeilen im Arbeitsspeicher vermieden. Dies ist für Masseneinfügungs-/-updateszenarien repräsentativ. Tabellenwertparameter bieten eine Leistungsfähigkeit, die zwischen Parameterarrays und Massenkopieren liegt. Tabellenwertparameter sind ebenso einfach zu programmieren wie Parameterarrays, sie bieten jedoch eine größere Flexibilität auf dem Server.

Das Binden des Tabellenwertparameters und der zugehörigen Spalten erfolgt wie im vorherigen Abschnitt "Tabellenwertparameter mit vollständig gebundenen mehrzeiligen Puffern" beschrieben, der Längenindikator des Tabellenwertparameters selbst wird jedoch auf SQL_DATA_AT_EXEC festgelegt. Der Treiber antwortet auf SQLExecute oder SQLExecuteDirect in der üblichen Weise für Data-at-execution-Parameter, d. h. durch Zurückgeben von SQL_NEED_DATA. Wenn der Treiber bereit ist, Daten für einen Tabellenwertparameter zu akzeptieren, gibt SQLParamData den Wert von ParameterValuePtr in SQLBindParameter zurück.

Eine Anwendung verwendet SQLPutData für einen Tabellenwertparameter, um die Verfügbarkeit von Daten für Spalten mit Tabellenwertparametern anzugeben. Wenn SQLPutData für einen Tabellenwertparameter aufgerufen wird, muss DataPtr immer null sein, und StrLen_or_Ind muss entweder 0 oder eine Zahl kleiner oder gleich der Arraygröße sein, die für Tabellenwertparameterpuffer (der ColumnSize-Parameter von SQLBindParameter) angegeben ist. Der Wert 0 gibt an, dass keine weiteren Zeilen für den Tabellenwertparameter vorhanden sind, und der Treiber fährt mit der Verarbeitung des nächsten tatsächlichen Prozedurparameters fort. Wenn StrLen_or_Ind nicht 0 ist, verarbeitet der Treiber die tabellenwertigen Parameterkomponentenspalten auf die gleiche Weise wie parametergebundene Parameter mit Nicht-Tabellenwert: Jede Parameterspalte mit Tabellenwert kann die tatsächliche Datenlänge, SQL_NULL_DATA angeben oder Daten zur Ausführung über den Längen-/Indikatorpuffer angeben. Spaltenwerte für Tabellenwerte können von wiederholten Aufrufen von SQLPutData wie gewohnt übergeben werden, wenn ein Zeichen oder binärer Wert in Teilen übergeben werden soll.

Nachdem alle Tabellenwertparameter-Spalten verarbeitet wurden, kehrt der Treiber zum Tabellenwertparameter zurück, um weitere Tabellenwertparameter-Datenzeilen zu verarbeiten. Bei Data-at-Execution-Tabellenwertparametern führt der Treiber daher nicht den üblichen sequenziellen Scan gebundener Parameter durch. Ein gebundener Tabellenwertparameter wird abgefragt, bis SQLPutData mit StrLen_Or_IndPtr gleich 0 aufgerufen wird, wobei der Treiber Tabellenwertparameterspalten überspringt und zum nächsten tatsächlich gespeicherten Prozedurparameter wechselt. Wenn SQLPutData einen Indikatorwert übergibt, der größer oder gleich 1 ist, verarbeitet der Treiber Tabellenwertparameterspalten und -zeilen sequenziell, bis er Werte für alle gebundenen Zeilen und Spalten enthält. Anschließend kehrt der Treiber zum Tabellenwertparameter zurück. Zwischen dem Empfangen des Tokens für den Tabellenwertparameter aus SQLParamData und dem Aufrufen von SQLPutData(hstmt, NULL, n) für einen Tabellenwertparameter muss die Anwendung Tabellenwertparameter-Spaltendaten und Indikatorpufferinhalte für die nächste Zeile oder Zeile festlegen, die an den Server übergeben werden soll.

Beispielcode für dieses Szenario befindet sich in der Routine demo_variable_TVP_binding in "Table-Valued Parameters (ODBC)".

Abrufen von Tabellenwertparameter-Metadaten aus dem Systemkatalog

Wenn eine Anwendung SQLProcedureColumns für eine Prozedur mit Parameterparametern mit Tabellenwert aufruft, wird DATA_TYPE als SQL_SS_TABLE zurückgegeben, und TYPE_NAME ist der Name des Tabellentyps für den Parameter mit Tabellenwert. Dem von SQLProcedureColumns zurückgegebenen Resultset werden zwei zusätzliche Spalten hinzugefügt: SS_TYPE_CATALOG_NAME gibt den Namen des Katalogs zurück, in dem der Tabellentyp des Tabellenwertparameters definiert ist, und SS_TYPE_SCHEMA_NAME den Namen des Schemas zurückgibt, in dem der Tabellentyp des Tabellenwertparameters definiert ist. In Übereinstimmung mit der ODBC-Spezifikation werden SS_TYPE_CATALOG_NAME und SS_TYPE_SCHEMA_NAME vor allen Treiberspezifischen Spalten angezeigt, die in früheren Versionen von SQL Server hinzugefügt wurden, und nach allen Spalten, die von ODBC selbst vorgeschrieben wurden.

Die neuen Spalten werden nicht nur für Tabellenwertparameter, sondern auch für Parameter des CLR-benutzerdefinierten Typs aufgefüllt. Die vorhandenen Schema- und Katalogspalten von Parametern des benutzerdefinierten Typs werden noch aufgefüllt, in Zukunft wird die Anwendungsentwicklung jedoch durch gemeinsame Schema- und Katalogspalten für Datentypen, die diese erfordern, erleichtert. (Beachten Sie, dass XML-Schemaauflistungen einige Unterschiede aufweisen und nicht in dieser Änderung enthalten sind.)

Eine Anwendung verwendet SQLTables, um die Namen von Tabellentypen auf die gleiche Weise zu bestimmen wie für persistente Tabellen, Systemtabellen und Ansichten. Die Einführung eines neuen Tabellentyps ? TABLE TYPE ? ermöglicht es einer Anwendung, Tabellentypen zu identifizieren, die mit Tabellenwertparametern verbunden sind. Tabellentypen und reguläre Tabellen verwenden unterschiedliche Namespaces. Daher können Sie den gleichen Namen für einen Tabellentyp und eine tatsächliche Tabelle verwenden. Für diesen Fall wurde ein neues Anweisungsattribut ? SQL_SOPT_SS_NAME_SCOPE ? eingeführt. Dieses Attribut gibt an, ob SQLTables und andere Katalogfunktionen, die einen Tabellennamen als Parameter verwenden, den Tabellennamen als Namen einer tatsächlichen Tabelle oder den Namen eines Tabellentyps interpretieren sollen.

Eine Anwendung verwendet SQLColumns, um die Spalten für einen Tabellentyp auf die gleiche Weise wie für persistente Tabellen zu bestimmen, muss jedoch zuerst SQL_SOPT_SS_NAME_SCOPE festlegen, um anzugeben, dass sie mit Tabellentypen und nicht mit tatsächlichen Tabellen arbeitet. SQLPrimaryKeys können auch mit Tabellentypen verwendet werden, wieder mit SQL_SOPT_SS_NAME_SCOPE.

Beispielcode für dieses Szenario befindet sich in der Routine demo_metadata_from_catalog_APIs in "Table-Valued Parameters (ODBC)".

Abrufen von Tabellenwertparameter-Metadaten für eine vorbereitete Anweisung

In diesem Szenario verwendet eine Anwendung SQLNumParameters und SQLDescribeParam, um Metadaten für Tabellenwertparameter abzurufen.

Das IPD-Feld SQL_CA_SS_TYPE_NAME wird verwendet, um den Typnamen für den Tabellenwertparameter abzurufen. Die IPD-Felder SQL_CA_SS_SCHEMA_NAME und SQL_CA_SS_CATALOG_NAME werden verwendet, um den Katalog bzw. das Schema abzurufen.

Tabellentypdefinitionen und Tabellenwertparameter müssen sich in der gleichen Datenbank befinden. SQLSetDescField meldet einen Fehler, wenn eine Anwendung bei Verwendung von Tabellenwertparametern SQL_CA_SS_CATALOG_NAME festlegt.

SQL_CA_SS_CATALOG_NAME und SQL_CA_SS_SCHEMA_NAME können auch verwendet werden, um den Katalog und das Schema abzurufen, das mit benutzerdefinierten CLR-Typparametern verknüpft ist. SQL_CA_SS_CATALOG_NAME und SQL_CA_SS_SCHEMA_NAME sind Alternativen zu den vorhandenen typspezifischen Katalogschemaattributen für CLR-UDT-Typen.

Eine Anwendung verwendet SQLColumns zum Abrufen von Spaltenmetadaten für einen Tabellenwertparameter in diesem Szenario, da SQLDescribeParam keine Metadaten für die Spalten einer Tabellenwertparameterspalte zurückgibt.

Beispielcode für diesen Anwendungsfall befindet sich in der Routine demo_metadata_from_prepared_statement in "Table-Valued Parameters (ODBC)".

Weitere Informationen

Tabellenwertparameter (ODBC)