Funzione SQLBulkOperations
Conformità
Versione introdotta: Conformità agli standard ODBC 3.0: ODBC
Riepilogo
SQLBulkOperations esegue operazioni bulk di inserimenti e segnalibri in blocco, tra cui aggiornamento, eliminazione e recupero in base al segnalibro.
Sintassi
SQLRETURN SQLBulkOperations(
SQLHSTMT StatementHandle,
SQLUSMALLINT Operation);
Argomenti
StatementHandle
[Input] Handle di istruzione.
Operazione
[Input] Operazione da eseguire:
SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK
Per altre informazioni, vedere "Commenti".
Resi
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR o SQL_INVALID_HANDLE.
Diagnostica
Quando SQLBulkOperations restituisce SQL_ERROR o SQL_SUCCESS_WITH_INFO, è possibile ottenere un valore SQLSTATE associato chiamando SQLGetDiagRec con handleTypedi SQL_HANDLE_STMT e handle di StatementHandle. La tabella seguente elenca i valori SQLSTATE restituiti in genere da SQLBulkOperations e 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.
Per tutti gli SQLSTATEs che possono restituire SQL_SUCCESS_WITH_INFO o SQL_ERROR (ad eccezione di 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO viene restituito se si verifica un errore in una o più righe, ma non tutte, righe di un'operazione multirow e SQL_ERROR viene restituito se si verifica un errore in un'operazione a riga singola.
SQLSTATE | Errore | Descrizione |
---|---|---|
01000 | Avviso generale | Messaggio informativo specifico del driver. (La funzione restituisce SQL_SUCCESS_WITH_INFO. |
01004 | Troncamento a destra dei dati stringa | L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e i dati stringa o binari restituiti per una colonna o colonne con un tipo di dati di SQL_C_CHAR o SQL_C_BINARY hanno causato il troncamento di dati binari non null o non NULL. |
01S01 | Errore nella riga | L'argomento Operation è stato SQL_ADD e si è verificato un errore in una o più righe durante l'esecuzione dell'operazione, ma almeno una riga è stata aggiunta correttamente. (La funzione restituisce SQL_SUCCESS_WITH_INFO. Questo errore viene generato solo quando un'applicazione utilizza odbc 2.x driver.) |
01S07 | Troncamento frazionario | L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK, il tipo di dati del buffer dell'applicazione non è stato SQL_C_CHAR o SQL_C_BINARY e i dati restituiti ai buffer dell'applicazione per una o più colonne sono stati troncati. Per i tipi di dati numerici C, la parte frazionaria del numero è stata troncata. Per i tipi di dati time, timestamp e interval C che contengono un componente time, la parte frazionaria dell'ora è stata troncata. (La funzione restituisce SQL_SUCCESS_WITH_INFO. |
07006 | Violazione dell'attributo del tipo di dati con restrizioni | L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e non è stato possibile convertire il valore di dati di una colonna nel set di risultati nel tipo di dati specificato dall'argomento TargetType nella chiamata a SQLBindCol. L'argomento Operation è stato SQL_UPDATE_BY_BOOKMARK o SQL_ADD e il valore dei dati nei buffer dell'applicazione non può essere convertito nel tipo di dati di una colonna nel set di risultati. |
07009 | Indice descrittore non valido | L'argomento Operation è stato SQL_ADD e una colonna è stata associata con un numero di colonna maggiore del numero di colonne nel set di risultati. |
21S02 | Il grado di tabella derivata non corrisponde all'elenco di colonne | L'argomento Operation è stato SQL_UPDATE_BY_BOOKMARK e nessuna colonna era aggiornabile perché tutte le colonne erano non associate o di sola lettura oppure il valore nel buffer di lunghezza/indicatore associato era SQL_COLUMN_IGNORE. |
22001 | Troncamento a destra dei dati stringa | L'assegnazione di un carattere o di un valore binario a una colonna nel set di risultati ha comportato il troncamento di caratteri o byte non null (per i caratteri binari). |
22003 | Valore numerico non compreso nell'intervallo | L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK e l'assegnazione di un valore numerico a una colonna nel set di risultati ha causato il troncamento dell'intera parte del numero, anziché frazionaria. L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e la restituzione del valore numerico per una o più colonne associate avrebbe causato una perdita di cifre significative. |
22007 | Formato datetime non valido | L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK e l'assegnazione di un valore di data o timestamp a una colonna nel set di risultati ha causato l'interruzione del campo anno, mese o giorno. L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e la restituzione del valore di data o timestamp per una o più colonne associate avrebbe causato l'interruzione dell'intervallo del campo anno, mese o giorno. |
22008 | Overflow del campo data/ora | L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK e le prestazioni dell'aritmetica datetime sui dati inviati a una colonna nel set di risultati hanno generato un campo datetime (l'anno, il mese, il giorno, l'ora, l'ora, il minuto o il secondo campo) del risultato che non rientra nell'intervallo consentito di valori per il campo o non è valido in base alle regole naturali del calendario gregoriano per datetimes. L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e le prestazioni dell'aritmetica datetime sui dati recuperati dal set di risultati hanno generato un campo datetime (il campo year, month, day, hour, minute o second) del risultato che non rientra nell'intervallo consentito di valori per il campo o non è valido in base alle regole naturali del calendario gregoriano per datetimes. |
22015 | Overflow del campo intervallo | L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK e l'assegnazione di un tipo C numerico o intervallo esatto a un tipo di dati SQL intervallo ha causato una perdita di cifre significative. L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK. Quando si assegna a un tipo SQL di intervallo, non è presente alcuna rappresentazione del valore del tipo C nel tipo SQL intervallo. L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK e l'assegnazione da un tipo SQL numerico o intervallo esatto a un tipo C intervallo ha causato una perdita di cifre significative nel campo iniziale. L'argomento Operation è stato SQL_FETCH_BY_BOOKMARK. Quando si assegna a un tipo C intervallo, non è presente alcuna rappresentazione del valore del tipo SQL nel tipo C intervallo. |
22018 | Valore carattere non valido per la specifica del cast | L'argomento Operation era SQL_FETCH_BY_BOOKMARK, il tipo C era un tipo numerico esatto o approssimativo, un tipo di dati datetime o un intervallo, il tipo SQL della colonna era un tipo di dati carattere e il valore nella colonna non era un valore letterale valido del tipo C associato. L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK; il tipo SQL era un valore numerico esatto o approssimativo, un tipo datetime o un tipo di dati interval, il tipo C era SQL_C_CHAR e il valore nella colonna non era un valore letterale valido del tipo SQL associato. |
23000 | Violazione del vincolo di integrità | L'argomento Operation è stato SQL_ADD, SQL_DELETE_BY_BOOKMARK o SQL_UPDATE_BY_BOOKMARK e è stato violato un vincolo di integrità. L'argomento Operation è stato SQL_ADD e una colonna non associata è definita come NOT NULL e non ha un valore predefinito. L'argomento Operation è stato SQL_ADD, la lunghezza specificata nel buffer StrLen_or_IndPtr associato è stata SQL_COLUMN_IGNORE e la colonna non ha un valore predefinito. |
24000 | Stato del cursore non valido | StatementHandle era in uno stato eseguito, ma nessun set di risultati era associato a StatementHandle. |
40001 | Errore di serializzazione | È stato eseguito il rollback della transazione a causa di un deadlock della risorsa con un'altra transazione. |
40003 | Completamento istruzione sconosciuto | La connessione associata non è riuscita durante l'esecuzione di questa funzione e non è possibile determinare lo stato della transazione. |
42000 | Errore di sintassi o violazione di accesso | Il driver non è riuscito a bloccare la riga in base alle esigenze per eseguire l'operazione richiesta nell'argomento Operation . |
44000 | Violazione della clausola WITH CHECK OPTION | L'argomento Operation è stato SQL_ADD o SQL_UPDATE_BY_BOOKMARK e l'inserimento o l'aggiornamento è stato eseguito su una tabella visualizzata (o una tabella derivata dalla tabella visualizzata) creata specificando WITH CHECK OPTION, in modo che una o più righe interessate dall'inserimento o aggiornamento non saranno più presenti nella tabella visualizzata. |
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 memoria necessaria per supportare l'esecuzione o il completamento della funzione. |
HY008 | Operazione annullata | L'elaborazione asincrona è stata abilitata per StatementHandle. La funzione è stata chiamata e prima di completare l'esecuzione, SQLCancel o SQLCancelHandle è stata chiamata in StatementHandle. La funzione è stata quindi chiamata di nuovo in StatementHandle. La funzione è stata chiamata e prima del completamento dell'esecuzione, SQLCancel o SQLCancelHandle è stato chiamato su StatementHandle da un thread diverso in un'applicazione multithread. |
HY010 | Errore della sequenza di funzioni | (DM) È stata chiamata una funzione in esecuzione asincrona per l'handle di connessione associato a StatementHandle. Questa funzione asincrona era ancora in esecuzione quando è stata chiamata la funzione SQLBulkOperations . (DM) SQLExecute, SQLExecDirect o SQLMoreResults è stato chiamato per StatementHandle e restituito SQL_PARAM_DATA_AVAILABLE. Questa funzione è stata chiamata prima del recupero dei dati per tutti i parametri trasmessi. (DM) StatementHandle specificato non era in uno stato eseguito. La funzione è stata chiamata senza prima chiamare SQLExecDirect, SQLExecute o una funzione di catalogo. (DM) Una funzione in esecuzione asincrona (non questa) è stata chiamata per StatementHandle ed è ancora in esecuzione quando questa funzione è stata chiamata. (DM) SQLExecute, SQLExecDirect o SQLSetPos è stato chiamato per StatementHandle 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) Il driver era ODBC 2.X driver e SQLBulkOperations è stato chiamato per un StatementHandle prima della chiamata di SQLFetchScroll o SQLFetch . (DM) SQLBulkOperations è stato chiamato dopo la chiamata di SQLExtendedFetch su StatementHandle. |
HY011 | Impossibile impostare l'attributo ora | (DM) Il driver era ODBC 2.X driver e l'attributo di istruzione SQL_ATTR_ROW_STATUS_PTR è stato impostato tra le chiamate a SQLFetch o SQLFetchScroll e SQLBulkOperations. |
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. |
HY090 | Lunghezza della stringa o del buffer non valida | L'argomento Operation era SQL_ADD o SQL_UPDATE_BY_BOOKMARK; un valore di dati non era un puntatore Null, il tipo di dati C era SQL_C_BINARY o SQL_C_CHAR e il valore della lunghezza della colonna era minore di 0, ma non uguale a SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS o SQL_NULL_DATA, o minore o uguale a SQL_LEN_DATA_AT_EXEC_OFFSET. Il valore in un buffer di lunghezza/indicatore è stato SQL_DATA_AT_EXEC; il tipo SQL era SQL_LONGVARCHAR, SQL_LONGVARBINARY o un tipo di dati lungo specifico dell'origine dati; e il tipo di informazioni SQL_NEED_LONG_DATA_LEN in SQLGetInfo era "Y". L'argomento Operation è stato SQL_ADD, l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARK è stato impostato su SQL_UB_VARIABLE e la colonna 0 è stata associata a un buffer la cui lunghezza non è uguale alla lunghezza massima per il segnalibro per questo set di risultati. Questa lunghezza è disponibile nel campo SQL_DESC_OCTET_LENGTH di IRD e può essere ottenuta chiamando SQLDescribeCol, SQLColAttribute o SQLGetDescField. |
HY092 | Identificatore di attributo non valido | (DM) Il valore specificato per l'argomento Operation non è valido. L'argomento Operation è stato SQL_ADD, SQL_UPDATE_BY_BOOKMARK o SQL_DELETE_BY_BOOKMARK e l'attributo dell'istruzione SQL_ATTR_CONCURRENCY è stato impostato su SQL_CONCUR_READ_ONLY. L'argomento Operation è stato SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK o SQL_UPDATE_BY_BOOKMARK e la colonna del segnalibro non è stata associata o l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARKS è stato impostato su SQL_UB_OFF. |
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. |
HYC00 | Funzionalità facoltativa non implementata | Il driver o l'origine dati non supporta l'operazione richiesta nell'argomento Operation . |
HYT00 | Timeout scaduto | Periodo di timeout della query scaduto prima che l'origine dati restituisca il set di risultati. Il periodo di timeout viene impostato tramite SQLSetStmtAttr con un argomento Attribute di SQL_ATTR_QUERY_TIMEOUT. |
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 StatementHandle non supporta la funzione. |
IM017 | Il polling è disabilitato in modalità di notifica asincrona | Ogni volta che viene usato il modello di notifica, il polling è disabilitato. |
IM018 | SQLCompleteAsync non è stato chiamato per completare l'operazione asincrona precedente su questo handle. | Se la chiamata di funzione precedente sull'handle restituisce SQL_STILL_EXECUTING e se la modalità di notifica è abilitata, è necessario chiamare SQLCompleteAsync sull'handle per eseguire la post-elaborazione e completare l'operazione. |
Commenti
Attenzione
Per informazioni sugli stati dell'istruzione in cui è possibile chiamare SQLBulkOperations e sulle operazioni da eseguire per garantire la compatibilità con ODBC 2.X applicazioni, vedere la sezione Cursori a blocchi, Cursori scorrevoli e Compatibilità con le versioni precedenti in Appendice G: Linee guida per il driver per la compatibilità con le versioni precedenti.
Un'applicazione usa SQLBulkOperations per eseguire le operazioni seguenti sulla tabella o sulla vista di base che corrisponde alla query corrente:
Aggiungere nuove righe.
Aggiornare un set di righe in cui ogni riga è identificata da un segnalibro.
Eliminare un set di righe in cui ogni riga è identificata da un segnalibro.
Recuperare un set di righe in cui ogni riga è identificata da un segnalibro.
Dopo una chiamata a SQLBulkOperations, la posizione del cursore del blocco non è definita. L'applicazione deve chiamare SQLFetchScroll per impostare la posizione del cursore. Un'applicazione deve chiamare SQLFetchScroll solo con un argomento FetchOrientation di SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE o SQL_FETCH_BOOKMARK. La posizione del cursore non è definita se l'applicazione chiama SQLFetch o SQLFetchScroll con un argomento FetchOrientation di SQL_FETCH_PRIOR, SQL_FETCH_NEXT o SQL_FETCH_RELATIVE.
Una colonna può essere ignorata nelle operazioni bulk eseguite da una chiamata a SQLBulkOperations impostando il buffer di lunghezza/indicatore di colonna specificato nella chiamata a SQLBindCol, su SQL_COLUMN_IGNORE.
Non è necessario che l'applicazione imposti l'attributo dell'istruzione SQL_ATTR_ROW_OPERATION_PTR quando chiama SQLBulkOperations perché le righe non possono essere ignorate durante l'esecuzione di operazioni bulk con questa funzione.
Il buffer a cui punta l'attributo dell'istruzione SQL_ATTR_ROWS_FETCHED_PTR contiene il numero di righe interessate da una chiamata a SQLBulkOperations.
Quando l'argomento Operation è SQL_ADD o SQL_UPDATE_BY_BOOKMARK e l'elenco di selezione della specifica della query associata al cursore contiene più riferimenti alla stessa colonna, viene definito dal driver se viene generato un errore o se il driver ignora i riferimenti duplicati ed esegue le operazioni richieste.
Per altre informazioni sull'uso di SQLBulkOperations, vedere Aggiornamento dei dati con SQLBulkOperations.
Esecuzione di inserimenti bulk
Per inserire dati con SQLBulkOperations, un'applicazione esegue la sequenza di passaggi seguente:
Esegue una query che restituisce un set di risultati.
Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE sul numero di righe da inserire.
Chiama SQLBindCol per associare i dati da inserire. I dati sono associati a una matrice con dimensioni uguali al valore di SQL_ATTR_ROW_ARRAY_SIZE.
Nota
La dimensione della matrice a cui punta l'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR deve essere uguale a SQL_ATTR_ROW_ARRAY_SIZE o SQL_ATTR_ROW_STATUS_PTR deve essere un puntatore Null.
Chiama SQLBulkOperations(StatementHandle, SQL_ADD) per eseguire l'inserimento.
Se l'applicazione ha impostato l'attributo di istruzione SQL_ATTR_ROW_STATUS_PTR, può esaminare questa matrice per visualizzare il risultato dell'operazione.
Se un'applicazione associa la colonna 0 prima di chiamare SQLBulkOperations con un argomento Operation di SQL_ADD, il driver aggiornerà i buffer della colonna associata 0 con i valori del segnalibro per la riga appena inserita. Affinché ciò accada, l'applicazione deve avere impostato l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARKS su SQL_UB_VARIABLE prima di eseguire l'istruzione . Non funziona con ODBC 2.x driver.)
I dati lunghi possono essere aggiunti in parti da SQLBulkOperations, usando chiamate a SQLParamData e SQLPutData. Per altre informazioni, vedere "Fornire dati lunghi per inserimenti e aggiornamenti bulk" più avanti in questa guida di riferimento alla funzione.
Non è necessario che l'applicazione chiami SQLFetch o SQLFetchScroll prima di chiamare SQLBulkOperations (tranne quando si passa a odbc 2.x driver; vedere Compatibilità con le versioni precedenti e conformità degli standard.
Il comportamento è definito dal driver se SQLBulkOperations, con un argomento Operation di SQL_ADD, viene chiamato su un cursore che contiene colonne duplicate. Il driver può restituire un'istruzione SQLSTATE definita dal driver, aggiungere i dati alla prima colonna visualizzata nel set di risultati o eseguire altri comportamenti definiti dal driver.
Esecuzione di aggiornamenti in blocco tramite segnalibri
Per eseguire gli aggiornamenti in blocco usando segnalibri con SQLBulkOperations, un'applicazione esegue i passaggi seguenti in sequenza:
Imposta l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARKS su SQL_UB_VARIABLE.
Esegue una query che restituisce un set di risultati.
Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE sul numero di righe da aggiornare.
Chiama SQLBindCol per associare i dati da aggiornare. I dati sono associati a una matrice con dimensioni uguali al valore di SQL_ATTR_ROW_ARRAY_SIZE. Chiama anche SQLBindCol per associare la colonna 0 (la colonna del segnalibro).
Copia i segnalibri per le righe a cui è interessato l'aggiornamento nella matrice associata alla colonna 0.
Aggiorna i dati nei buffer associati.
Nota
La dimensione della matrice a cui punta l'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR deve essere uguale a SQL_ATTR_ROW_ARRAY_SIZE o SQL_ATTR_ROW_STATUS_PTR deve essere un puntatore Null.
Chiama SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).
Nota
Se l'applicazione ha impostato l'attributo di istruzione SQL_ATTR_ROW_STATUS_PTR, può esaminare questa matrice per visualizzare il risultato dell'operazione.
Facoltativamente, chiama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) per recuperare i dati nei buffer dell'applicazione associati per verificare che si sia verificato l'aggiornamento.
Se i dati sono stati aggiornati, il driver modifica il valore nella matrice di stato della riga per le righe appropriate in modo da SQL_ROW_UPDATED.
Gli aggiornamenti in blocco eseguiti da SQLBulkOperations possono includere dati lunghi usando chiamate a SQLParamData e SQLPutData. Per altre informazioni, vedere "Fornire dati lunghi per inserimenti e aggiornamenti bulk" più avanti in questa guida di riferimento alla funzione.
Se i segnalibri vengono mantenuti tra i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di eseguire l'aggiornamento tramite segnalibri. Può usare segnalibri archiviati da un cursore precedente. Se i segnalibri non vengono mantenuti tra i cursori, l'applicazione deve chiamare SQLFetch o SQLFetchScroll per recuperare i segnalibri.
Il comportamento è definito dal driver se SQLBulkOperations, con un argomento Operation di SQL_UPDATE_BY_BOOKMARK, viene chiamato su un cursore che contiene colonne duplicate. Il driver può restituire un'istruzione SQLSTATE definita dal driver, aggiornare la prima colonna visualizzata nel set di risultati o eseguire altri comportamenti definiti dal driver.
Esecuzione di recupero bulk tramite segnalibri
Per eseguire il recupero bulk tramite segnalibri con SQLBulkOperations, un'applicazione esegue i passaggi seguenti in sequenza:
Imposta l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARKS su SQL_UB_VARIABLE.
Esegue una query che restituisce un set di risultati.
Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE sul numero di righe da recuperare.
Chiama SQLBindCol per associare i dati da recuperare. I dati sono associati a una matrice con dimensioni uguali al valore di SQL_ATTR_ROW_ARRAY_SIZE. Chiama anche SQLBindCol per associare la colonna 0 (la colonna del segnalibro).
Copia i segnalibri per le righe a cui è interessato il recupero nella matrice associata alla colonna 0. Si presuppone che l'applicazione abbia già ottenuto i segnalibri separatamente.
Nota
La dimensione della matrice a cui punta l'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR deve essere uguale a SQL_ATTR_ROW_ARRAY_SIZE o SQL_ATTR_ROW_STATUS_PTR deve essere un puntatore Null.
Chiama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).
Se l'applicazione ha impostato l'attributo di istruzione SQL_ATTR_ROW_STATUS_PTR, può esaminare questa matrice per visualizzare il risultato dell'operazione.
Se i segnalibri vengono mantenuti tra i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di recuperare i segnalibri. Può usare segnalibri archiviati da un cursore precedente. Se i segnalibri non vengono mantenuti tra cursori, l'applicazione deve chiamare SQLFetch o SQLFetchScroll una volta per recuperare i segnalibri.
Esecuzione di eliminazioni bulk tramite segnalibri
Per eseguire eliminazioni bulk usando segnalibri con SQLBulkOperations, un'applicazione esegue i passaggi seguenti in sequenza:
Imposta l'attributo dell'istruzione SQL_ATTR_USE_BOOKMARKS su SQL_UB_VARIABLE.
Esegue una query che restituisce un set di risultati.
Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE sul numero di righe da eliminare.
Chiama SQLBindCol per associare la colonna 0 (colonna del segnalibro).
Copia i segnalibri per le righe a cui è interessato l'eliminazione nella matrice associata alla colonna 0.
Nota
La dimensione della matrice a cui punta l'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR deve essere uguale a SQL_ATTR_ROW_ARRAY_SIZE o SQL_ATTR_ROW_STATUS_PTR deve essere un puntatore Null.
Chiama SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).
Se l'applicazione ha impostato l'attributo di istruzione SQL_ATTR_ROW_STATUS_PTR, può esaminare questa matrice per visualizzare il risultato dell'operazione.
Se i segnalibri vengono mantenuti tra i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di eliminare i segnalibri. Può usare segnalibri archiviati da un cursore precedente. Se i segnalibri non vengono mantenuti tra cursori, l'applicazione deve chiamare SQLFetch o SQLFetchScroll una volta per recuperare i segnalibri.
Fornitura di dati lunghi per inserimenti e aggiornamenti bulk
I dati lunghi possono essere forniti per inserimenti bulk e aggiornamenti eseguiti dalle chiamate a SQLBulkOperations. Per inserire o aggiornare dati lunghi, un'applicazione esegue i passaggi seguenti oltre ai passaggi descritti nelle sezioni "Esecuzione di inserimenti bulk" e "Esecuzione di aggiornamenti in blocco tramite segnalibri" più indietro in questo argomento.
Quando associa i dati tramite SQLBindCol, l'applicazione inserisce un valore definito dall'applicazione, ad esempio il numero di colonna, nel buffer *TargetValuePtr per le colonne data-at-execution. Il valore può essere usato in un secondo momento per identificare la colonna.
L'applicazione inserisce il risultato della macro SQL_LEN_DATA_AT_EXEC(lunghezza) nel buffer *StrLen_or_IndPtr . Se il tipo di dati SQL della colonna è SQL_LONGVARBINARY, SQL_LONGVARCHAR o un tipo di dati specifico dell'origine dati long e il driver restituisce "Y" per il tipo di informazioni SQL_NEED_LONG_DATA_LEN in SQLGetInfo, la lunghezza è il numero di byte di dati da inviare per il parametro; in caso contrario, deve essere un valore non negativo e viene ignorato.
Quando viene chiamato SQLBulkOperations , se sono presenti colonne data-at-execution, la funzione restituisce SQL_NEED_DATA e procede al passaggio 3, che segue. Se non sono presenti colonne di dati in fase di esecuzione, il processo è completo.
L'applicazione chiama SQLParamData per recuperare l'indirizzo del buffer *TargetValuePtr per la prima colonna data-at-execution da elaborare. SQLParamData restituisce SQL_NEED_DATA. L'applicazione recupera il valore definito dall'applicazione dal buffer *TargetValuePtr .
Nota
Sebbene i parametri di data-at-execution siano simili alle colonne data-at-execution, il valore restituito da SQLParamData è diverso per ognuno di essi.
Le colonne data-at-execution sono colonne in un set di righe per cui i dati verranno inviati con SQLPutData quando una riga viene aggiornata o inserita con SQLBulkOperations. Sono associati a SQLBindCol. Il valore restituito da SQLParamData è l'indirizzo della riga nel buffer *TargetValuePtr in fase di elaborazione.
L'applicazione chiama SQLPutData una o più volte per inviare dati per la colonna. È necessaria più di una chiamata se non è possibile restituire tutti i valori di dati nel buffer *TargetValuePtr specificato in SQLPutData. Sono consentite più chiamate a SQLPutData per la stessa colonna solo quando si inviano dati C carattere a una colonna con un tipo di dati carattere, binario o specifico dell'origine dati o quando si inviano dati C binari a una colonna con un carattere, tipo di dati binario o specifico dell'origine dati.
L'applicazione chiama di nuovo SQLParamData per segnalare che tutti i dati sono stati inviati per la colonna.
Se sono presenti più colonne data-at-execution, SQLParamData restituisce SQL_NEED_DATA e l'indirizzo del buffer TargetValuePtr per l'elaborazione della colonna data-at-execution successiva. L'applicazione ripete i passaggi 4 e 5.
Se non sono presenti altre colonne di dati in fase di esecuzione, il processo viene completato. Se l'istruzione è stata eseguita correttamente, SQLParamData restituisce SQL_SUCCESS o SQL_SUCCESS_WITH_INFO; se l'esecuzione non è riuscita, restituisce SQL_ERROR. A questo punto, SQLParamData può restituire qualsiasi SQLSTATE che può essere restituito da SQLBulkOperations.
Se l'operazione viene annullata o si verifica un errore in SQLParamData o SQLPutData dopo che SQLBulkOperations restituisce SQL_NEED_DATA e prima dell'invio dei dati per tutte le colonne di esecuzione dei dati, l'applicazione può chiamare solo SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData o SQLPutData per l'istruzione o la connessione associata all'istruzione. Se chiama qualsiasi altra funzione per l'istruzione o la connessione associata all'istruzione , la funzione restituisce SQL_ERROR e SQLSTATE HY010 (errore della sequenza di funzioni).
Se l'applicazione chiama SQLCancel mentre il driver necessita ancora di dati per le colonne data-at-execution, il driver annulla l'operazione. L'applicazione può quindi chiamare di nuovo SQLBulkOperations . L'annullamento non influisce sullo stato del cursore o sulla posizione corrente del cursore.
Matrice di stato riga
La matrice di stato della riga contiene valori di stato per ogni riga di dati nel set di righe dopo una chiamata a SQLBulkOperations. Il driver imposta i valori di stato in questa matrice dopo una chiamata a SQLFetch, SQLFetchScroll, SQLSetPos o SQLBulkOperations. Questa matrice viene inizialmente popolata da una chiamata a SQLBulkOperations se SQLFetch o SQLFetchScroll non è stato chiamato prima di SQLBulkOperations. Questa matrice punta all'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR. Il numero di elementi nelle matrici di stato delle righe deve essere uguale al numero di righe nel set di righe, come definito dall'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE. Per informazioni su questa matrice di stato della riga, vedere SQLFetch.
Esempio di codice
Nell'esempio seguente vengono recuperate 10 righe di dati alla volta dalla tabella Customers. Richiede quindi all'utente di eseguire un'azione. Per ridurre il traffico di rete, gli aggiornamenti del buffer di esempio, le eliminazioni e gli inserimenti in locale nelle matrici associate, ma con offset oltre i dati del set di righe. Quando l'utente sceglie di inviare aggiornamenti, eliminazioni e inserimenti nell'origine dati, il codice imposta l'offset di associazione in modo appropriato e chiama SQLBulkOperations. Per semplicità, l'utente non può memorizzare nel buffer più di 10 aggiornamenti, eliminazioni o inserimenti.
// 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);
}
Funzioni correlate
Per informazioni su | Vedere |
---|---|
Associazione di un buffer a una colonna in un set di risultati | Funzione SQLBindCol |
Annullamento dell'elaborazione delle istruzioni | Funzione SQLCancel |
Recupero di un blocco di dati o scorrimento di un set di risultati | Funzione SQLFetchScroll |
Recupero di un singolo campo di un descrittore | Funzione SQLGetDescField |
Recupero di più campi di un descrittore | Funzione SQLGetDescRec |
Impostazione di un singolo campo di un descrittore | Funzione SQLSetDescField |
Impostazione di più campi di un descrittore | Funzione SQLSetDescRec |
Posizionamento del cursore, aggiornamento dei dati nel set di righe o aggiornamento o eliminazione di dati nel set di righe | Funzione SQLSetPos |
Impostazione di un attributo di istruzione | Funzione SQLSetStmtAttr |