Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I DBMS definiscono dati lunghi come dati di tipo carattere o binari su una determinata dimensione, ad esempio 255 caratteri. Questi dati possono essere sufficientemente piccoli da archiviare in un singolo buffer, ad esempio una descrizione di diverse migliaia di caratteri. Tuttavia, potrebbe essere troppo lungo per essere archiviato in memoria, come documenti di testo lunghi o bitmap. Poiché tali dati non possono essere archiviati in un singolo buffer, vengono recuperati dal driver in parti con SQLGetData dopo il recupero degli altri dati nella riga.
Annotazioni
Un'applicazione può effettivamente recuperare qualsiasi tipo di dati con SQLGetData, non solo dati lunghi, anche se solo i dati di tipo carattere e binario possono essere recuperati in parti. Tuttavia, se i dati sono sufficientemente piccoli da adattarsi a un singolo buffer, in genere non esiste alcun motivo per usare SQLGetData. È molto più semplice associare un buffer alla colonna e consentire al driver di restituire i dati nel buffer.
Per recuperare dati lunghi da una colonna, un'applicazione chiama prima SQLFetchScroll o SQLFetch per passare a una riga e recuperare i dati per le colonne associate. L'applicazione chiama quindi SQLGetData. SQLGetData ha gli stessi argomenti di SQLBindCol: un handle di dichiarazione; un numero di colonna; il tipo di dati C; l'indirizzo e la lunghezza in byte di una variabile dell'applicazione; e l'indirizzo di un buffer di lunghezza/indicatore. Entrambe le funzioni hanno gli stessi argomenti perché eseguono essenzialmente la stessa attività: descrivono entrambe una variabile dell'applicazione al driver e specificano che i dati per una determinata colonna devono essere restituiti in tale variabile. Le differenze principali sono che SQLGetData viene chiamato dopo il recupero di una riga (e talvolta definito associazione tardiva per questo motivo) e che l'associazione specificata da SQLGetData dura solo per la durata della chiamata.
Per quanto riguarda una singola colonna, SQLGetData si comporta come SQLFetch: recupera i dati per la colonna, lo converte nel tipo della variabile dell'applicazione e lo restituisce in tale variabile. Restituisce anche la lunghezza dei byte dei dati nel buffer di lunghezza/indicatore. Per altre informazioni su come SQLFetch restituisce i dati, vedere Recupero di una riga di dati.
SQLGetData differisce da SQLFetch in un aspetto importante. Se viene chiamato più volte in successione per la stessa colonna, ogni chiamata restituisce una parte successiva dei dati. Ogni chiamata tranne l'ultima chiamata restituisce SQL_SUCCESS_WITH_INFO e SQLSTATE 01004 (dati stringa, troncati a destra); l'ultima chiamata restituisce SQL_SUCCESS. Questo è il modo in cui SQLGetData viene usato per recuperare dati lunghi in parti. Quando non sono presenti altri dati da restituire, SQLGetData restituisce SQL_NO_DATA. L'applicazione è responsabile dell'inserimento dei dati lunghi, che potrebbe significare concatenare le parti dei dati. Ogni parte è terminata da un carattere null. L'applicazione deve rimuovere il carattere di terminazione null se si concatenano le parti tra loro. Il recupero dei dati in parti può essere eseguito per segnalibri a lunghezza variabile e per altri dati lunghi. Il valore restituito nel buffer di lunghezza/indicatore diminuisce in ogni chiamata in base al numero di byte restituiti nella chiamata precedente, anche se è comune che il driver non sia in grado di individuare la quantità di dati disponibili e restituire una lunghezza di byte di SQL_NO_TOTAL. Per esempio:
// Declare a binary buffer to retrieve 5000 bytes of data at a time.
SQLCHAR BinaryPtr[5000];
SQLUINTEGER PartID;
SQLINTEGER PartIDInd, BinaryLenOrInd, NumBytes;
SQLRETURN rc;
SQLHSTMT hstmt;
// Create a result set containing the ID and picture of each part.
SQLExecDirect(hstmt, "SELECT PartID, Picture FROM Pictures", SQL_NTS);
// Bind PartID to the PartID column.
SQLBindCol(hstmt, 1, SQL_C_ULONG, &PartID, 0, &PartIDInd);
// Retrieve and display each row of data.
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {
// Display the part ID and initialize the picture.
DisplayID(PartID, PartIDInd);
InitPicture();
// Retrieve the picture data in parts. Send each part and the number
// of bytes in each part to a function that displays it. The number
// of bytes is always 5000 if there were more than 5000 bytes
// available to return (cbBinaryBuffer > 5000). Code to check if
// rc equals SQL_ERROR or SQL_SUCCESS_WITH_INFO not shown.
while ((rc = SQLGetData(hstmt, 2, SQL_C_BINARY, BinaryPtr, sizeof(BinaryPtr),
&BinaryLenOrInd)) != SQL_NO_DATA) {
NumBytes = (BinaryLenOrInd > 5000) || (BinaryLenOrInd == SQL_NO_TOTAL) ?
5000 : BinaryLenOrInd;
DisplayNextPictPart(BinaryPtr, NumBytes);
}
}
// Close the cursor.
SQLCloseCursor(hstmt);
Esistono diverse restrizioni sull'uso di SQLGetData. In genere, le colonne a cui si accede con SQLGetData:
È necessario accedere in ordine di numero di colonna crescente a causa del modo in cui le colonne di un insieme di risultati vengono lette dall'origine dati. Ad esempio, è un errore chiamare SQLGetData per la colonna 5 e poi chiamarli per la colonna 4.
Non può essere associato.
Deve avere un numero di colonna superiore all'ultima colonna vincolata. Ad esempio, se l'ultima colonna associata è la colonna 3, si tratta di un errore per chiamare SQLGetData per la colonna 2. Per questo motivo, le applicazioni devono assicurarsi di inserire colonne di dati lunghe alla fine dell'elenco di selezione.
Non può essere usato se è stato chiamato SQLFetch o SQLFetchScroll per recuperare più righe. Per altre informazioni, vedere Uso dei cursori a blocchi.
Alcuni driver non applicano queste restrizioni. Le applicazioni interoperabili devono presupporre che esistano o determinare quali restrizioni non vengono applicate chiamando SQLGetInfo con l'opzione SQL_GETDATA_EXTENSIONS.
Se l'applicazione non necessita di tutti i dati in una colonna di dati di tipo carattere o binario, può ridurre il traffico di rete nei driver basati su DBMS impostando l'attributo dell'istruzione SQL_ATTR_MAX_LENGTH prima di eseguire l'istruzione. In questo modo viene limitato il numero di byte di dati che verranno restituiti per qualsiasi colonna di tipo carattere o binario. Si supponga, ad esempio, che una colonna contenga documenti di testo lunghi. Un'applicazione che esplora la tabella contenente questa colonna potrebbe dover visualizzare solo la prima pagina di ogni documento. Anche se questo attributo di dichiarazione può essere simulato nel driver, non vi è alcun motivo per farlo. In particolare, se un'applicazione vuole troncare i dati di tipo carattere o binario, deve associare un buffer di piccole dimensioni alla colonna con SQLBindCol e consentire al driver di troncare i dati.