Ottenere dati Long
I DBMS definiscono come dati Long qualsiasi carattere o dato binario che supera una determinata dimensione, per esempio 255 caratteri. Questi dati possono essere sufficientemente piccoli da essere archiviati in un singolo buffer, come per esempio una descrizione di diverse migliaia di caratteri. Tuttavia, potrebbe essere troppo lungo per essere archiviato nella memoria, come per esempio lunghi documenti di testo o bitmap. Poiché tali dati non possono essere archiviati in un singolo buffer, vengono recuperati in parti dal driver con SQLGetData successivamente al recupero degli altri dati nella riga.
Nota
Un'applicazione può recuperare qualsiasi tipo di dati con SQLGetData, non solo dati Long, anche se solo i dati di tipo carattere e binario possono essere recuperati in parti. Tuttavia, se i dati sono sufficientemente piccoli da essere archiviati in un singolo buffer, in genere non vi è motivo di usare SQLGetData. È molto più semplice associare un buffer alla colonna e consentire al driver di restituire i dati nel buffer.
Per recuperare dati Long da una colonna, per prima cosa un'applicazione chiama SQLFetchScroll o SQLFetch per passare a una riga e recuperare i dati per le colonne associate. Dopodiché, l'applicazione chiama SQLGetData. SQLGetData ha gli stessi argomenti di SQLBindCol: un handle di istruzione, un numero di colonna, i dati di tipo C, l'indirizzo e la lunghezza di byte di una variabile dell'applicazione, nonché l'indirizzo di un buffer di lunghezza/indicatore. Entrambe le funzioni hanno gli stessi argomenti perché in pratica eseguono la stessa attività: entrambe descrivono 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 (per questo motivo, a volte viene definito come associazione tardiva) e che l'associazione specificata da SQLGetData dura solamente il tempo della chiamata.
Per quanto riguarda una singola colonna, SQLGetData si comporta come SQLFetch: recupera i dati per la colonna, li converte nel tipo della variabile dell'applicazione e li restituisce in tale variabile. Restituisce anche la lunghezza dei byte dei dati nel buffer di lunghezza/indicatore. Per ulteriori 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, a eccezione dell'ultima, 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 Long in parti. Quando non sono presenti altri dati da restituire, SQLGetData restituisce SQL_NO_DATA. L'applicazione è responsabile dell'unione dei dati Long, che potrebbe concatenare le parti dei dati. Ogni parte è con terminazione Null; l'applicazione deve rimuovere il carattere di terminazione Null se si concatenano le parti. Il recupero dei dati in parti può essere eseguito per segnalibri a lunghezza variabile e per altri dati Long. Il valore restituito nel buffer di lunghezza/indicatore diminuisce in ogni chiamata in base al numero di byte restituiti nella chiamata precedente, anche se in genere il driver non è 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:
Devono essere chiamate in ordine crescente rispetto al numero di colonna (a causa del modo in cui le colonne di un set di risultati vengono lette dall'origine dati). Per esempio, chiamare SQLGetData prima per la colonna 5 e poi per la colonna 4 è un errore.
Non possono essere associate.
Devono avere un numero di colonna superiore all'ultima colonna associata. Per esempio, se l'ultima colonna associata è la colonna 3, chiamare SQLGetData per la colonna 2 è un errore. Per questo motivo, le applicazioni devono assicurarsi di inserire colonne di dati Long alla fine dell'elenco di selezione.
Non possono essere usate se sono stati chiamati SQLFetch o SQLFetchScroll per recuperare più righe. Per ulteriori informazioni, vedere Uso del cursore rettangolare.
Alcuni driver non applicano queste restrizioni. Le applicazioni interoperabili devono presupporre che esistano delle restrizioni o determinare quali 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 si limita il numero di byte di dati che verranno restituiti per qualsiasi colonna di tipo carattere o binario. Si supponga, per esempio, che una colonna contenga lunghi documenti di testo. Un'applicazione che esplora la tabella contenente questa colonna potrebbe dover visualizzare solo la prima pagina di ogni documento. Anche se questo attributo di istruzione 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 usare SQLBindCol per associare un buffer di piccole dimensioni alla colonna e consentire al driver di troncare i dati.