Bindung und Datenübertragung von Tabellenwertparametern und Spaltenwerten
Tabellenwertparameter müssen ebenso wie andere Parameter gebunden werden, bevor sie an den Server übergeben werden. Die Anwendung bindet Tabellenwertparameter auf dieselbe Weise wie andere Parameter, nämlich mit SQLBindParameter oder entsprechenden Aufrufen von SQLSetDescField oder SQLSetDescRec. Tabellenwertparameter haben den Serverdatentyp SQL_SS_TABLE. Der C-Typ kann entweder als SQL_C_DEFAULT oder SQL_C_BINARY angegeben werden.
In SQL Server 2008 oder höher werden nur Eingabe-Tabellenwertparameter unterstützt. Daher resultiert jeder Versuch, SQL_DESC_PARAMETER_TYPE auf einen anderen Wert als SQL_PARAM_INPUT festzulegen, in der Rückgabe von SQL_ERROR mit SQLSTATE = HY105 und der Meldung "Der Parametertyp ist ungültig".
Gesamten Tabellenwertparameter-Spalten können mit dem Attribut SQL_CA_SS_COL_HAS_DEFAULT_VALUE Standardwerte zugewiesen werden. Einzelnen Tabellenwertparameter-Spaltenwerten können allerdings mit SQLBindParameter und der Angabe von SQL_DEFAULT_PARAM in StrLen_or_IndPtr keine Standardwerte zugewiesen werden. Tabellenwertparameter als Ganzes können mit SQLBindParameter und der Angabe von SQL_DEFAULT_PARAM in StrLen_or_IndPtr nicht auf einen Standardwert festgelegt werden. Wenn diese Regeln nicht befolgt werden, gibt SQLExecute oder SQLExecDirect SQL_ERROR zurück. Es wird ein Diagnosedatensatz mit SQLSTATE=07S01 und der Meldung "Verwendung des Standardparameters ungültig für Parameter <p>" generiert, wobei <p> für die Ordnungszahl des Tabellenwertparameters in der Abfrageanweisung steht.
Nachdem die Anwendung den Tabellenwertparameter gebunden hat, muss sie jede einzelne Tabellenwertparameter-Spalte binden. Hierzu ruft die Anwendung zuerst SQLSetStmtAttr auf, um SQL_SOPT_SS_PARAM_FOCUS auf die Ordnungszahl des Tabellenwertparameters festzulegen. Dann bindet die Anwendung die Spalten des Tabellenwertparameters durch Aufrufe der folgenden Routinen: SQLBindParameter, SQLSetDescRec und SQLSetDescField. Durch die Festlegung von SQL_SOPT_SS_PARAM_FOCUS auf 0 wird das übliche Verhalten von SQLBindParameter, SQLSetDescRec und SQLSetDescField wiederherstellt, sodass sich diese Routinen wieder auf Parameter der obersten Ebene beziehen..
Für den Tabellenwertparameter an sich werden keine Daten gesendet oder empfangen, die Daten werden für die einzelnen Spalten, aus denen er sich zusammensetzt, gesendet und empfangen. Weil es sich bei Tabellenwertparametern um Pseudospalten handelt, wird mit den Parametern für SQLBindParameter auf andere Attribute als andere Datentypen verwiesen. Die Parameterangaben haben folgende Bedeutung:
Parameter |
Verknüpftes Attribut für Parametertypen, die keine Tabellenwertparameter sind, einschließlich Spalten |
Verknüpftes Attribut für Tabellenwertparameter |
---|---|---|
InputOutputType |
SQL_DESC_PARAMETER_TYPE in IPD Für Tabellenwertparameter-Spalten muss diese Angabe der Angabe für den Tabellenwertparameter selbst entsprechen. |
SQL_DESC_PARAMETER_TYPE in IPD Hier muss SQL_PARAM_INPUT angegeben werden. |
ValueType |
SQL_DESC_TYPE, SQL_DESC_CONCISE_TYPE in APD |
SQL_DESC_TYPE, SQL_DESC_CONCISE_TYPE in APD Hier muss SQL_C_DEFAULT oder SQL_C_BINARY angegeben werden. |
ParameterType |
SQL_DESC_TYPE, SQL_DESC_CONCISE_TYPE in IPD |
SQL_DESC_TYPE, SQL_DESC_CONCISE_TYPE in IPD Hier muss SQL_SS_TABLE angegeben werden. |
ColumnSize |
SQL_DESC_LENGTH oder SQL_DESC_PRECISION in IPD Diese Angabe hängt vom Wert für ParameterType ab. |
SQL_DESC_ARRAY_SIZE Kann auch mit SQL_ATTR_PARAM_SET_SIZE festgelegt werden, wenn der Parameterfokus auf den Tabellenwertparameter festgelegt wurde. Bei einem Tabellenwertparameter ist dies die Anzahl von Zeilen in den Tabellenwertparameter-Spaltenpuffern. |
DecimalDigits |
SQL_DESC_PRECISION oder SQL_DESC_SCALE in IPD |
Wird nicht verwendet. Diese Angabe muss 0 sein. Wenn dieser Parameter ungleich 0 ist, dann gibt SQLBindParameter SQL_ERROR zurück, und es wird ein Diagnosedatensatz mit SQLSTATE= HY104 und der Meldung "Ungültige Genauigkeit oder Dezimalstellenanzahl" generiert. |
ParameterValuePtr |
SQL_DESC_DATA_PTR in APD |
SQL_CA_SS_TYPE_NAME Dies ist ein optionales Attribut für gespeicherte Prozeduren, und NULL kann angegeben werden, wenn es nicht erforderlich ist. Es muss für SQL-Anweisungen angegeben werden, die keine Prozeduraufrufe sind. Dieser Parameter dient als eindeutiger Wert, anhand dessen die Anwendung den betreffenden Tabellenwertparameter bei Verwendung einer variablen Zeilenbindung identifizieren kann. Weitere Informationen finden Sie im Abschnitt "Variable Tabellenwertparameter-Zeilenbindung" weiter unten in diesem Thema. Wenn bei einem Aufruf von SQLBindParameter der Name des Tabellenwertparametertyps angegeben wird, muss dieser auch bei Anwendungen, die als ANSI-Anwendungen erstellt wurden, als Unicode-Wert angegeben werden. Der für den Parameter StrLen_or_IndPtr verwendete Wert sollte entweder SQL_NTS oder die Zeichenfolgenlänge des Namens multipliziert mit sizeof(WCHAR) sein. |
BufferLength |
SQL_DESC_OCTET_LENGTH in APD |
Die Länge des Typnamens des Tabellenwertparameters in Byte Kann SQL_NTS sein, wenn der Typname NULL-termininiert ist, oder 0, wenn der Typname des Tabellenwertparameters nicht erforderlich ist. |
StrLen_or_IndPtr |
SQL_DESC_OCTET_LENGTH_PTR in APD |
SQL_DESC_OCTET_LENGTH_PTR in APD Für Tabellenwertparameter wird hier die Zeilenanzahl statt die Datenlänge angegeben. |
Zwei Datenübertragungsmodi werden für Tabellenwertparameter unterstützt: feste Zeilenbindung und variable Zeilenbindung.
Feste Tabellenwertparameter-Zeilenbindung
Bei der festen Zeilenbindung ordnet die Anwendung Puffer (oder Pufferarrays) zu, die groß genug sind, um alle Eingabespaltenwerte aufnehmen zu können. Die Anwendung führt Folgendes aus:
Sie bindet alle Parameter durch Aufrufe von SQLBindParameterSQLSetDescRec oder SQLSetDescField.
- Sie legt SQL_DESC_ARRAY_SIZE auf die maximale Anzahl von Zeilen fest, die für jeden Tabellenwertparameter übertragen werden können. Der SQLBindParameter-Aufruf kann hierzu verwendet werden.
Sie ruft SQLSetStmtAttr auf, um SQL_SOPT_SS_PARAM_FOCUS auf die Ordnungszahl der einzelnen Tabellenwertparameter festzulegen.
Sie bindet bei jedem Tabellenwertparameter die Tabellenwertparameter-Spalten durch Aufrufe von SQLBindParameter SQLSetDescRec oder SQLSetDescField.
Sie ruft für jede Tabellenwertparameter-Spalte, die über Standardwerte verfügen soll, SQLSetDescField auf, um SQL_CA_SS_COL_HAS_DEFAULT_VALUE auf 1 festzulegen.
Sie ruft SQLSetStmtAttr auf, um SQL_SOPT_SS_PARAM_FOCUS auf 0 festzulegen. Dies muss vor dem Aufruf von SQLExecute oder SQLExecDirect geschehen. Andernfalls wird SQL_ERROR zurückgegeben, und es wird ein Diagnosedatensatz mit SQLSTATE=HY024 und der Meldung "Ungültiger Attributwert, SQL_SOPT_SS_PARAM_FOCUS (muss zur Laufzeit Null sein)" generiert.
Legt StrLen_or_IndPtr oder SQL_DESC_OCTET_LENGTH_PTR für einen Tabellenwertparameter ohne Zeilen auf SQL_DEFAULT_PARAM und für einen Tabellenwertparameter mit Zeilen auf die Anzahl der Zeilen fest, die beim nächsten Aufruf von SQLExecute oder SQLExecDirect übertragen werden soll. StrLen_or_IndPtr oder SQL_DESC_OCTET_LENGTH_PTR kann für einen Tabellenwertparameter nicht auf SQL_NULL_DATA festgelegt werden, da Tabellenwertparameter nicht auf NULL festlegbar sind (die einzelnen Spalten, aus denen ein Tabellenwertparameter besteht, können allerdings NULL sein). Wenn hierfür ein ungültiger Wert gewählt wird, gibt SQLExecute bzw. SQLExecDirect SQL_ERROR zurück, und es wird ein Diagnosedatensatz mit SQLSTATE=HY090 und der Meldung "Ungültige Zeichenfolgen- oder Pufferlänge für Parameter <p>" generiert, wobei p für die Parameterzahl steht.
Sie ruft SQLExecute oder SQLExecDirect auf.
Eingabewerte für Tabellenwertparameter-Spalten können schrittweise übergeben werden, wenn StrLen_or_IndPtr für die Spalte auf SQL_LEN_DATA_AT_EXEC(length) oder SQL_DATA_AT_EXEC festgelegt wird. Dies gleicht der Übergabe einzelner Werte bei Verwendung von Parameterarrays. Wie bei allen Data-at-Execution-Parametern (Daten-in-Ausführung) gibt SQLParamData nicht an, für welche Zeile des Arrays der Treiber Daten anfordert. Die Anwendung muss dies herausfinden. Die Anwendung kann keine Annahmen über die Reihenfolge treffen, in der der Treiber Werte anfordert.
Variable Tabellenwertparameter-Zeilenbindung
Bei einer variablen Zeilenbildung werden die Zeilen zur Laufzeit in Batches übertragen, und die Anwendung übergibt die Zeilen bei Bedarf dem Treiber. Dies ähnelt der Übergabe einzelner Werte für Data-at-Execution-Parameter zur Laufzeit. Bei einer variablen Zeilenbindung geht die Anwendung wie folgt vor:
Sie bindet Parameter und Tabellenwertparameter-Spalten wie in den Schritten 1 bis 3 im vorigen Abschnitt mit dem Titel "Feste Tabellenwertparameter-Zeilenbindung" beschrieben.
Sie legt StrLen_or_IndPtr oder SQL_DESC_OCTET_LENGTH_PTR für alle Tabellenwertparameter, die zur Laufzeit übergeben werden sollen, auf SQL_DATA_AT_EXEC fest. Wenn keiner dieser beiden Zeiger festgelegt wird, wird der Parameter wie im vorherigen Abschnitt beschrieben verarbeitet.
Sie ruft SQLExecute oder SQLExecDirect auf. Dieser Aufruf gibt SQL_NEED_DATA zurück, falls SQL_PARAM_INPUT- oder SQL_PARAM_INPUT_OUTPUT-Parameter als Data-at-Execution-Parameter behandelt werden sollen. In diesem Fall geht die Anwendung wie folgt vor:
- Sie ruft SQLParamData auf. Dieser Aufruf gibt den ParameterValuePtr-Wert für einen Data-at-Execution-Parameter und den Rückgabecode SQL_NEED_DATA zurück. Wenn alle Parameterdaten an den Treiber übergeben wurden, gibt SQLParamData SQL_SUCCESS, SQL_SUCCESS_WITH_INFO oder SQL_ERROR zurück. Bei Data-at-Execution-Parametern kann der Zeiger ParameterValuePtr, der dem Deskriptorfeld SQL_DESC_DATA_PTR entspricht, als Token betrachtet werden, der den Parameter eindeutig identifiziert, für den ein Wert erforderlich ist. Dieses "Token" wird beim Binden von der Anwendung an den Treiber übergeben und während der Ausführung dann wieder an die Anwendung übergeben.
Wenn Zeilendaten für Tabellenwertparameter mit dem Wert NULL gesendet werden sollen und der Tabellenwertparameter keine Zeilen umfasst, ruft die Anwendung SQLPutData auf, wobei StrLen_or_Ind auf SQL_DEFAULT_PARAM festgelegt ist.
Bei Tabellenwertparametern, die nicht NULL sind, geht die Anwendung wie folgt vor:
Sie legt Str_Len_or_Ind für alle Tabellenwertparameter-Spalten auf die geeigneten Werte fest und füllt die Datenpuffer für Tabellenwertparameterspalten, die keine Data-at-Execution-Parameter sein sollen. Tabellenwertparameter-Spalten können Daten zur Laufzeit auf ähnliche Weise übergeben werden wie dem Treiber gewöhnliche Parameter schrittweise übergeben werden.
Sie ruft SQLPutData auf, wobei Str_Len_or_Ind auf die Anzahl der an den Server zu sendenden Zeilen festgelegt wird. Werte, die nicht im Bereich von 0 bis SQL_DESC_ARRAY_SIZE oder SQL_DEFAULT_PARAM liegen, sind ungültig und bewirken die Rückgabe von SQLSTATE HY090 und der Meldung "Ungültige Zeichenfolgen- oder Pufferlänge". Mit 0 wird angegeben, dass alle Zeilen übermittelt wurden und dass keine weiteren Daten für einen Tabellenwertparameter vorliegen (wie im zweiten Aufzählungspunkt dieser Auflistung beschrieben). SQL_DEFAULT_PARAM kann nur verwendet werden, wenn der Treiber zum ersten Mal Daten für einen Tabellenwertparameter anfordert (wie im ersten Aufzählungspunkt dieser Auflistung beschrieben).
Wenn alle Zeilen übermittelt wurden, ruft die Anwendung SQLPutData für den Tabellenwertparameter mit dem Str_Len_or_Ind-Wert 0 auf und fährt dann mit dem oben beschriebenen Schritt 3a fort.
Sie ruft nochmals SQLParamData auf. Wenn Tabellenwertparameter-Spalten Data-at-Execution-Parameter sind, wird dies durch den Wert ValuePtrPtr angegeben, der von SQLParamData zurückgegeben wird. Wenn alle Spaltenwerte verfügbar sind, dann gibt SQLParamData wieder den ParameterValuePtr-Wert für den Tabellenwertparameter zurück, und die Anwendung beginnt erneut.