Share via


Verwendungen von ODBC-Tabellenwertparametern

Gilt für:SQL ServerAzure SQL-DatenbankAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics 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 Tabellenwertparameter selbst wird mithilfe von SQLBindParameter zusammen mit den anderen Parametern 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 ColumnSize-Parameter von SQLBindParameter für einen Tabellenwertparameter 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 der zugehörige BufferLength verwendet, um bei Bedarf den Typnamen des Tabellenwertparameters zu übergeben. Der Typname wird nicht für gespeicherte Prozeduraufrufe benötigt, er ist jedoch für SQL-Anweisungen erforderlich.

Wenn ein Tabellenwertparametertypname 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 Tabellenwertparametertypnamen mithilfe von SQLSetDescField angeben, können Sie ein Literal verwenden, das der Erstellung der Anwendung entspricht. Der ODBC-Treiber-Manager führt die eventuell erforderliche Unicode-Konvertierung aus.

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

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

Beispielcode für dieses Szenario finden Sie in der Prozedur demo_fixed_TVP_bindingunter Verwenden 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 reagiert auf SQLExecute oder SQLExecuteDirect in der üblichen Weise für Data-at-Execution-Parameter, d. h., indem er SQL_NEED_DATA zurückgibt. 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, die nicht tabellenwertgebunden sind: Jede Tabellenwertparameterspalte kann ihre tatsächliche Datenlänge angeben, SQL_NULL_DATA oder daten bei der Ausführung über ihren Längen-/Indikatorpuffer angeben. Tabellenwertparameterspaltenwerte können wie gewohnt durch wiederholte Aufrufe an SQLPutData übergeben werden, wenn ein Zeichen- oder Binärwert 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. Zu diesem Zeitpunkt überspringt der Treiber Tabellenwertparameterspalten und wechselt zum nächsten tatsächlichen gespeicherten Prozedurparameter. 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 von SQLParamData und dem Aufrufen von SQLPutData(hstmt, NULL, n) für einen Tabellenwertparameter muss die Anwendung Tabellenwert-Parameterkomponentenspaltendaten und Indikatorpufferinhalte für die nächsten Zeilen festlegen, die an den Server übergeben werden sollen.

Beispielcode für dieses Szenario befindet sich in der Routine demo_variable_TVP_binding unter Verwenden von Table-Valued-Parametern (ODBC).

Abrufen von Tabellenwertparameter-Metadaten aus dem Systemkatalog

Wenn eine Anwendung SQLProcedureColumns für eine Prozedur mit Tabellenwertparametern aufruft, wird DATA_TYPE als SQL_SS_TABLE zurückgegeben, und TYPE_NAME ist der Name des Tabellentyps für den Tabellenwertparameter. 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 gibt den Namen des Schemas zurück, 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 von ODBC selbst vorgeschriebenen Spalten.

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 wie für persistente Tabellen, Systemtabellen und Sichten zu bestimmen. 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 zu bestimmen wie für persistente Tabellen. Sie muss jedoch zuerst SQL_SOPT_SS_NAME_SCOPE festlegen, um anzugeben, dass sie mit Tabellentypen und nicht mit tatsächlichen Tabellen arbeitet. SQLPrimaryKeys kann auch mit Tabellentypen verwendet werden, wiederum mit SQL_SOPT_SS_NAME_SCOPE.

Beispielcode für dieses Szenario befindet sich in der Routine demo_metadata_from_catalog_APIs unter Verwenden von Table-Valued-Parametern (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 zum Abrufen des Katalogs bzw. Schemas verwendet.

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, die benutzerdefinierten CLR-Typparametern zugeordnet sind. 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, um Spaltenmetadaten für einen Tabellenwertparameter auch in diesem Szenario abzurufen, 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 Use Table-Valued Parameters (ODBC).

Weitere Informationen

Tabellenwertparameter (ODBC)