DBMS 將 長資料 定義為任何字元或二進位資料,大小超過一定大小,例如 255 個字元。 這些資料可能小到可以儲存在單一緩衝區,例如數千字元的零件描述。 然而,儲存在記憶體中可能過長,例如長篇文字文件或位圖。 由於此類資料無法儲存在單一緩衝區,因此在擷取該列其他資料後,會以 SQLGetData 分段從驅動程式中擷取。
備註
應用程式實際上可以用 SQLGetData 擷取任何類型的資料,不僅限於長資料,雖然只能部分檢索字元和二進位資料。 然而,如果資料足夠小,能放入單一緩衝區,通常沒有必要使用 SQLGetData。 將緩衝區綁定到欄位,讓驅動程式回傳緩衝區資料會簡單得多。
要從欄位擷取長資料,應用程式首先呼叫 SQLFetchScroll 或 SQLFetch 移動到某一列並取得綁定欄位的資料。 應用程式接著呼叫 SQLGetData。 SQLGetData 與 SQLBindCol 有相同的參數:一個語句 handle;欄位編號;應用變數的 C 資料型態、位址與位元組長度;以及長度/指示緩衝區的位址。 兩個函式的參數相同,因為它們執行的任務本質相同:它們都向驅動程式描述應用程式變數,並指定特定欄位的資料應以該變數回傳。 主要差異在於 SQLGetData 是在擷取資料列後呼叫(因此有時稱為 延遲綁定 ),且 SQLGetData 指定的綁定僅持續整個呼叫期間。
關於單一欄位, SQLGetData 的行為類似 SQLFetch:它取得該欄位的資料,將其轉換成應用程式變數的型別,並以該變數回傳資料。 它也會回傳長度/指示緩衝區中資料的位元組長度。 欲了解更多關於 SQLFetch 如何回傳資料的資訊,請參閱 「取得資料列」。
SQLGetData 與 SQLFetch 在一個重要方面有所不同。 若同一欄位連續多次呼叫,每次呼叫會回傳資料的連續部分。 除了最後一次呼叫外,每個呼叫都會回傳 SQL_SUCCESS_WITH_INFO 和 SQLSTATE 01004(字串資料,經過截斷);最後一次呼叫會回傳 SQL_SUCCESS。 這就是 SQLGetData 用來分段擷取長資料的方式。 當沒有資料可回傳時, SQLGetData 會回傳 SQL_NO_DATA。 應用程式負責將長資料組合起來,這可能意味著將資料的各個部分串接起來。 每個元件皆為零終端;若將元件串接,應用程式必須移除空終止特性。 可分段檢索資料,適用於可變長度書籤或其他長資料。 長度/指示緩衝區中回傳的值會依前一次呼叫回傳的位元組數減少,儘管驅動程式常無法發現可用資料量,無法回傳SQL_NO_TOTAL的位元組長度。 例如:
// 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);
使用 SQLGetData 有幾項限制。 一般而言,使用 SQLGetData 存取的欄位:
必須依欄位數遞增順序存取(因為結果集欄位從資料來源讀取的方式不同)。 例如,先呼叫 SQLGetData 處理第 5 欄,再呼叫第 4 欄,會是錯誤。
無法綁定。
欄位編號必須高於上一欄的綁定欄位。 例如,如果最後綁定的欄位是第 3 欄,呼叫 SQLGetData 取得第 2 欄是錯誤。 因此,應用程式應確保在選取清單的末尾放置較長的資料欄位。
若呼叫 SQLFetch 或 SQLFetchScroll 以取得多於一列,則無法使用。 更多資訊請參見 使用區塊游標。
有些駕駛人並未執行這些限制。 互通應用程式應假設其存在,或透過呼叫 SQLGetInfo 並啟用 SQL_GETDATA_EXTENSIONS 選項來判斷哪些限制未被強制執行。
如果應用程式不需要字元或二進位資料欄位中的所有資料,可以在基於資料庫管理系統的驅動程式中,透過在執行語句前設定 SQL_ATTR_MAX_LENGTH 陳述式屬性來減少網路流量。 這限制了任何字元或二進位欄位可回傳的資料位元組數。 例如,假設一欄包含長篇文字文件。 瀏覽包含此欄位的表格的應用程式可能只需顯示每份文件的第一頁。 雖然這個陳述屬性可以在驅動程式中模擬,但其實沒有必要這麼做。 特別是,如果應用程式想要截斷字元或二進位資料,應該用 SQLBindCol 綁定一個小緩衝區到欄位,並讓驅動程式自行截斷資料。