SQLCopyDesc-Funktion
Konformität
Version eingeführt: ODBC 3.0-Normenkonformität: ISO 92
Zusammenfassung
SQLCopyDesc kopiert Deskriptorinformationen von einem Deskriptorhandle in ein anderes.
Syntax
SQLRETURN SQLCopyDesc(
SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle);
Argumente
SourceDescHandle
[Eingabe] Quelldeskriptorhandle.
TargetDescHandle
[Eingabe] Zieldeskriptorhandle. Das TargetDescHandle-Argument kann ein Handle für einen Anwendungsdeskriptor oder eine IPD sein.
TargetDescHandle kann nicht auf ein Handle für einen IRD festgelegt werden, oder SQLCopyDesc gibt SQLSTATE HY016 zurück (Kann einen Implementierungszeilendeskriptor nicht ändern).
Gibt zurück
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR oder SQL_INVALID_HANDLE.
Diagnose
Wenn SQLCopyDesc SQL_ERROR oder SQL_SUCCESS_WITH_INFO zurückgibt, kann ein zugeordneter SQLSTATE-Wert abgerufen werden, indem SQLGetDiagRec mit einem HandleType von SQL_HANDLE_DESC und einem Handle von TargetDescHandle aufgerufen wird. Wenn im Aufruf ein ungültiges SourceDescHandle übergeben wurde, wird SQL_INVALID_HANDLE zurückgegeben, aber es wird kein SQLSTATE zurückgegeben. In der folgenden Tabelle sind die SQLSTATE-Werte aufgeführt, die häufig von SQLCopyDesc zurückgegeben werden, und die einzelnen Werte werden im Kontext dieser Funktion erläutert. die Notation "(DM)" geht den Beschreibungen von SQLSTATEs voran, die vom Treiber-Manager zurückgegeben werden. Der rückgabecode, der jedem SQLSTATE-Wert zugeordnet ist, ist SQL_ERROR, sofern nicht anders angegeben.
Wenn ein Fehler zurückgegeben wird, wird der Aufruf von SQLCopyDesc sofort abgebrochen, und der Inhalt der Felder im TargetDescHandle-Deskriptor ist nicht definiert.
Da SQLCopyDesc durch Aufrufen von SQLGetDescField und SQLSetDescField implementiert werden kann, gibt SQLCopyDesc möglicherweise SQLSTATEs zurück, die von SQLGetDescField oder SQLSetDescField zurückgegeben werden.
SQLSTATE | Fehler | BESCHREIBUNG |
---|---|---|
01000 | Allgemeine Warnung | Treiberspezifische Informationsmeldung. (Die Funktion gibt SQL_SUCCESS_WITH_INFO zurück.) |
08S01 | Kommunikationslinkfehler | Die Kommunikationsverbindung zwischen dem Treiber und der Datenquelle, mit der der Treiber verbunden war, ist fehlgeschlagen, bevor die Verarbeitung der Funktion abgeschlossen wurde. |
HY000 | Allgemeiner Fehler | Es ist ein Fehler aufgetreten, für den kein spezifischer SQLSTATE-Wert vorhanden war und für den kein implementierungsspezifischer SQLSTATE-Wert definiert wurde. Die von SQLGetDiagRec im *MessageText-Puffer zurückgegebene Fehlermeldung beschreibt den Fehler und seine Ursache. |
HY001 | Fehler bei der Speicherbelegung | Der Treiber konnte den Speicher nicht zuordnen, der für die Unterstützung der Ausführung oder Vervollständigung der Funktion erforderlich ist. |
HY007 | Zugeordnete Anweisung ist nicht vorbereitet | SourceDescHandle war einem IRD zugeordnet, und das zugehörige Anweisungshandle befand sich nicht im vorbereiteten oder ausgeführten Zustand. |
HY010 | Funktionssequenzfehler | (DM) Das Deskriptorhandle in SourceDescHandle oder TargetDescHandle war einem StatementHandle zugeordnet, für den eine asynchron ausgeführte Funktion (nicht diese) aufgerufen wurde und beim Aufruf dieser Funktion weiterhin ausgeführt wurde. (DM) Das Deskriptorhandle in SourceDescHandle oder TargetDescHandle war einem StatementHandle zugeordnet, für das SQLExecute, SQLExecDirect, SQLBulkOperations oder SQLSetPos aufgerufen und SQL_NEED_DATA zurückgegeben wurde. Diese Funktion wurde aufgerufen, bevor Daten für alle Daten bei der Ausführung gesendet wurden. (DM) Eine asynchron ausgeführte Funktion wurde für das Verbindungshandle aufgerufen, das dem SourceDescHandle oder TargetDescHandle zugeordnet ist. Diese asynchrone Funktion wurde noch ausgeführt, als die SQLCopyDesc-Funktion aufgerufen wurde. (DM) SQLExecute, SQLExecDirect oder SQLMoreResults wurde für eines der Anweisungshandles aufgerufen, die dem SourceDescHandle oder TargetDescHandle zugeordnet sind, und SQL_PARAM_DATA_AVAILABLE zurückgegeben wurden. Diese Funktion wurde aufgerufen, bevor Daten für alle gestreamten Parameter abgerufen wurden. |
HY013 | Fehler bei der Speicherverwaltung | Der Funktionsaufruf konnte nicht verarbeitet werden, da auf die zugrunde liegenden Speicherobjekte nicht zugegriffen werden konnte, möglicherweise aufgrund von niedrigen Speicherbedingungen. |
HY016 | Ein Implementierungszeilendeskriptor kann nicht geändert werden. | TargetDescHandle war einer IRD zugeordnet. |
HY021 | Inkonsistente Deskriptorinformationen | Die bei einer Konsistenzprüfung überprüften Deskriptorinformationen waren nicht konsistent. Weitere Informationen finden Sie unter "Konsistenzprüfungen" in SQLSetDescField. |
HY092 | Ungültiger Attribut-/Optionsbezeichner | Der Aufruf von SQLCopyDesc hat einen Aufruf von SQLSetDescField aufgefordert, aber *ValuePtr war für das FieldIdentifier-Argument auf TargetDescHandle ungültig. |
HY117 | Die Verbindung wird aufgrund eines unbekannten Transaktionsstatus angehalten. Nur Trennen und schreibgeschützte Funktionen sind zulässig. | (DM) Weitere Informationen zum Angehaltenen Zustand finden Sie unter SQLEndTran-Funktion. |
HYT01 | Verbindungstimeout abgelaufen | Der Zeitraum für das Verbindungstimeout ist abgelaufen, bevor die Datenquelle auf die Anforderung reagiert hat. Der Zeitraum für das Verbindungstimeout wird über SQLSetConnectAttr festgelegt, SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | Der Treiber unterstützt diese Funktion nicht. | (DM) Der Treiber, der sourceDescHandle oder TargetDescHandle zugeordnet ist, unterstützt die Funktion nicht. |
Kommentare
Ein Aufruf von SQLCopyDesc kopiert die Felder des Quelldeskriptorhandles in das Zieldeskriptorhandle. Felder können nur in einen Anwendungsdeskriptor oder eine IPD, aber nicht in eine IRD kopiert werden. Felder können aus einer Anwendung oder einem Implementierungsdeskriptor kopiert werden.
Felder können nur aus einer IRD kopiert werden, wenn sich das Anweisungshandle im vorbereiteten oder ausgeführten Zustand befindet. Andernfalls gibt die Funktion SQLSTATE HY007 (Zugeordnete Anweisung ist nicht vorbereitet) zurück.
Felder können aus einer IPD kopiert werden, unabhängig davon, ob eine Anweisung vorbereitet wurde oder nicht. Wenn eine SQL-Anweisung mit dynamischen Parametern vorbereitet wurde und die automatische Auffüllung der IPD unterstützt und aktiviert wird, wird die IPD vom Treiber aufgefüllt. Wenn SQLCopyDesc mit der IPD als SourceDescHandle aufgerufen wird, werden die aufgefüllten Felder kopiert. Wenn die IPD nicht vom Treiber aufgefüllt wird, werden die Inhalte der felder, die ursprünglich in der IPD enthalten waren, kopiert.
Alle Felder des Deskriptors mit Ausnahme von SQL_DESC_ALLOC_TYPE (der angibt, ob das Deskriptorhandle automatisch oder explizit zugeordnet wurde) werden kopiert, unabhängig davon, ob das Feld für den Zieldeskriptor definiert ist oder nicht. Kopierte Felder überschreiben die vorhandenen Felder.
Der Treiber kopiert alle Deskriptorfelder, wenn die Argumente SourceDescHandle und TargetDescHandle demselben Treiber zugeordnet sind, auch wenn sich die Treiber in zwei verschiedenen Verbindungen oder Umgebungen befinden. Wenn die Argumente SourceDescHandle und TargetDescHandle verschiedenen Treibern zugeordnet sind, kopiert der Treiber-Manager von ODBC definierte Felder, kopiert jedoch keine vom Treiber definierten Felder oder Felder, die nicht von ODBC für den Typ des Deskriptors definiert sind.
Der Aufruf von SQLCopyDesc wird sofort abgebrochen, wenn ein Fehler auftritt.
Wenn das feld SQL_DESC_DATA_PTR kopiert wird, wird eine Konsistenzprüfung für den Zieldeskriptor durchgeführt. Wenn die Konsistenzprüfung fehlschlägt, wird SQLSTATE HY021 (Inkonsistente Deskriptorinformationen) zurückgegeben, und der Aufruf von SQLCopyDesc wird sofort abgebrochen. Weitere Informationen zu Konsistenzprüfungen finden Sie unter "Konsistenzprüfungen" in SQLSetDescRec-Funktion.
Deskriptorhandles können verbindungenübergreifend kopiert werden, auch wenn sich die Verbindungen in unterschiedlichen Umgebungen befinden. Wenn der Treiber-Manager erkennt, dass die Quell- und Zieldeskriptorhandles nicht zu derselben Verbindung gehören und die beiden Verbindungen zu separaten Treibern gehören, implementiert er SQLCopyDesc , indem er eine Feld-für-Feld-Kopie mit SQLGetDescField und SQLSetDescField durchführt.
Wenn SQLCopyDesc mit einem SourceDescHandle auf einem Treiber und einem TargetDescHandle auf einem anderen Treiber aufgerufen wird, wird die Fehlerwarteschlange der SourceDescHandle gelöscht. Dies tritt auf, weil SQLCopyDesc in diesem Fall durch Aufrufe von SQLGetDescField und SQLSetDescField implementiert wird.
Hinweis
Eine Anwendung kann einem StatementHandle möglicherweise ein explizit zugeordnetes Deskriptorhandle zuordnen, anstatt SQLCopyDesc aufzurufen, um Felder von einem Deskriptor in eine andere zu kopieren. Ein explizit zugeordneter Deskriptor kann einem anderen StatementHandle auf demselben ConnectionHandle zugeordnet werden, indem das SQL_ATTR_APP_ROW_DESC- oder SQL_ATTR_APP_PARAM_DESC-Anweisungsattribut auf das Handle des explizit zugeordneten Deskriptors festgelegt wird. Wenn dies geschehen ist, muss SQLCopyDesc nicht aufgerufen werden, um Deskriptorfeldwerte von einem Deskriptor in einen anderen zu kopieren. Ein Deskriptorhandle kann jedoch keinem StatementHandle in einem anderen ConnectionHandle zugeordnet werden. Um die gleichen Deskriptorfeldwerte für StatementHandles für verschiedene ConnectionHandles zu verwenden, muss SQLCopyDesc aufgerufen werden.
Eine Beschreibung der Felder in einem Deskriptorheader oder -Datensatz finden Sie unter SQLSetDescField-Funktion. Weitere Informationen zu Deskriptoren finden Sie unter Deskriptoren.
Kopieren von Zeilen zwischen Tabellen
Eine Anwendung kann Daten aus einer Tabelle in eine andere kopieren, ohne die Daten auf Anwendungsebene zu kopieren. Dazu bindet die Anwendung dieselben Datenpuffer und Deskriptorinformationen an eine Anweisung, die die Daten abruft, und die Anweisung, die die Daten in eine Kopie einfügt. Dies kann entweder durch gemeinsame Nutzung eines Anwendungsdeskriptors (Bindung eines explizit zugeordneten Deskriptors als ARD an eine Anweisung und die APD in einer anderen) oder durch Verwenden von SQLCopyDesc zum Kopieren der Bindungen zwischen der ARD und der APD der beiden Anweisungen erreicht werden. Wenn sich die -Anweisungen für unterschiedliche Verbindungen befinden, muss SQLCopyDesc verwendet werden. Darüber hinaus muss SQLCopyDesc aufgerufen werden, um die Bindungen zwischen der IRD und der IPD der beiden Anweisungen zu kopieren. Beim Kopieren von Anweisungen in derselben Verbindung muss der vom Treiber für einen Aufruf von SQLGetInfo zurückgegebene SQL_ACTIVE_STATEMENTS Informationstyp größer als 1 sein, damit dieser Vorgang erfolgreich ausgeführt werden kann. (Dies ist beim Kopieren zwischen Verbindungen nicht der Fall.)
Codebeispiel
Im folgenden Beispiel werden Deskriptorvorgänge verwendet, um die Felder der Tabelle PartsSource in die Tabelle PartsCopy zu kopieren. Der Inhalt der PartsSource-Tabelle wird in Rowsetpuffer in hstmt0 abgerufen. Diese Werte werden als Parameter einer INSERT-Anweisung auf hstmt1 verwendet, um die Spalten der PartsCopy-Tabelle aufzufüllen. Dazu werden die Felder der IRD von hstmt0 in die Felder der IPD von hstmt1 kopiert, und die Felder der ARD von hstmt0 werden in die Felder der APD von hstmt1 kopiert. Verwenden Sie SQLSetDescField , um das SQL_DESC_PARAMETER_TYPE-Attribut der IPD auf SQL_PARAM_INPUT festzulegen, wenn Sie IRD-Felder aus einer Anweisung mit Ausgabeparametern in IPD-Felder kopieren, die Eingabeparameter sein müssen.
#define ROWS 100
#define DESC_LEN 50
#define SQL_SUCCEEDED(rc) (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
// Template for a row
typedef struct {
SQLINTEGER sPartID;
SQLINTEGER cbPartID;
SQLUCHAR szDescription[DESC_LENGTH];
SQLINTEGER cbDescription;
REAL sPrice;
SQLINTEGER cbPrice;
} PartsSource;
PartsSource rget[ROWS]; // rowset buffer
SQLUSMALLINT sts_ptr[ROWS]; // status pointer
SQLHSTMT hstmt0, hstmt1;
SQLHDESC hArd0, hIrd0, hApd1, hIpd1;
// ARD and IRD of hstmt0
SQLGetStmtAttr(hstmt0, SQL_ATTR_APP_ROW_DESC, &hArd0, 0, NULL);
SQLGetStmtAttr(hstmt0, SQL_ATTR_IMP_ROW_DESC, &hIrd0, 0, NULL);
// APD and IPD of hstmt1
SQLGetStmtAttr(hstmt1, SQL_ATTR_APP_PARAM_DESC, &hApd1, 0, NULL);
SQLGetStmtAttr(hstmt1, SQL_ATTR_IMP_PARAM_DESC, &hIpd1, 0, NULL);
// Use row-wise binding on hstmt0 to fetch rows
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER) sizeof(PartsSource), 0);
// Set rowset size for hstmt0
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);
// Execute a select statement
SQLExecDirect(hstmt0, "SELECT PARTID, DESCRIPTION, PRICE FROM PARTS ORDER BY 3, 1, 2"",
SQL_NTS);
// Bind
SQLBindCol(hstmt0, 1, SQL_C_SLONG, rget[0].sPartID, 0,
&rget[0].cbPartID);
SQLBindCol(hstmt0, 2, SQL_C_CHAR, &rget[0].szDescription, DESC_LEN,
&rget[0].cbDescription);
SQLBindCol(hstmt0, 3, SQL_C_FLOAT, rget[0].sPrice,
0, &rget[0].cbPrice);
// Perform parameter bindings on hstmt1.
SQLCopyDesc(hArd0, hApd1);
SQLCopyDesc(hIrd0, hIpd1);
// Set the array status pointer of IRD
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_STATUS_PTR, sts_ptr, SQL_IS_POINTER);
// Set the ARRAY_STATUS_PTR field of APD to be the same
// as that in IRD.
SQLSetStmtAttr(hstmt1, SQL_ATTR_PARAM_OPERATION_PTR, sts_ptr, SQL_IS_POINTER);
// Set the hIpd1 records as input parameters
rc = SQLSetDescField(hIpd1, 1, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
rc = SQLSetDescField(hIpd1, 2, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
rc = SQLSetDescField(hIpd1, 3, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
// Prepare an insert statement on hstmt1. PartsCopy is a copy of
// PartsSource
SQLPrepare(hstmt1, "INSERT INTO PARTS_COPY VALUES (?, ?, ?)", SQL_NTS);
// In a loop, fetch a rowset, and copy the fetched rowset to PARTS_COPY
rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);
while (SQL_SUCCEEDED(rc)) {
// After the call to SQLFetchScroll, the status array has row
// statuses. This array is used as input status in the APD
// and hence determines which elements of the rowset buffer
// are inserted.
SQLExecute(hstmt1);
rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);
} // while
Verwandte Funktionen
Informationen über | Finden Sie unter |
---|---|
Abrufen mehrerer Deskriptorfelder | SQLGetDescRec-Funktion |
Festlegen eines einzelnen Deskriptorfelds | SQLSetDescField-Funktion |
Festlegen mehrerer Deskriptorfelder | SQLSetDescRec-Funktion |