Funzione SQLBulkOperations

Conformità
Versione introdotta: Conformità agli Standard ODBC 3.0: ODBC

Sommario
SQLBulkOperations esegue inserimenti e operazioni di bookmark in massa, inclusi aggiornamento, cancellazione e recupero tramite segnalibri.

Sintassi

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

Arguments

StatementHandle
[Input] Handle di istruzione.

Operation
[Input] Operazione da eseguire:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

Per altre informazioni, vedere "Commenti".

Returns

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, un valore SQLSTATE associato può essere ottenuto chiamando SQLGetDiagRec con un HandleType di SQL_HANDLE_STMT e un Handle di StatementHandle. La tabella seguente elenca i valori SQLSTATE tipicamente restituiti da SQLBulkOperations e spiega ciascuno nel contesto di questa funzione; la notazione "(DM)" precede le descrizioni degli stati SQL restituite dal Driver Manager. Il codice restituito associato a ogni valore SQLSTATE è SQL_ERROR, a meno che non sia specificato diversamente.

Per tutti quegli stati SQL che possono restituire SQL_SUCCESS_WITH_INFO o SQL_ERROR (eccetto gli stati SQL1xxx), SQL_SUCCESS_WITH_INFO viene restituito se si verifica un errore su una o più, ma non su tutte, righe di un'operazione a più righe, e SQL_ERROR viene restituito se si verifica un errore su un'operazione a una singola riga.

SQLSTATE Error Description
01000 Avviso generale Messaggio informativo specifico del driver. (La funzione restituisce SQL_SUCCESS_WITH_INFO.
01004 Troncamento a destra dei dati della stringa L'argomento Operation era SQL_FETCH_BY_BOOKMARK, e i dati stringa o binari restituiti per una colonna o colonne con un tipo di dato SQL_C_CHAR o SQL_C_BINARY portavano alla troncatura di dati binari non vuoti o non NULL.
01S01 Errore in riga L'argomento Operazione era SQL_ADD, e si verificava un errore in una o più righe durante l'esecuzione dell'operazione, ma almeno una riga era stata aggiunta con successo. (La funzione restituisce SQL_SUCCESS_WITH_INFO.

(Questo errore viene generato solo quando un'applicazione lavora con un ODBC 2. x driver.)
01S07 Troncamento frazionario L'argomento Operation era SQL_FETCH_BY_BOOKMARK, il tipo di dato del buffer applicativo non era SQL_C_CHAR o SQL_C_BINARY, e i dati restituiti ai buffer applicativo per una o più colonne venivano troncati. (Per i tipi di dati numerici C, la parte frazionaria del numero veniva troncata. Per i tipi di dati di tempo, timestamp e intervallo C che contengono una componente temporale, la porzione frazionaria del tempo veniva troncata.)

(La funzione restituisce SQL_SUCCESS_WITH_INFO.
07006 Violazione dell'attributo del tipo di dati con restrizioni L'argomento Operazione era SQL_FETCH_BY_BOOKMARK, e il valore dati di una colonna nell'insieme di risultati non poteva essere convertito nel tipo di dato specificato dall'argomento TargetType nella chiamata a SQLBindCol.

L'argomento Operation era SQL_UPDATE_BY_BOOKMARK o SQL_ADD, e il valore dei dati nei buffer applicativi non poteva essere convertito nel tipo di dato di una colonna nell'insieme di risultati.
07009 Indice descrittore non valido L'operazione argomentazione era SQL_ADD, e una colonna veniva vincolata con un numero di colonne maggiore del numero di colonne nell'insieme dei risultati.
21S02 Il grado di tabella derivata non corrisponde all'elenco di colonne L'Operazione dell'argomentazione fu SQL_UPDATE_BY_BOOKMARK; e nessuna colonna era aggiornabile perché tutte le colonne erano non legate o di sola lettura, oppure il valore nel buffer di lunghezza/indicatore limitato era SQL_COLUMN_IGNORE.
22001 Troncamento a destra dei dati della stringa L'assegnazione di un carattere o di un valore binario a una colonna nell'insieme di risultati comportava la troncatura di caratteri o byte non vuoti (per i caratteri) o non nulli (per i binari).
22003 Valore numerico non compreso nell'intervallo L'argomento Operazione era SQL_ADD o SQL_UPDATE_BY_BOOKMARK, e l'assegnazione di un valore numerico a una colonna nell'insieme dei risultati causava la troncazione dell'intera parte (anziché frazionaria).

L'argomento Operation era SQL_FETCH_BY_BOOKMARK, e restituire il valore numerico per una o più colonne legate avrebbe causato una perdita di cifre significative.
22007 Formato datetime non valido L'argomento Operazione era SQL_ADD o SQL_UPDATE_BY_BOOKMARK, e l'assegnazione di un valore di data o timestamp a una colonna nell'insieme dei risultati faceva sì che il campo anno, mese o giorno fosse fuori portata.

L'argomentazione Operation era SQL_FETCH_BY_BOOKMARK, e restituire il valore della data o del timestamp per una o più colonne legate avrebbe causato l'uscita del campo anno, mese o giorno fuori portata.
22008 Eccesso di campo data/ora L'argomento dell'operazione era SQL_ADD o SQL_UPDATE_BY_BOOKMARK, e l'esecuzione dell'aritmetica data-time sui dati inviati a una colonna del set di risultati faceva sì che un campo datatime (anno, mese, giorno, ora, minuto o secondo) del risultato uscisse dall'intervallo consentito di valori per il campo o risultasse invalido secondo le regole naturali del calendario gregoriano per le datetime.

L'argomento dell'operazione era SQL_FETCH_BY_BOOKMARK, e l'esecuzione dell'aritmetica data-time sui dati recuperati dal set di risultati faceva sì che un campo datatime (anno, mese, giorno, ora, minuto o secondo) del risultato uscisse dall'intervallo consentito di valori per il campo o risultasse invalido secondo le regole naturali del calendario gregoriano per le datetime.
22015 Overflow del campo intervallo L'argomento Operation era SQL_ADD o SQL_UPDATE_BY_BOOKMARK, e l'assegnazione di un tipo esatto numerico o intervallo C a un tipo di dato SQL a intervallo causava una perdita di cifre significative.

L'argomento dell'Operazione era SQL_ADD o SQL_UPDATE_BY_BOOKMARK; quando si assegnava a un tipo SQL a intervallo, non c'era alcuna rappresentazione del valore del tipo C nel tipo SQL a intervallo.

L'argomento Operazione era SQL_FETCH_BY_BOOKMARK, e assegnare da un tipo SQL numerico o intervallo esatto a un tipo C a intervallo causava una perdita di cifre significative nel campo principale.

L'argomento dell'Operazione era SQL_FETCH_BY_BOOKMARK; quando si assegnava a un intervallo il tipo C, non c'era alcuna rappresentazione del valore del tipo SQL nel tipo intervallo C.
22018 Valore carattere non valido per la specifica del cast L'argomento dell'Operazione era SQL_FETCH_BY_BOOKMARK; il tipo C era un tipo numerico esatto o approssimativo, un data-orario o un tipo di dato a intervallo; il tipo SQL della colonna era un tipo di dato carattere; e il valore nella colonna non era un letterale valido del tipo C limitato.

L'argomentazione Operation era SQL_ADD o SQL_UPDATE_BY_BOOKMARK; il tipo SQL era un tipo numerico esatto o approssimativo, un data-ora o un tipo di dato a intervallo; il tipo C era SQL_C_CHAR; e il valore nella colonna non era un letterale valido del tipo SQL limitato.
23000 Violazione del vincolo di integrità L'argomento dell'Operazione era SQL_ADD, SQL_DELETE_BY_BOOKMARK o SQL_UPDATE_BY_BOOKMARK, e fu violato un vincolo di integrità.

L'argomento Operazione era SQL_ADD, e una colonna non vincolata è definita come NON NULLA e non ha un default (default).

L'argomento Operation era SQL_ADD, la lunghezza specificata nel buffer di StrLen_or_IndPtr limitata era SQL_COLUMN_IGNORE e la colonna non aveva un valore predefinito.
24000 Stato del cursore non valido L'StatementHandle era in uno stato eseguito, ma non era associato alcun set di risultati al 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 poteva bloccare la riga come necessario per eseguire l'operazione richiesta nell'argomento Operazione .
44000 Violazione della clausola WITH CHECK OPTION L'argomento Operation era SQL_ADD o SQL_UPDATE_BY_BOOKMARK, e l'inserimento o aggiornamento veniva eseguito su una tabella vista (o una tabella derivata dalla tabella visualizzata) creata specificando CON CHECK OPTION, in modo che una o più righe interessate dall'inserimento o dall'aggiornamento non fossero 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 veniva 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) L'InstructionHandle specificato non era in uno stato eseguito. La funzione veniva chiamata senza prima chiamare SQLExecDirect, SQLExecute o una funzione catalog.

(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 veniva chiamato per il StatementHandle e restituiva SQL_NEED_DATA. Questa funzione è stata chiamata prima dell'invio dei dati per tutti i parametri o le colonne data-at-execution.

(DM) Il pilota era un ODBC 2. x , e SQLBulkOperations veniva chiamato per un StatementHandle prima che venissero chiamati SQLFetchScroll o SQLFetch .

(DM) SQLBulkOperations veniva chiamato dopo che SQLExtendedFetch veniva chiamato sullo StatementHandle.
HY011 Impossibile impostare l'attributo ora (DM) Il pilota era un ODBC 2. x , e l'attributo SQL_ATTR_ROW_STATUS_PTR statement veniva 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 dell'Operazione era SQL_ADD o SQL_UPDATE_BY_BOOKMARK; un valore di dato non era un puntatore nullo; il tipo di dato C era SQL_C_BINARY o SQL_C_CHAR; e il valore della lunghezza della colonna era inferiore a 0, ma non uguale a SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS o SQL_NULL_DATA, né inferiore o uguale a SQL_LEN_DATA_AT_EXEC_OFFSET.

Il valore in un buffer di lunghezza/indicatore era SQL_DATA_AT_EXEC; il tipo SQL era o SQL_LONGVARCHAR, SQL_LONGVARBINARY o un tipo di dato lungo specifico per la fonte di dati; e il SQL_NEED_LONG_DATA_LEN tipo di informazione in SQLGetInfo era "Y".

L'argomento Operazione era SQL_ADD, l'attributo SQL_ATTR_USE_BOOKMARK dell'istruzione era impostato a SQL_UB_VARIABLE, e la colonna 0 era legata a un buffer la cui lunghezza non era uguale alla lunghezza massima del segnalibro per questo set di risultati. (Questa lunghezza è disponibile nel campo SQL_DESC_OCTET_LENGTH dell'IRD e può essere ottenuta chiamando SQLDescribeCol, SQLColAttribute o SQLGetDescField.)
HY092 Identificatore di attributo non valido (DM) Il valore specificato per l'argomento Operazione era invalido.

L'argomento Operazione era SQL_ADD, SQL_UPDATE_BY_BOOKMARK o SQL_DELETE_BY_BOOKMARK, e l'attributo di affermazione SQL_ATTR_CONCURRENCY era impostato su SQL_CONCUR_READ_ONLY.

L'argomento Operazione era SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK o SQL_UPDATE_BY_BOOKMARK, e la colonna dei segnalibri non era rilegata o l'attributo SQL_ATTR_USE_BOOKMARKS della frazione era 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 la sorgente dati non supporta l'operazione richiesta nell'argomento Operazione .
HYT00 Il timeout è scaduto Periodo di timeout della query scaduto prima che l'origine dati restituisca il set di risultati. Il periodo di timeout è 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.

Comments

Caution

Per informazioni su quali stati di istruzione può essere chiamato SQLBulkOperations e cosa deve fare per la compatibilità con ODBC 2. x applicazioni applicative, vedi la sezione Block Cursors, Scrollable Cursors, and Backward Compatibility nell'Appendice G: Driver Guidelines for Backward Compatibility.

Un'applicazione utilizza SQLBulkOperations per eseguire le seguenti operazioni sulla tabella o vista base che corrisponde alla query corrente:

  • Aggiungere nuove righe.

  • Aggiorna un insieme di righe in cui ogni riga è identificata da un segnalibro.

  • Elimina un insieme di righe in cui ogni riga è identificata da un segnalibro.

  • Prendi un insieme di righe in cui ogni riga è identificata da un segnalibro.

Dopo una chiamata a SQLBulkOperations, la posizione del cursore a blocco non è definita. L'applicazione deve chiamare SQLFetchScroll per impostare la posizione del cursore. Un'applicazione dovrebbe 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 di blocco eseguite tramite una chiamata a SQLBulkOperations impostando il buffer della lunghezza della colonna/indicatore specificato nella chiamata a SQLBindCol su SQL_COLUMN_IGNORE.

Non è necessario che l'applicazione imposti l'attributo SQL_ATTR_ROW_OPERATION_PTR istruzione quando chiama SQLBulkOperations perché le righe non possono essere ignorate quando si esegue operazioni di massa con questa funzione.

Il buffer indicato dall'attributo SQL_ATTR_ROWS_FETCHED_PTR dell'istruzione contiene il numero di righe interessate da una chiamata a SQLBulkOperations.

Quando l'argomento Operation è SQL_ADD o SQL_UPDATE_BY_BOOKMARK e la select-list della specifica di query associata al cursore contiene più di un riferimento 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 maggiori informazioni su come utilizzare SQLBulkOperations, vedi Aggiornamento dati con SQLBulkOperations.

Esecuzione degli inserti in blocco

Per inserire dati con SQLBulkOperations, un'applicazione esegue la seguente sequenza di passaggi:

  1. Esegue una query che restituisce un set di risultati.

  2. Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE al numero di righe che vuole inserire.

  3. Chiama SQLBindCol per associare i dati che vuole inserire. I dati sono legati a un array di dimensione pari al valore di SQL_ATTR_ROW_ARRAY_SIZE.

    Note

    La dimensione dell'array a cui punta l'attributo dell'istruzione SQL_ATTR_ROW_STATUS_PTR dovrebbe essere uguale a SQL_ATTR_ROW_ARRAY_SIZE oppure SQL_ATTR_ROW_STATUS_PTR dovrebbe essere un puntatore nullo.

  4. Chiama SQLBulkOperations(StatementHandle, SQL_ADD) per eseguire l'inserimento.

  5. Se l'applicazione ha impostato l'attributo SQL_ATTR_ROW_STATUS_PTR di unità, può ispezionare questo array per vedere il risultato dell'operazione.

Se un'applicazione lega la colonna 0 prima di chiamare SQLBulkOperations con un argomento Operation di SQL_ADD, il driver aggiornerà i buffer della colonna 0 con i valori dei segnalibri per la riga appena inserita. Perché ciò avvenga, l'applicazione deve aver impostato l'attributo SQL_ATTR_USE_BOOKMARKS istruzione a SQL_UB_VARIABLE prima di eseguire l'istruzione. (Questo non funziona con un ODBC 2. x driver.)

I dati lunghi possono essere aggiunti in parti da SQLBulkOperations, utilizzando chiamate a SQLParamData e SQLPutData. Per ulteriori informazioni, vedi "Fornire dati lunghi per inserimenti e aggiornamenti in massa" più avanti in questo riferimento di funzione.

Non è necessario che l'applicazione chiami SQLFetch o SQLFetchScroll prima di chiamare SQLBulkOperations (tranne quando si confronta con un ODBC 2).X driver; vedi Retrocompatibilità e Conformità agli 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 uno stato SQLSTATE definito dal driver, aggiungere i dati alla prima colonna che appare nel set di risultati, oppure eseguire altri comportamenti definiti dal driver.

Eseguire aggiornamenti in blocco usando segnalibri

Per eseguire aggiornamenti in massa usando segnalibri con SQLBulkOperations, un'applicazione esegue i seguenti passaggi in sequenza:

  1. Imposta l'attributo della SQL_ATTR_USE_BOOKMARKS istruzione a SQL_UB_VARIABLE.

  2. Esegue una query che restituisce un set di risultati.

  3. Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE al numero di righe che vuole aggiornare.

  4. Chiama SQLBindCol per associare i dati che vuole aggiornare. I dati sono legati a un array di dimensione pari al valore di SQL_ATTR_ROW_ARRAY_SIZE. Chiama anche SQLBindCol per associare la colonna 0 (la colonna segnalibro).

  5. Copia i segnalibri delle righe che è interessato ad aggiornare nell'array legato alla colonna 0.

  6. Aggiorna i dati nei buffer vincolati.

    Note

    La dimensione dell'array indicata dall'attributo SQL_ATTR_ROW_STATUS_PTR istruzione dovrebbe essere uguale a SQL_ATTR_ROW_ARRAY_SIZE oppure SQL_ATTR_ROW_STATUS_PTR dovrebbe essere un puntatore nullo.

  7. Chiama SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).

    Note

    Se l'applicazione ha impostato l'attributo SQL_ATTR_ROW_STATUS_PTR di unità, può ispezionare questo array per vedere il risultato dell'operazione.

  8. Opzionalmente chiama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) per recuperare dati nei buffer applicativi vincolati e verificare che l'aggiornamento sia avvenuto.

  9. Se i dati sono stati aggiornati, il driver modifica il valore nell'array di stato delle righe per le righe appropriate da SQL_ROW_UPDATED.

Gli aggiornamenti in blocco eseguiti da SQLBulkOperations possono includere dati lunghi utilizzando chiamate a SQLParamData e SQLPutData. Per ulteriori informazioni, vedi "Fornire dati lunghi per inserimenti e aggiornamenti in massa" più avanti in questo riferimento di funzione.

Se i segnalibri persistono attraverso i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di aggiornare tramite segnalibri. Può usare segnalibri che ha memorizzato da un cursore precedente. Se i segnalibri non persistono 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 uno stato SQLSTATE definito dal driver, aggiornare la prima colonna che appare nel set di risultati o eseguire altri comportamenti definiti dal driver.

Esecuzione di recuperi in massa usando segnalibri

Per eseguire i recuperi in massa usando segnalibri con SQLBulkOperations, un'applicazione esegue i seguenti passaggi in sequenza:

  1. Imposta l'attributo della SQL_ATTR_USE_BOOKMARKS istruzione a SQL_UB_VARIABLE.

  2. Esegue una query che restituisce un set di risultati.

  3. Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE al numero di righe che vuole recuperare.

  4. Chiama SQLBindCol per associare i dati che vuole recuperare. I dati sono legati a un array di dimensione pari al valore di SQL_ATTR_ROW_ARRAY_SIZE. Chiama anche SQLBindCol per associare la colonna 0 (la colonna segnalibro).

  5. Copia i segnalibri delle righe che è interessato a recuperare nell'array legato alla colonna 0. (Questo presuppone che l'applicazione abbia già ottenuto i segnalibri separatamente.)

    Note

    La dimensione dell'array indicata dall'attributo SQL_ATTR_ROW_STATUS_PTR istruzione dovrebbe essere uguale a SQL_ATTR_ROW_ARRAY_SIZE oppure SQL_ATTR_ROW_STATUS_PTR dovrebbe essere un puntatore nullo.

  6. Chiama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).

  7. Se l'applicazione ha impostato l'attributo SQL_ATTR_ROW_STATUS_PTR di unità, può ispezionare questo array per vedere il risultato dell'operazione.

Se i segnalibri persistono tra i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di recuperare tramite segnalibri. Può usare segnalibri che ha memorizzato da un cursore precedente. Se i segnalibri non persistono tra i cursori, l'applicazione deve chiamare SQLFetch o SQLFetchScroll una volta per recuperare i segnalibri.

Eseguire cancellazioni di massa usando segnalibri

Per eseguire cancellazioni di massa usando segnalibri con SQLBulkOperations, un'applicazione esegue i seguenti passaggi in sequenza:

  1. Imposta l'attributo della SQL_ATTR_USE_BOOKMARKS istruzione a SQL_UB_VARIABLE.

  2. Esegue una query che restituisce un set di risultati.

  3. Imposta l'attributo dell'istruzione SQL_ATTR_ROW_ARRAY_SIZE al numero di righe che vuole eliminare.

  4. Chiama SQLBindCol per associare la colonna 0 (la colonna segnalibro).

  5. Copia i segnalibri delle righe che è interessato a eliminare nell'array legato alla colonna 0.

    Note

    La dimensione dell'array indicata dall'attributo SQL_ATTR_ROW_STATUS_PTR istruzione dovrebbe essere uguale a SQL_ATTR_ROW_ARRAY_SIZE oppure SQL_ATTR_ROW_STATUS_PTR dovrebbe essere un puntatore nullo.

  6. Chiama SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).

  7. Se l'applicazione ha impostato l'attributo SQL_ATTR_ROW_STATUS_PTR di unità, può ispezionare questo array per vedere il risultato dell'operazione.

Se i segnalibri persistono attraverso i cursori, l'applicazione non deve chiamare SQLFetch o SQLFetchScroll prima di eliminare tramite segnalibri. Può usare segnalibri che ha memorizzato da un cursore precedente. Se i segnalibri non persistono tra i cursori, l'applicazione deve chiamare SQLFetch o SQLFetchScroll una volta per recuperare i segnalibri.

Fornitura di dati lunghi per inserimenti e aggiornamenti in massa

I dati lunghi possono essere forniti per inserimenti e aggiornamenti in massa effettuati tramite chiamate a SQLBulkOperations. Per inserire o aggiornare dati lunghi, un'applicazione esegue i seguenti passaggi oltre a quelli descritti nelle sezioni "Esecuzione di inserimenti in massa" e "Esecuzione di aggiornamenti in blocco tramite segnalibri" precedentemente in questo argomento.

  1. Quando collega i dati usando SQLBindCol, l'applicazione inserisce un valore definito dall'applicazione, come il numero di colonna, nel buffer *TargetValuePtr per le colonne data-at-execution. Il valore può essere usato successivamente per identificare la colonna.

    L'applicazione colloca il risultato della macro SQL_LEN_DATA_AT_EXEC(length) nel buffer *StrLen_or_IndPtr . Se il tipo di dato SQL della colonna è SQL_LONGVARBINARY, SQL_LONGVARCHAR o un tipo di dato lungo specifico della sorgente dati e il driver restituisce "Y" per il tipo di informazione SQL_NEED_LONG_DATA_LEN in SQLGetInfo, la lunghezza è il numero di byte di dati da inviare per il parametro; altrimenti, deve essere un valore non negativo e viene ignorato.

  2. Quando viene chiamato SQLBulkOperations , se ci sono colonne data-at-execution, la funzione restituisce SQL_NEED_DATA e procede al passo 3, che segue di conseguenza. (Se non ci sono colonne data-at-execution, il processo è completo.)

  3. 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 .

    Note

    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 le quali 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 che viene elaborata.

  4. L'applicazione chiama SQLPutData una o più volte per inviare dati alla colonna. È necessaria più di una chiamata se non tutti i valori dati possono essere restituiti nel buffer *TargetValuePtr specificato in SQLPutData; chiamate multiple a SQLPutData per la stessa colonna sono consentite solo quando si inviano dati di carattere C a una colonna con un tipo di dato specifico di carattere, binario o sorgente di dati, oppure quando si inviano dati binari C a una colonna con un tipo di dato specifico di carattere, binario o sorgente di dati.

  5. L'applicazione richiama nuovamente SQLParamData per segnalare che tutti i dati sono stati inviati per la colonna.

    • Se ci sono più colonne data-at-execution, SQLParamData restituisce SQL_NEED_DATA e l'indirizzo del buffer TargetValuePtr per la colonna data-at-execution successiva da elaborare. L'applicazione ripete i passaggi 4 e 5.

    • Se non ci sono più colonne data-at-execution, il processo è completo. Se l'istruzione è stata eseguita con successo, SQLParamData restituisce SQL_SUCCESS o SQL_SUCCESS_WITH_INFO; se l'esecuzione è fallita, restituisce SQL_ERROR. A questo punto, SQLParamData può restituire qualsiasi stato SQLBulkOperations possa restituire.

Se l'operazione viene annullata o si verifica un errore in SQLParamData o SQLPutData dopo che SQLBulkOperations ha restituito SQL_NEED_DATA e prima che i dati vengano inviati per tutte le colonne data-at-execution, 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 (Function sequence error).

Se l'applicazione chiama SQLCancel mentre il driver ha ancora bisogno di dati per le colonne data-at-execution, il driver annulla l'operazione. L'applicazione può quindi richiamare SQLBulkOperations ; la cancellazione non influisce sullo stato del cursore né sulla posizione attuale del cursore.

Matrice di stato riga

L'array di stato delle righe contiene i 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 questo array dopo una chiamata a SQLFetch, SQLFetchScroll, SQLSetPos o SQLBulkOperations. Questo array viene inizialmente popolato tramite una chiamata a SQLBulkOperations se SQLFetch o SQLFetchScroll non sono stati chiamati prima di SQLBulkOperations. Questo array è indicato dall'attributo SQL_ATTR_ROW_STATUS_PTR sentenza. Il numero di elementi negli array di stato delle righe deve essere uguale al numero di righe nell'insieme di righe (come definito dall'attributo SQL_ATTR_ROW_ARRAY_SIZE sentenza). Per informazioni su questo array di stato delle righe, vedi SQLFetch.

Esempio di codice

Il seguente esempio ottiene 10 righe di dati alla volta dalla tabella Clienti. Successivamente viene invitato l'utente a compiere un'azione. Per ridurre il traffico di rete, il buffer di esempio aggiorna, elimina e inserisce localmente negli array legati, ma a offset oltre i dati del rowset. Quando l'utente sceglie di inviare aggiornamenti, cancellazioni e inserimenti alla sorgente dati, il codice imposta correttamente l'offset di binding e chiama SQLBulkOperations. Per semplicità, l'utente non può buffer più di 10 aggiornamenti, cancellazioni o inserti.

// 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);  
}  
Per informazioni su Vedi
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
Ottenere un singolo campo di un descrittore Funzione SQLGetDescField
Ottenere più campi di un descrittore Funzione SQLGetDescRec
Impostare un singolo campo di un descrittore Funzione SQLSetDescField
Impostare più campi di un descrittore Funzione SQLSetDescRec
Posizionamento del cursore, aggiornamento dei dati nel rowset o aggiornamento o cancellazione dei dati nel rowset Funzione SQLSetPos
Impostazione di un attributo di istruzione Funzione SQLSetStmtAttr