Funzione SQLCopyDesc
Conformità
Versione introdotta: Conformità agli standard ODBC 3.0: ISO 92
Riepilogo
SQLCopyDesc copia le informazioni del descrittore da un handle descrittore a un altro.
Sintassi
SQLRETURN SQLCopyDesc(
SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle);
Argomenti
SourceDescHandle
[Input] Handle del descrittore di origine.
TargetDescHandle
[Input] Handle del descrittore di destinazione. L'argomento TargetDescHandle può essere un handle per un descrittore di applicazione o un IPD. TargetDescHandle non può essere impostato su un handle su un IRD o SQLCopyDesc restituirà SQLSTATE HY016 (Non è possibile modificare un descrittore di riga di implementazione).
Valori restituiti
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR o SQL_INVALID_HANDLE.
Diagnostica
Quando SQLCopyDesc restituisce SQL_ERROR o SQL_SUCCESS_WITH_INFO, è possibile ottenere un valore SQLSTATE associato chiamando SQLGetDiagRec con handleType di SQL_HANDLE_DESC e handle di TargetDescHandle. Se è stato passato un oggetto SourceDescHandle non valido nella chiamata, SQL_INVALID_HANDLE verrà restituito ma non verrà restituito sqlSTATE. La tabella seguente elenca i valori SQLSTATE comunemente restituiti da SQLCopyDesc e ne spiega ognuno nel contesto di questa funzione. La notazione "(DM)" precede le descrizioni di SQLSTATEs restituite da Gestione driver. Il codice restituito associato a ogni valore SQLSTATE è SQL_ERROR, a meno che non sia specificato diversamente.
Quando viene restituito un errore, la chiamata a SQLCopyDesc viene interrotta immediatamente e il contenuto dei campi nel descrittore TargetDescHandle non è definito.
Poiché SQLCopyDesc può essere implementato chiamando SQLGetDescField e SQLSetDescField, SQLCopyDesc può restituire SQLSTATEs restituiti da SQLGetDescField o SQLSetDescField.
SQLSTATE | Errore | Descrizione |
---|---|---|
01000 | Avviso generale | Messaggio informativo specifico del driver. (La funzione restituisce SQL_SUCCESS_WITH_INFO. |
08S01 | Errore del collegamento di comunicazione | Collegamento di comunicazione tra il driver e l'origine dati a cui è stato connesso il driver non è riuscito prima del completamento dell'elaborazione della funzione. |
HY000 | Errore generale: | Si è verificato un errore per il quale non è stato specificato SQLSTATE e per il quale non è stato definito alcun SQLSTATE specifico dell'implementazione. Il messaggio di errore restituito da SQLGetDiagRec nel buffer *MessageText descrive l'errore e la relativa causa. |
HY001 | Errore di allocazione della memoria | Il driver non è riuscito ad allocare la memoria necessaria per supportare l'esecuzione o il completamento della funzione. |
HY007 | Istruzione associata non preparata | SourceDescHandle è stato associato a un IRD e l'handle di istruzione associato non era nello stato preparato o eseguito. |
HY010 | Errore della sequenza di funzioni | (DM) L'handle del descrittore in SourceDescHandle o TargetDescHandle è stato associato a un statementHandle per il quale è stata chiamata una funzione in esecuzione asincrona (non questa) ed era ancora in esecuzione quando è stata chiamata questa funzione. (DM) L'handle del descrittore in SourceDescHandle o TargetDescHandle è stato associato a un statementHandle per cui SQLExecute, SQLExecDirect, SQLBulkOperations o SQLSetPos è stato chiamato e restituito SQL_NEED_DATA. Questa funzione è stata chiamata prima dell'invio dei dati per tutti i parametri o le colonne data-at-execution. (DM) È stata chiamata una funzione in esecuzione asincrona per l'handle di connessione associato a SourceDescHandle o TargetDescHandle. Questa funzione asincrona era ancora in esecuzione quando è stata chiamata la funzione SQLCopyDesc . (DM) SQLExecute, SQLExecDirect o SQLMoreResults è stato chiamato per uno degli handle di istruzione associati a SourceDescHandle o TargetDescHandle e restituito SQL_PARAM_DATA_AVAILABLE. Questa funzione è stata chiamata prima del recupero dei dati per tutti i parametri trasmessi. |
HY013 | Errore di gestione della memoria | Impossibile elaborare la chiamata di funzione perché non è stato possibile accedere agli oggetti di memoria sottostanti, probabilmente a causa di condizioni di memoria insufficiente. |
HY016 | Impossibile modificare un descrittore di riga di implementazione | TargetDescHandle è stato associato a un IRD. |
HY021 | Informazioni sul descrittore incoerente | Le informazioni del descrittore controllate durante un controllo coerenza non sono coerenti. Per altre informazioni, vedere "Verifiche di coerenza" in SQLSetDescField. |
HY092 | Identificatore di attributo/opzione non valido | La chiamata a SQLCopyDesc ha richiesto una chiamata a SQLSetDescField, ma *ValuePtr non è valido per l'argomento FieldIdentifier in TargetDescHandle. |
HY117 | La connessione viene sospesa a causa dello stato sconosciuto della transazione. Sono consentite solo funzioni disconnesse e di sola lettura. | (DM) Per altre informazioni sullo stato sospeso, vedere Funzione SQLEndTran. |
HYT01 | Il timeout della connessione è scaduto | Periodo di timeout della connessione scaduto prima che l'origine dati rispondesse alla richiesta. Il periodo di timeout della connessione viene impostato tramite SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | Il driver non supporta questa funzione | (DM) Il driver associato a SourceDescHandle o TargetDescHandle non supporta la funzione. |
Commenti
Una chiamata a SQLCopyDesc copia i campi dell'handle del descrittore di origine nell'handle del descrittore di destinazione. I campi possono essere copiati solo in un descrittore applicazione o in un DP, ma non in un IRD. I campi possono essere copiati da un'applicazione o da un descrittore di implementazione.
I campi possono essere copiati da un IRD solo se l'handle di istruzione si trova nello stato preparato o eseguito; in caso contrario, la funzione restituisce SQLSTATE HY007 (l'istruzione associata non è preparata).
I campi possono essere copiati da un IPD indipendentemente dal fatto che un'istruzione sia stata preparata o meno. Se è stata preparata un'istruzione SQL con parametri dinamici e la popolazione automatica dell'IPD è supportata e abilitata, l'IPD viene popolato dal driver. Quando SQLCopyDesc viene chiamato con l'IPD come SourceDescHandle, i campi popolati vengono copiati. Se l'IPD non viene popolato dal driver, il contenuto dei campi originariamente nell'IPD viene copiato.
Tutti i campi del descrittore, ad eccezione di SQL_DESC_ALLOC_TYPE (che specifica se l'handle del descrittore è stato allocato automaticamente o in modo esplicito), vengono copiati, indipendentemente dal fatto che il campo sia definito per il descrittore di destinazione. I campi copiati sovrascrivono i campi esistenti.
Il driver copia tutti i campi descrittore se gli argomenti SourceDescHandle e TargetDescHandle sono associati allo stesso driver, anche se i driver si trovano in due connessioni o ambienti diversi. Se gli argomenti SourceDescHandle e TargetDescHandle sono associati a driver diversi, Gestione driver copia i campi definiti da ODBC, ma non copia campi definiti dal driver o campi non definiti da ODBC per il tipo di descrittore.
La chiamata a SQLCopyDesc viene interrotta immediatamente se si verifica un errore.
Quando il campo SQL_DESC_DATA_PTR viene copiato, viene eseguita una verifica coerenza nel descrittore di destinazione. Se il controllo di coerenza ha esito negativo, viene restituito SQLSTATE HY021 (informazioni del descrittore incoerente) e la chiamata a SQLCopyDesc viene interrotta immediatamente. Per altre informazioni sui controlli di coerenza, vedere "Verifiche coerenza" nella funzione SQLSetDescRec.
Gli handle del descrittore possono essere copiati tra le connessioni anche se le connessioni si trovano in ambienti diversi. Se Gestione driver rileva che gli handle del descrittore di origine e di destinazione non appartengono alla stessa connessione e le due connessioni appartengono a driver separati, implementa SQLCopyDesc eseguendo una copia da campo per campo usando SQLGetDescField e SQLSetDescField.
Quando SQLCopyDesc viene chiamato con sourceDescHandle in un driver e targetDescHandle in un altro driver, la coda di errori di SourceDescHandle viene cancellata. Ciò si verifica perché SQLCopyDesc in questo caso viene implementato dalle chiamate a SQLGetDescField e SQLSetDescField.
Nota
Un'applicazione potrebbe essere in grado di associare un handle descrittore allocato in modo esplicito a un oggetto StatementHandle, anziché chiamare SQLCopyDesc per copiare i campi da un descrittore a un altro. Un descrittore allocato in modo esplicito può essere associato a un altro StatementHandle nello stesso oggetto ConnectionHandle impostando l'attributo di istruzione SQL_ATTR_APP_ROW_DESC o SQL_ATTR_APP_PARAM_DESC sull'handle del descrittore allocato in modo esplicito. Al termine, SQLCopyDesc non deve essere chiamato per copiare i valori dei campi del descrittore da un descrittore a un altro. Un handle di descrittore non può essere associato a un oggetto StatementHandle in un altro oggetto ConnectionHandle. Per utilizzare gli stessi valori di campo del descrittore in StatementHandles in connectionHandles diversi, è necessario chiamare SQLCopyDesc.
Per una descrizione dei campi in un'intestazione o un record descrittore, vedere Funzione SQLSetDescField. Per altre informazioni sui descrittori, vedere Descrittori.
Copia di righe tra tabelle
Un'applicazione può copiare dati da una tabella a un'altra senza copiare i dati a livello di applicazione. A tale scopo, l'applicazione associa gli stessi buffer di dati e le stesse informazioni del descrittore a un'istruzione che recupera i dati e l'istruzione che inserisce i dati in una copia. A tale scopo, è possibile condividere un descrittore dell'applicazione (associando un descrittore allocato in modo esplicito come ARD a un'istruzione e APD in un'altra) oppure usando SQLCopyDesc per copiare le associazioni tra il ARD e il APD delle due istruzioni. Se le istruzioni si trovano in connessioni diverse, è necessario usare SQLCopyDesc . È inoltre necessario chiamare SQLCopyDesc per copiare le associazioni tra IRD e IPD delle due istruzioni. Quando si copiano istruzioni nella stessa connessione, il tipo di informazioni SQL_ACTIVE_STATEMENTS restituito dal driver per una chiamata a SQLGetInfo deve essere maggiore di 1 affinché l'operazione abbia esito positivo. Questo non è il caso durante la copia tra le connessioni.
Esempio di codice
Nell'esempio seguente vengono usate le operazioni del descrittore per copiare i campi della tabella PartsSource nella tabella PartsCopy. Il contenuto della tabella PartsSource viene recuperato in buffer di set di righe in hstmt0. Questi valori vengono usati come parametri di un'istruzione INSERT in hstmt1 per popolare le colonne della tabella PartsCopy. A tale scopo, i campi dell'IRD di hstmt0 vengono copiati nei campi dell'IPD di hstmt1 e i campi del ARD di hstmt0 vengono copiati nei campi dell'APD di hstmt1. Usare SQLSetDescField per impostare l'attributo SQL_DESC_PARAMETER_TYPE IPD su SQL_PARAM_INPUT quando si copiano campi IRD da un'istruzione con parametri di output in campi IPD che devono essere parametri di input.
#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
Funzioni correlate
Per informazioni su | Vedere |
---|---|
Recupero di più campi descrittore | Funzione SQLGetDescRec |
Impostazione di un singolo campo descrittore | Funzione SQLSetDescField |
Impostazione di più campi descrittori | Funzione SQLSetDescRec |