Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Konformität
Eingeführte Version: ODBC 3.0 Standards Compliance: ODBC
Summary
SQLBulkOperations führt Masseneinfügungen und Massen-Lesezeichen-Operationen durch, einschließlich Aktualisieren, Löschen und Abrufen per Lesezeichen.
Syntax
SQLRETURN SQLBulkOperations(
SQLHSTMT StatementHandle,
SQLUSMALLINT Operation);
Argumente
StatementHandle
[Eingabe] Anweisungshandle.
Operation
[Eingabe] Durchzuführende Operation:
SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK
Weitere Informationen finden Sie unter "Kommentare".
Rücklieferungen
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR oder SQL_INVALID_HANDLE.
Diagnostics
Wenn SQLBulkOperations SQL_ERROR oder SQL_SUCCESS_WITH_INFO zurückgibt, kann ein zugehöriger SQLSTATE-Wert erhalten werden, indem SQLGetDiagRec mit einem HandleType von SQL_HANDLE_STMT und einem Handle von StatementHandle aufgerufen wird. Die folgende Tabelle listet die SQLSTATE-Werte auf, die typischerweise von SQLBulkOperations zurückgegeben werden, und erklärt jeden einzelnen im Kontext dieser Funktion; die Notation "(DM)" geht den vom Treibermanager zurückgegebenen SQLSTATE-Beschreibungen voraus. Der rückgabecode, der jedem SQLSTATE-Wert zugeordnet ist, ist SQL_ERROR, sofern nicht anders angegeben.
Für alle SQLSTATEs, die SQL_SUCCESS_WITH_INFO oder SQL_ERROR zurückgeben können (außer 01xxx SQLSTATEs), wird SQL_SUCCESS_WITH_INFO zurückgegeben, wenn ein Fehler in einer oder mehreren, aber nicht allen Zeilen einer mehrzeiligen Operation auftritt, und SQL_ERROR wird zurückgegeben, wenn bei einer einzeiligen Operation ein Fehler auftritt.
| SQLSTATE | Fehler | Description |
|---|---|---|
| 01000 | Allgemeiner Warnhinweis | Treiberspezifische Informationsmeldung. (Funktion gibt SQL_SUCCESS_WITH_INFO zurück.) |
| 01004 | Rechtsabschneidung von Stringdaten | Das Operation-Argument wurde SQL_FETCH_BY_BOOKMARK, und String- oder Binärdaten wurden für eine Spalte oder mehrere Spalten mit einem Datentyp SQL_C_CHAR oder SQL_C_BINARY zurückgegeben, was zur Trunkierung von nichtleeren Zeichen- oder nicht-NULL-Binärdaten führte. |
| 01S01 | Fehler in der Reihe | Das Operation-Argument war SQL_ADD, und während der Ausführung der Operation trat ein Fehler in einer oder mehreren Zeilen auf, aber mindestens eine Zeile wurde erfolgreich hinzugefügt. (Funktion gibt SQL_SUCCESS_WITH_INFO zurück.) (Dieser Fehler wird nur angezeigt, wenn eine Anwendung mit einem ODBC 2 arbeitet. X-Fahrer .) |
| 01S07 | Bruchabkürzung | Das Operation-Argument war SQL_FETCH_BY_BOOKMARK, der Datentyp des Anwendungspuffers war nicht SQL_C_CHAR oder SQL_C_BINARY, und die an Anwendungspuffer zurückgegebenen Daten für eine oder mehrere Spalten wurden abgeschnitten. (Für numerische C-Datentypen wurde der Bruchteil der Zahl abgeschnitten. Für Zeit-, Zeitstempel- und Intervall-C-Datentypen, die eine Zeitkomponente enthalten, wurde der Bruchteil der Zeit abgeschnitten.) (Funktion gibt SQL_SUCCESS_WITH_INFO zurück.) |
| 07006 | Verletzung des Eingeschränkten Datentyp-Attributs | Das Operation-Argument war SQL_FETCH_BY_BOOKMARK, und der Datenwert einer Spalte im Ergebnissatz konnte nicht in den vom TargetType-Argument im Aufruf zu SQLBindCol angegebenen Datentyp umgewandelt werden. Das Operation-Argument war SQL_UPDATE_BY_BOOKMARK oder SQL_ADD, und der Datenwert in den Anwendungspuffern konnte nicht in den Datentyp einer Spalte im Ergebnissatz umgewandelt werden. |
| 07009 | Ungültiger Deskriptorindex | Das Argument Operation war SQL_ADD, und eine Spalte wurde mit einer Spaltennummer gebunden, die größer war als die Anzahl der Spalten im Ergebnisset. |
| 21S02 | Der Grad der abgeleiteten Tabelle stimmt nicht mit der Spaltenliste überein. | Das Argument Operation war SQL_UPDATE_BY_BOOKMARK; und keine Spalten konnten aktualisiert werden, da alle Spalten entweder ungebunden oder nur lesegeschützt waren oder der Wert im gebundenen Längen-/Indikatorpuffer SQL_COLUMN_IGNORE war. |
| 22001 | Rechtsabschneidung von Stringdaten | Die Zuweisung eines Zeichens oder Binärwerts an eine Spalte im Ergebnisset führte zur Abkürzung von nichtleeren (für Zeichen) oder nicht-nullen (für binären) Zeichen oder Bytes. |
| 22003 | Numerischer Wert außerhalb des Bereichs | Das Operation-Argument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK, und die Zuweisung eines numerischen Werts an eine Spalte im Ergebnisset führte dazu, dass der gesamte (im Gegensatz zum bruchteilige) Teil der Zahl abgeschnitten wurde. Das Argument Operation war SQL_FETCH_BY_BOOKMARK, und das Zurückgeben des numerischen Werts für eine oder mehrere gebundene Spalten hätte einen Verlust signifikanter Ziffern verursacht. |
| 22007 | Ungültiges Datetime-Format | Das Operation-Argument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK, und die Zuweisung eines Datums- oder Zeitstempelwerts an eine Spalte im Ergebnisset führte dazu, dass das Feld für Jahr, Monat oder Tag außerhalb des Reichweitenbereichs war. Das Argument Operation war SQL_FETCH_BY_BOOKMARK, und das Zurückgeben des Datums- oder Zeitstempelwerts für eine oder mehrere gebundene Spalten hätte dazu geführt, dass das Feld für Jahr, Monat oder Tag außerhalb des Bereichs war. |
| 22008 | Datum/Uhrzeit-Feldüberlauf | Das Operation-Argument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK, und die Ausführung der Datetime-Arithmetik bei Daten, die an eine Spalte im Ergebnissatz gesendet wurden, führte dazu, dass ein Datetime-Feld (Jahr, Monat, Tag, Stunde, Minute oder zweites Feld) des Ergebnisses außerhalb des zulässigen Wertebereichs des Feldes lag oder gemäß den natürlichen Regeln des gregorianischen Kalenders für Datetimes ungültig war. Das Operation-Argument war SQL_FETCH_BY_BOOKMARK, und die Ausführung der Datetime-Arithmetik auf aus dem Ergebnissatz abgerufenen Daten führte dazu, dass ein Datetime-Feld (Jahr, Monat, Tag, Stunde, Minute oder zweites Feld) des Ergebnisses außerhalb des zulässigen Wertebereichs des Feldes lag oder gemäß den natürlichen Regeln des gregorianischen Kalenders für Datetimes ungültig war. |
| 22015 | Intervallfeldüberlauf | Das Operation-Argument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK, und die Zuordnung eines exakten numerischen oder Intervall-C-Typs zu einem Intervall-SQL-Datentyp führte zu einem Verlust signifikanter Ziffern. Das Operationsargument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK; bei der Zuweisung eines Intervall-SQL-Typs gab es keine Darstellung des Wertes des C-Typs im Intervall-SQL-Typ. Das Operation-Argument war SQL_FETCH_BY_BOOKMARK, und die Zuweisung von einem exakten numerischen oder Intervall-SQL-Typ auf einen Intervall-C-Typ führte zu einem Verlust signifikanter Ziffern im führenden Feld. Das Argument der Operation war SQL_FETCH_BY_BOOKMARK; bei der Zuweisung eines Intervalls C-Typs gab es keine Darstellung des Werts des SQL-Typs im Intervall-C-Typ. |
| 22018 | Ungültiger Zeichenwert für die Umwandlungsspezifikation |
Das Argument der Operation war SQL_FETCH_BY_BOOKMARK; der C-Typ war eine exakte oder ungefähre Nummer, ein Datums- oder Intervalldatentyp; der SQL-Typ der Spalte war ein Zeichendatentyp; und der Wert in der Spalte war kein gültiges Literal des gebundenen C-Typs. Das Argument Operation war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK; der SQL-Typ war ein exakter oder ungefährer Zahlentyp, ein Datumszeit- oder Intervalldatentyp; der C-Typ war SQL_C_CHAR; und der Wert in der Spalte war kein gültiges Literal des gebundenen SQL-Typs. |
| 23000 | Integritätseinschränkungsverletzung |
Das Operation-Argument wurde SQL_ADD, SQL_DELETE_BY_BOOKMARK oder SQL_UPDATE_BY_BOOKMARK, und eine Integritätsbeschränkung wurde verletzt. Das Operation-Argument war SQL_ADD, und eine Spalte, die nicht gebunden war, ist als NICHT NULL definiert und hat keinen Standard. Das Operation-Argument war SQL_ADD, die im Bound StrLen_or_IndPtr Puffer angegebene Länge war SQL_COLUMN_IGNORE, und die Spalte hatte keinen Standardwert. |
| 24000 | Ungültiger Cursorstatus | Der StatementHandle befand sich im ausgeführten Zustand, aber es war kein Ergebnisset mit dem StatementHandle verknüpft. |
| 40001 | Serialisierungsfehler | Die Transaktion wurde aufgrund eines Ressourcen-Deadlocks mit einer anderen Transaktion zurückgesetzt. |
| 40003 | Abschluss der Anweisung unbekannt | Fehler bei der zugehörigen Verbindung während der Ausführung dieser Funktion, und der Status der Transaktion kann nicht bestimmt werden. |
| 42000 | Syntaxfehler oder Zugriffsverletzung | Der Fahrer konnte die Reihe nicht wie nötig verriegeln, um die im Operation-Argument geforderte Operation durchzuführen. |
| 44000 | WITH CHECK OPTION-Verstoß | Das Operation-Argument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK, und das Einfügen oder Update wurde auf einer angezeigten Tabelle (oder einer Tabelle, die von der angezeigten Tabelle abgeleitet wurde) durchgeführt, die durch die Angabe der WITH CHECK OPTION erstellt wurde, sodass eine oder mehrere Zeilen, die vom Einfügen oder Update betroffen sind, in der angezeigten Tabelle nicht mehr vorhanden sind. |
| HY000 | Allgemeiner Fehler | Es ist ein Fehler aufgetreten, für den kein spezifischer SQLSTATE-Wert vorhanden war und für den keine implementierungsspezifische SQLSTATE definiert wurde. Die von SQLGetDiagRec im *MessageText-Puffer zurückgegebene Fehlermeldung beschreibt den Fehler und dessen Ursache. |
| HY001 | Speicherzuweisungsfehler | Der Treiber konnte speicher nicht zuordnen, der erforderlich ist, um die Ausführung oder den Abschluss der Funktion zu unterstützen. |
| HY008 | Vorgang abgebrochen | Die asynchrone Verarbeitung wurde für " StatementHandle" aktiviert. Die Funktion wurde aufgerufen, und bevor sie die Ausführung abgeschlossen hat, wurde SQLCancel oder SQLCancelHandle für die Anweisungshandle aufgerufen. Anschließend wurde die Funktion erneut für " StatementHandle" aufgerufen. Die Funktion wurde aufgerufen, und bevor sie die Ausführung abgeschlossen hat, wurde SQLCancel oder SQLCancelHandle für das StatementHandle von einem anderen Thread in einer Multithreadanwendung aufgerufen. |
| HY010 | Funktionssequenzfehler | (DM) Eine asynchron ausgeführte Funktion wurde für den Verbindungshandle aufgerufen, der dem StatementHandle zugeordnet ist. Diese asynchrone Funktion lief noch, als die SQLBulkOperations-Funktion aufgerufen wurde. (DM) SQLExecute, SQLExecDirect oder SQLMoreResults wurde für " StatementHandle " aufgerufen und SQL_PARAM_DATA_AVAILABLE zurückgegeben. Diese Funktion wurde aufgerufen, bevor Daten für alle gestreamten Parameter abgerufen wurden. (DM) Das angegebene StatementHandle war nicht im ausgeführten Zustand. Die Funktion wurde aufgerufen, ohne vorher SQLExecDirect, SQLExecute oder eine Katalogfunktion aufzurufen. (DM) Eine asynchron ausgeführte Funktion (nicht diese) wurde für das StatementHandle aufgerufen und wurde noch ausgeführt, als diese Funktion aufgerufen wurde. (DM) SQLExecute, SQLExecDirect oder SQLSetPos wurde für den StatementHandle aufgerufen und SQL_NEED_DATA zurückgegeben. Diese Funktion wurde aufgerufen, bevor Daten für alle Daten bei ausführungsparametern oder -spalten gesendet wurden. (DM) Der Fahrer war ein ODBC 2. x-Treiber , und SQLBulkOperations wurde für einen StatementHandle aufgerufen, bevor SQLFetchScroll oder SQLFetch aufgerufen wurden. (DM) SQLBulkOperations wurde aufgerufen, nachdem SQLExtendedFetch auf dem StatementHandle aufgerufen wurde. |
| HY011 | Attribut kann jetzt nicht festgelegt werden | (DM) Der Fahrer war ein ODBC 2. x-Treiber , und das Attribut SQL_ATTR_ROW_STATUS_PTR Statement wurde zwischen Aufrufen von SQLFetch oder SQLFetchScroll und SQLBulkOperations gesetzt. |
| HY013 | Speicherverwaltungsfehler | Der Funktionsaufruf konnte nicht verarbeitet werden, da auf die zugrunde liegenden Speicherobjekte nicht zugegriffen werden konnte, möglicherweise aufgrund geringer Arbeitsspeicherbedingungen. |
| HY090 | Ungültige Zeichenfolgen- oder Pufferlänge | Das Operationsargument war SQL_ADD oder SQL_UPDATE_BY_BOOKMARK; ein Datenwert war kein Nullzeiger; der C-Datentyp war SQL_C_BINARY oder SQL_C_CHAR; und der Spaltenlängenwert war kleiner als 0, aber nicht gleich SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS oder SQL_NULL_DATA, oder kleiner als oder gleich SQL_LEN_DATA_AT_EXEC_OFFSET. Der Wert in einem Längen-/Indikatorpuffer war SQL_DATA_AT_EXEC; der SQL-Typ war entweder SQL_LONGVARCHAR, SQL_LONGVARBINARY oder ein langer, datenquellenspezifischer Datentyp; und der SQL_NEED_LONG_DATA_LEN Informationstyp in SQLGetInfo war "Y". Das Operation-Argument wurde SQL_ADD, das Attribut SQL_ATTR_USE_BOOKMARK der Anweisung wurde auf SQL_UB_VARIABLE gesetzt, und Spalte 0 war an einen Puffer gebunden, dessen Länge nicht der maximalen Länge für das Lesezeichen für dieses Ergebnisset entsprach. (Diese Länge ist im SQL_DESC_OCTET_LENGTH Feld des IRD verfügbar und kann durch Aufruf von SQLDescribeCol, SQLColAttribute oder SQLGetDescField erhalten werden.) |
| HY092 | Ungültige Attributkennung | (DM) Der für das Operation-Argument angegebene Wert war ungültig. Das Operation-Argument war SQL_ADD, SQL_UPDATE_BY_BOOKMARK oder SQL_DELETE_BY_BOOKMARK, und das Attribut SQL_ATTR_CONCURRENCY Statement wurde auf SQL_CONCUR_READ_ONLY gesetzt. Das Operation-Argument war SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK oder SQL_UPDATE_BY_BOOKMARK, und die Lesezeichenspalte war nicht gebunden oder das Attribut SQL_ATTR_USE_BOOKMARKS Anweisung wurde auf SQL_UB_OFF gesetzt. |
| HY117 | Die Verbindung wird aufgrund des unbekannten Transaktionsstatus angehalten. Es sind nur Trenn- und schreibgeschützte Funktionen zulässig. | (DM) Weitere Informationen zum angehaltenen Zustand finden Sie unter SQLEndTran Function. |
| HYC00 | Optionales Feature wurde nicht implementiert | Der Treiber oder die Datenquelle unterstützt die im Operation-Argument angeforderte Operation nicht. |
| HYT00 | Timeout überschritten | Der Abfragetimeoutzeitraum ist abgelaufen, bevor die Datenquelle das Resultset zurückgibt. Die Auszeitperiode wird durch SQLSetStmtAttr mit einem Attribut-Argument SQL_ATTR_QUERY_TIMEOUT festgelegt. |
| HYT01 | Verbindungstimeout abgelaufen | Der Zeitraum für das Verbindungstimeout ist abgelaufen, bevor die Datenquelle auf die Anforderung geantwortet hat. Der Verbindungstimeoutzeitraum wird über SQLSetConnectAttr SQL_ATTR_CONNECTION_TIMEOUT festgelegt. |
| IM001 | Dieser Treiber unterstützt diese Funktion nicht. | (DM) Der dem StatementHandle zugeordnete Treiber unterstützt die Funktion nicht. |
| IM017 | Die Abrufung ist im asynchronen Benachrichtigungsmodus deaktiviert. | Immer wenn das Benachrichtigungsmodell verwendet wird, ist die Abrufung deaktiviert. |
| IM018 | SQLCompleteAsync wurde nicht aufgerufen, um den vorherigen asynchronen Vorgang für dieses Handle abzuschließen. | Wenn der vorherige Funktionsaufruf für das Handle SQL_STILL_EXECUTING zurückgibt und der Benachrichtigungsmodus aktiviert ist, muss SQLCompleteAsync für das Handle aufgerufen werden, um die Nachbearbeitung durchzuführen und den Vorgang abzuschließen. |
Kommentare
Caution
Für Informationen darüber, welche Anweisungen SQLBulkOperations aufgerufen werden können und was es für die Kompatibilität mit ODBC 2 tun muss. x Anwendungen, siehe den Abschnitt Blockcursor, scrollbare Cursor und Abwärtskompatibilität im Anhang G: Treiberrichtlinien für Abwärtskompatibilität.
Eine Anwendung verwendet SQLBulkOperations, um die folgenden Operationen auf der Basistabelle oder Ansicht auszuführen, die der aktuellen Abfrage entspricht:
Fügen Sie neue Zeilen hinzu.
Aktualisieren Sie eine Reihe von Zeilen, in denen jede Zeile durch ein Lesezeichen identifiziert wird.
Löschen Sie eine Reihe von Zeilen, in denen jede Zeile durch ein Lesezeichen identifiziert wird.
Holen Sie eine Reihe von Zeilen, in denen jede Zeile durch ein Lesezeichen identifiziert wird.
Nach einem Aufruf von SQLBulkOperations ist die Position des Blockcursors undefiniert. Die Anwendung muss SQLFetchScroll aufrufen, um die Cursorposition festzulegen. Eine Anwendung sollte SQLFetchScroll nur mit einem FetchOrientation-Argument SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE oder SQL_FETCH_BOOKMARK aufrufen. Die Cursorposition ist undefiniert, wenn die Anwendung SQLFetch oder SQLFetchScroll mit einem FetchOrientation-Argument SQL_FETCH_PRIOR, SQL_FETCH_NEXT oder SQL_FETCH_RELATIVE aufruft.
Eine Spalte kann in Massenoperationen, die durch einen Aufruf zu SQLBulkOperations ausgeführt werden, ignoriert werden, indem der im Aufruf zu SQLBindCol angegebene Spaltenlänge/Indikatorpuffer auf SQL_COLUMN_IGNORE gesetzt wird.
Es ist nicht notwendig, dass die Anwendung das Attribut SQL_ATTR_ROW_OPERATION_PTR Statement beim Aufruf von SQLBulkOperations setzt, da Zeilen bei Massenoperationen mit dieser Funktion nicht ignoriert werden können.
Der Puffer, auf den das Attribut SQL_ATTR_ROWS_FETCHED_PTR Statement zeigt, enthält die Anzahl der Zeilen, die von einem Aufruf zu SQLBulkOperations betroffen sind.
Wenn das Operation-Argument SQL_ADD oder SQL_UPDATE_BY_BOOKMARK ist und die Auswahlliste der Abfragespezifikation, die dem Cursor zugeordnet ist, mehr als eine Referenz auf dieselbe Spalte enthält, wird der Treiber definiert, ob ein Fehler generiert wird oder der Treiber die duplizierten Referenzen ignoriert und die angeforderten Operationen ausführt.
Weitere Informationen zur Verwendung von SQLBulkOperations finden Sie unter Daten aktualisieren mit SQLBulkOperations.
Durchführung von Bulk-Einsätzen
Um Daten mit SQLBulkOperations einzufügen, führt eine Anwendung folgende Schrittfolge durch:
Führt eine Abfrage aus, die eine Ergebnismenge zurückgibt.
Setzt das Attribut der SQL_ATTR_ROW_ARRAY_SIZE-Anweisung auf die Anzahl der Zeilen, die eingefügt werden möchte.
Ruft SQLBindCol auf, um die Daten zu binden, die es einfügen möchte. Die Daten sind an ein Array gebunden, dessen Größe dem Wert von SQL_ATTR_ROW_ARRAY_SIZE entspricht.
Note
Die Größe des Arrays, auf das das Attribut SQL_ATTR_ROW_STATUS_PTR Statement zeigt, sollte entweder gleich SQL_ATTR_ROW_ARRAY_SIZE sein oder SQL_ATTR_ROW_STATUS_PTR sollte ein Nullzeiger sein.
Ruft SQLBulkOperations(StatementHandle, SQL_ADD) auf, um die Einfügung durchzuführen.
Wenn die Anwendung das Attribut SQL_ATTR_ROW_STATUS_PTR Statement gesetzt hat, kann sie dieses Array inspizieren, um das Ergebnis der Operation zu sehen.
Wenn eine Anwendung Spalte 0 bindet, bevor sie SQLBulkOperations mit einem Operation-Argument SQL_ADD aufruft, aktualisiert der Treiber die gebundenen Spaltenpuffer 0 mit den Lesezeichenwerten für die neu eingefügte Zeile. Damit dies geschieht, muss die Anwendung das Attribut SQL_ATTR_USE_BOOKMARKS Statement auf SQL_UB_VARIABLE gesetzt haben, bevor die Anweisung ausgeführt wird. (Das funktioniert nicht mit einem ODBC 2. X-Fahrer .)
Lange Daten können in Teilen von SQLBulkOperations hinzugefügt werden, indem Aufrufe zu SQLParamData und SQLPutData verwendet werden. Weitere Informationen finden Sie später in dieser Funktionsreferenz unter "Bereitstellung langer Daten für Masseneinsätze und Updates".
Es ist nicht erforderlich, dass die Anwendung SQLFetch oder SQLFetchScroll aufruft, bevor sie SQLBulkOperations aufruft (außer bei ODBC 2).x Treiber; siehe Abwärtskompatibilität und Einhaltung von Standards).
Das Verhalten ist treiberdefiniert, wenn SQLBulkOperations mit dem Operation-Argument SQL_ADD auf einem Cursor aufgerufen wird, der doppelte Spalten enthält. Der Treiber kann einen treiberdefinierten SQLSTATE zurückgeben, die Daten zur ersten Spalte hinzufügen, die im Ergebnissatz erscheint, oder andere treiberdefinierte Verhaltensweisen ausführen.
Massen-Updates durch Verwendung von Lesezeichen durchführen
Um Massen-Updates mit Lesezeichen mit SQLBulkOperations durchzuführen, führt eine Anwendung folgende Schritte in der Reihenfolge durch:
Setzt das Attribut SQL_ATTR_USE_BOOKMARKS Statement auf SQL_UB_VARIABLE.
Führt eine Abfrage aus, die eine Ergebnismenge zurückgibt.
Setzt das Attribut SQL_ATTR_ROW_ARRAY_SIZE Statement auf die Anzahl der Zeilen, die aktualisiert werden möchte.
Ruft SQLBindCol auf, um die Daten zu binden, die aktualisiert werden sollen. Die Daten sind an ein Array gebunden, dessen Größe dem Wert von SQL_ATTR_ROW_ARRAY_SIZE entspricht. Es ruft außerdem SQLBindCol auf, um Spalte 0 (die Lesezeichenspalte) zu binden.
Kopiert die Lesezeichen für Zeilen, die es aktualisieren möchte, in das Array, das an Spalte 0 gebunden ist.
Aktualisiert die Daten in den gebundenen Puffern.
Note
Die Größe des Arrays, auf das das Attribut SQL_ATTR_ROW_STATUS_PTR Statement zeigt, sollte gleich SQL_ATTR_ROW_ARRAY_SIZE sein oder SQL_ATTR_ROW_STATUS_PTR sollte ein Nullzeiger sein.
Aufruft SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).
Note
Wenn die Anwendung das Attribut SQL_ATTR_ROW_STATUS_PTR Statement gesetzt hat, kann sie dieses Array inspizieren, um das Ergebnis der Operation zu sehen.
Optional ruft SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) auf, um Daten in die gebundenen Anwendungspuffer zu holen und zu überprüfen, ob das Update stattgefunden hat.
Wenn die Daten aktualisiert wurden, ändert der Treiber den Wert im Zeilenstatus-Array für die entsprechenden Zeilen auf SQL_ROW_UPDATED.
Massen-Updates, die von SQLBulkOperations durchgeführt werden, können lange Daten umfassen, indem Aufrufe zu SQLParamData und SQLPutData verwendet werden. Weitere Informationen finden Sie später in dieser Funktionsreferenz unter "Bereitstellung langer Daten für Masseneinsätze und Updates".
Wenn Lesezeichen über Cursors hinweg bestehen, muss die Anwendung SQLFetch oder SQLFetchScroll nicht aufrufen, bevor sie mit Lesezeichen aktualisiert. Es kann Lesezeichen verwenden, die es von einem vorherigen Cursor gespeichert hat. Wenn Lesezeichen nicht über Cursors hinweg erhalten bleiben, muss die Anwendung SQLFetch oder SQLFetchScroll aufrufen, um die Lesezeichen abzurufen.
Das Verhalten ist treiberdefiniert, wenn SQLBulkOperations mit einem Operation-Argument von SQL_UPDATE_BY_BOOKMARK auf einem Cursor aufgerufen wird, der doppelte Spalten enthält. Der Treiber kann einen treiberdefinierten SQLSTATE zurückgeben, die erste Spalte im Ergebnissatz aktualisieren oder ein anderes treiberdefiniertes Verhalten ausführen.
Massenabrufe mit Lesezeichen durchführen
Um Massenabrufe mit Lesezeichen mit SQLBulkOperations durchzuführen, führt eine Anwendung folgende Schritte nacheinander durch:
Setzt das Attribut SQL_ATTR_USE_BOOKMARKS Statement auf SQL_UB_VARIABLE.
Führt eine Abfrage aus, die eine Ergebnismenge zurückgibt.
Setzt das Attribut SQL_ATTR_ROW_ARRAY_SIZE Statement auf die Anzahl der Zeilen, die es abrufen möchte.
Ruft SQLBindCol auf, um die Daten zu binden, die es abrufen möchte. Die Daten sind an ein Array gebunden, dessen Größe dem Wert von SQL_ATTR_ROW_ARRAY_SIZE entspricht. Es ruft außerdem SQLBindCol auf, um Spalte 0 (die Lesezeichenspalte) zu binden.
Kopiert die Lesezeichen für Zeilen, die es abrufen möchte, in das an Spalte 0 gebundene Array. (Dies setzt voraus, dass die Anwendung die Lesezeichen bereits separat abgerufen hat.)
Note
Die Größe des Arrays, auf das das Attribut SQL_ATTR_ROW_STATUS_PTR Statement zeigt, sollte gleich SQL_ATTR_ROW_ARRAY_SIZE sein oder SQL_ATTR_ROW_STATUS_PTR sollte ein Nullzeiger sein.
Ruft SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) auf.
Wenn die Anwendung das Attribut SQL_ATTR_ROW_STATUS_PTR Statement gesetzt hat, kann sie dieses Array inspizieren, um das Ergebnis der Operation zu sehen.
Wenn Lesezeichen über Cursors hinweg erhalten bleiben, muss die Anwendung SQLFetch oder SQLFetchScroll nicht aufrufen, bevor sie die Lesezeichen abruft. Es kann Lesezeichen verwenden, die es von einem vorherigen Cursor gespeichert hat. Wenn Lesezeichen nicht über Cursors hinweg erhalten bleiben, muss die Anwendung SQLFetch oder SQLFetchScroll einmal aufrufen, um die Lesezeichen abzurufen.
Massenlöschungen mit Lesezeichen durchführen
Um Massenlöschungen mit Lesezeichen mit SQLBulkOperations durchzuführen, führt eine Anwendung folgende Schritte in der Reihenfolge durch:
Setzt das Attribut SQL_ATTR_USE_BOOKMARKS Statement auf SQL_UB_VARIABLE.
Führt eine Abfrage aus, die eine Ergebnismenge zurückgibt.
Setzt das Attribut SQL_ATTR_ROW_ARRAY_SIZE Statement auf die Anzahl der Zeilen, die gelöscht werden möchte.
Ruft SQLBindCol auf, um Spalte 0 (die Lesezeichenspalte) zu binden.
Kopiert die Lesezeichen für Zeilen, die es löschen möchte, in das an Spalte 0 gebundene Array.
Note
Die Größe des Arrays, auf das das Attribut SQL_ATTR_ROW_STATUS_PTR Statement zeigt, sollte gleich SQL_ATTR_ROW_ARRAY_SIZE sein oder SQL_ATTR_ROW_STATUS_PTR sollte ein Nullzeiger sein.
Ruft SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK) auf.
Wenn die Anwendung das Attribut SQL_ATTR_ROW_STATUS_PTR Statement gesetzt hat, kann sie dieses Array inspizieren, um das Ergebnis der Operation zu sehen.
Wenn Lesezeichen über Cursors hinweg erhalten bleiben, muss die Anwendung SQLFetch oder SQLFetchScroll nicht aufrufen, bevor sie sie durch Lesezeichen löscht. Es kann Lesezeichen verwenden, die es von einem vorherigen Cursor gespeichert hat. Wenn Lesezeichen nicht über Cursors hinweg erhalten bleiben, muss die Anwendung SQLFetch oder SQLFetchScroll einmal aufrufen, um die Lesezeichen abzurufen.
Bereitstellung langer Daten für Bulk-Einsätze und Updates
Lange Daten können für Masseneinsätze und Updates bereitgestellt werden, die durch Aufrufe zu SQLBulkOperations durchgeführt werden. Um lange Daten einzufügen oder zu aktualisieren, führt eine Anwendung die folgenden Schritte zusätzlich zu den zuvor in diesem Thema beschriebenen Abschnitten "Durchführung von Masseneinsätzen" und "Durchführung von Massenupdates mit Lesezeichen" durch.
Wenn sie die Daten mittels SQLBindCol bindet, legt die Anwendung einen anwendungsdefinierten Wert, wie z. B. die Spaltennummer, in den *TargetValuePtr-Puffer für die Daten-at-Ausführung-Spalten. Der Wert kann später verwendet werden, um die Spalte zu identifizieren.
Die Anwendung legt das Ergebnis des Makros SQL_LEN_DATA_AT_EXEC(Länge) in den *StrLen_or_IndPtr-Puffer . Wenn der SQL-Datentyp der Spalte SQL_LONGVARBINARY, SQL_LONGVARCHAR oder ein langer datenquellenspezifischer Datentyp ist und der Treiber "Y" für den SQL_NEED_LONG_DATA_LEN Informationstyp in SQLGetInfo zurückgibt, ist die Länge die Anzahl der Datenbytes, die für den Parameter gesendet werden sollen; ansonsten muss er ein nichtnegativer Wert sein und wird ignoriert.
Wenn SQLBulkOperations aufgerufen wird, gibt die Funktion bei Daten-at-Ausführung-Spalten SQL_NEED_DATA zurück und fährt mit Schritt 3 fort, der folgt. (Gibt es keine Spalten für Daten bei der Ausführung, ist der Prozess abgeschlossen.)
Die Anwendung ruft SQLParamData auf, um die Adresse des *TargetValuePtr-Puffers für die erste Daten-zu-Ausführung-Spalte abzurufen, die verarbeitet werden soll. SQLParamData gibt SQL_NEED_DATA zurück. Die Anwendung ruft den anwendungsdefinierten Wert aus dem *TargetValuePtr-Puffer ab.
Note
Obwohl Daten bei ausführungsparametern daten at-execution-Spalten ähneln, ist der von SQLParamData zurückgegebene Wert für jeden unterschiedlich.
Data-at-Execution-Spalten sind Spalten in einem Zeilensatz, für die Daten mit SQLPutData gesendet werden, wenn eine Zeile mit SQLBulkOperations aktualisiert oder eingefügt wird. Sie sind mit SQLBindCol gebunden. Der von SQLParamData zurückgegebene Wert ist die Adresse der Zeile im *TargetValuePtr-Puffer , die verarbeitet wird.
Die Anwendung ruft SQLPutData ein- oder mehrmals auf, um Daten für die Spalte zu senden. Es werden mehr als ein Aufruf benötigt, wenn nicht alle Datenwerte im * TargetValuePtr-Puffer , der in SQLPutData angegeben ist, zurückgegeben werden kann; mehrere Aufrufe von SQLPutData für dieselbe Spalte sind nur erlaubt, wenn Charakterdaten C an eine Spalte mit einem Zeichen-, Binär- oder datenquellenspezifischen Datentyp gesendet werden oder wenn binäre C-Daten an eine Spalte mit einem Zeichen-, Binär- oder datenquellenspezifischen Datentyp gesendet werden.
Die Anwendung ruft SQLParamData erneut auf, um anzuzeigen, dass alle Daten für die Spalte gesendet wurden.
Wenn es mehr Daten-at-Ausführung-Spalten gibt, gibt SQLParamData SQL_NEED_DATA und die Adresse des TargetValuePtr-Puffers für die nächste Daten-at-Ausführung-Spalte zurück, die verarbeitet werden soll. Die Anwendung wiederholt die Schritte 4 und 5.
Wenn keine Daten-at-Ausführung-Spalten mehr vorhanden sind, ist der Prozess abgeschlossen. Wenn die Anweisung erfolgreich ausgeführt wurde, gibt SQLParamData SQL_SUCCESS oder SQL_SUCCESS_WITH_INFO zurück; Wenn die Ausführung fehlschlug, wurde SQL_ERROR zurückgegeben. An diesem Punkt kann SQLParamData jeden SQLSTATE zurückgeben, der von SQLBulkOperations zurückgegeben werden kann.
Wenn die Operation abgebrochen wird oder ein Fehler in SQLParamData oder SQLPutData auftritt, nachdem SQLBulkOperations SQL_NEED_DATA zurückgegeben ist und bevor Daten für alle Daten-at-Execution-Spalten gesendet wurden, kann die Anwendung nur SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData oder SQLPutData für die Anweisung oder die mit der Anweisung zugeordnete Verbindung aufrufen. Wenn eine andere Funktion für die Anweisung oder die mit der Anweisung zugeordnete Verbindung aufgerufen wird, gibt die Funktion SQL_ERROR und SQLSTATE HY010 zurück (Funktionssequenzfehler).
Wenn die Anwendung SQLCancel aufruft, während der Treiber noch Daten für Daten-zu-Ausführung-Spalten benötigt, bricht der Treiber die Operation ab. Die Anwendung kann dann SQLBulkOperations erneut aufrufen; Das Aufheben beeinflusst weder den Cursorzustand noch die aktuelle Cursorposition.
Zeilenstatusarray
Das Zeilenstatusarray enthält Statuswerte für jede Datenzeile im Zeilensatz nach einem Aufruf zu SQLBulkOperations. Der Treiber setzt die Statuswerte in diesem Array nach einem Aufruf von SQLFetch, SQLFetchScroll, SQLSetPos oder SQLBulkOperations. Dieses Array wird zunächst durch einen Aufruf von SQLBulkOperations gefüllt, falls SQLFetch oder SQLFetchScroll nicht vor SQLBulkOperations aufgerufen wurden. Dieses Array wird durch das Attribut SQL_ATTR_ROW_STATUS_PTR Statement angezeigt. Die Anzahl der Elemente in den Zeilenstatusarrays muss der Anzahl der Zeilen im Zeilensatz entsprechen (wie durch das Attribut SQL_ATTR_ROW_ARRAY_SIZE Statement definiert). Informationen zu diesem Zeilenstatus-Array finden Sie unter SQLFetch.
Codebeispiel
Das folgende Beispiel holt jeweils 10 Datenzeilen aus der Kundentabelle. Anschließend fordert es den Nutzer nach einer Aktion auf. Um den Netzwerkverkehr zu reduzieren, aktualisiert, löscht und fügt der Beispielpuffer lokal in die gebundenen Arrays ein, jedoch mit Offsets über die Rowset-Daten hinaus. Wenn der Benutzer Updates, Löschungen und Einfügungen an die Datenquelle sendet, setzt der Code den Binding-Offset entsprechend und ruft SQLBulkOperations auf. Zur Vereinfachung kann der Benutzer nicht mehr als 10 Updates, Löschungen oder Einfügungen puffern.
// SQLBulkOperations_Function.cpp
// compile with: ODBC32.lib
#include <windows.h>
#include <sqlext.h>
#include "stdio.h"
#define UPDATE_ROW 100
#define DELETE_ROW 101
#define ADD_ROW 102
#define SEND_TO_DATA_SOURCE 103
#define UPDATE_OFFSET 10
#define INSERT_OFFSET 20
#define DELETE_OFFSET 30
// Define structure for customer data (assume 10 byte maximum bookmark size).
typedef struct tagCustStruct {
SQLCHAR Bookmark[10];
SQLINTEGER BookmarkLen;
SQLUINTEGER CustomerID;
SQLINTEGER CustIDInd;
SQLCHAR CompanyName[51];
SQLINTEGER NameLenOrInd;
SQLCHAR Address[51];
SQLINTEGER AddressLenOrInd;
SQLCHAR Phone[11];
SQLINTEGER PhoneLenOrInd;
} CustStruct;
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,
// elements 10-19 are for the buffered updates, elements 20-29 are for
// the buffered inserts, and elements 30-39 are for the buffered deletes.
CustStruct CustArray[40];
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,
NumDeletes = 0;
SQLLEN BindOffset = 0;
SQLRETURN retcode;
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLHSTMT hstmt = NULL;
int main() {
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Set the following statement attributes:
// SQL_ATTR_CURSOR_TYPE: Keyset-driven
// SQL_ATTR_ROW_BIND_TYPE: Row-wise
// SQL_ATTR_ROW_ARRAY_SIZE: 10
// SQL_ATTR_USE_BOOKMARKS: Use variable-length bookmarks
// SQL_ATTR_ROW_STATUS_PTR: Points to RowStatusArray
// SQL_ATTR_ROW_BIND_OFFSET_PTR: Points to BindOffset
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);
// Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.
retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);
retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);
retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);
retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);
// Execute a statement to retrieve rows from the Customers table.
retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);
// Fetch and display the first 10 rows.
retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);
// DisplayCustData(CustArray, 10);
// Call GetAction to get an action and a row number from the user.
// while (GetAction(&Action, &RowNum)) {
Action = SQL_FETCH_NEXT;
RowNum = 2;
switch (Action) {
case SQL_FETCH_NEXT:
case SQL_FETCH_PRIOR:
case SQL_FETCH_FIRST:
case SQL_FETCH_LAST:
case SQL_FETCH_ABSOLUTE:
case SQL_FETCH_RELATIVE:
// Fetch and display the requested data.
SQLFetchScroll(hstmt, Action, RowNum);
// DisplayCustData(CustArray, 10);
break;
case UPDATE_ROW:
// Check if we have reached the maximum number of buffered updates.
if (NumUpdates < 10) {
// Get the new customer data and place it in the next available element of
// the buffered updates section of CustArray, copy the bookmark of the row
// being updated to the same element, and increment the update counter.
// Checking to see we have not already buffered an update for this
// row not shown.
// GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);
memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumUpdates++;
} else {
printf("Buffers full. Send buffered changes to the data source.");
}
break;
case DELETE_ROW:
// Check if we have reached the maximum number of buffered deletes.
if (NumDeletes < 10) {
// Copy the bookmark of the row being deleted to the next available element
// of the buffered deletes section of CustArray and increment the delete
// counter. Checking to see we have not already buffered an update for
// this row not shown.
memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumDeletes++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case ADD_ROW:
// reached maximum number of buffered inserts?
if (NumInserts < 10) {
// Get the new customer data and place it in the next available element of
// the buffered inserts section of CustArray and increment insert counter.
// GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);
NumInserts++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case SEND_TO_DATA_SOURCE:
// If there are any buffered updates, inserts, or deletes, set the array size
// to that number, set the binding offset to use the data in the buffered
// update, insert, or delete part of CustArray, and call SQLBulkOperations to
// do the updates, inserts, or deletes. Because we will never have more than
// 10 updates, inserts, or deletes, we can use the same row status array.
if (NumUpdates) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);
BindOffset = UPDATE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);
NumUpdates = 0;
}
if (NumInserts) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);
BindOffset = INSERT_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_ADD);
NumInserts = 0;
}
if (NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);
BindOffset = DELETE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);
NumDeletes = 0;
}
// If there were any updates, inserts, or deletes, reset the binding offset
// and array size to their original values.
if (NumUpdates || NumInserts || NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
BindOffset = 0;
}
break;
}
// }
// Close the cursor.
SQLFreeStmt(hstmt, SQL_CLOSE);
}
Verwandte Funktionen
| Weitere Informationen zu | Siehe |
|---|---|
| Binden eines Puffers an eine Spalte in einem Resultset | SQLBindCol-Funktion |
| Abbrechen der Verarbeitung von Anweisungen | SQLCancel-Funktion |
| Abrufen eines Datenblocks oder Scrollen durch ein Resultset | SQLFetchScroll-Funktion |
| Ein einzelnes Feld eines Deskriptors erhalten | SQLGetDescField-Funktion |
| Mehrere Felder eines Deskriptors erhalten | SQLGetDescRec-Funktion |
| Setzen eines einzelnen Körpers eines Deskriptors | SQLSetDescField-Funktion |
| Setzen mehrerer Körper eines Deskriptors | SQLSetDescRec-Funktion |
| Positionierung des Cursors, Aktualisierung der Daten im Zeilensatz oder Aktualisierung oder Löschen von Daten im Zeilensatz | SQLSetPos-Funktion |
| Festlegen eines Anweisungsattributs | SQLSetStmtAttr-Funktion |