取得長型數據

DBMS 將 長資料 定義為任何字元或二進位資料,大小超過一定大小,例如 255 個字元。 這些資料可能小到可以儲存在單一緩衝區,例如數千字元的零件描述。 然而,儲存在記憶體中可能過長,例如長篇文字文件或位圖。 由於此類資料無法儲存在單一緩衝區,因此在擷取該列其他資料後,會以 SQLGetData 分段從驅動程式中擷取。

備註

應用程式實際上可以用 SQLGetData 擷取任何類型的資料,不僅限於長資料,雖然只能部分檢索字元和二進位資料。 然而,如果資料足夠小,能放入單一緩衝區,通常沒有必要使用 SQLGetData。 將緩衝區綁定到欄位,讓驅動程式回傳緩衝區資料會簡單得多。

要從欄位擷取長資料,應用程式首先呼叫 SQLFetchScrollSQLFetch 移動到某一列並取得綁定欄位的資料。 應用程式接著呼叫 SQLGetDataSQLGetDataSQLBindCol 有相同的參數:一個語句 handle;欄位編號;應用變數的 C 資料型態、位址與位元組長度;以及長度/指示緩衝區的位址。 兩個函式的參數相同,因為它們執行的任務本質相同:它們都向驅動程式描述應用程式變數,並指定特定欄位的資料應以該變數回傳。 主要差異在於 SQLGetData 是在擷取資料列後呼叫(因此有時稱為 延遲綁定 ),且 SQLGetData 指定的綁定僅持續整個呼叫期間。

關於單一欄位, SQLGetData 的行為類似 SQLFetch:它取得該欄位的資料,將其轉換成應用程式變數的型別,並以該變數回傳資料。 它也會回傳長度/指示緩衝區中資料的位元組長度。 欲了解更多關於 SQLFetch 如何回傳資料的資訊,請參閱 「取得資料列」。

SQLGetDataSQLFetch 在一個重要方面有所不同。 若同一欄位連續多次呼叫,每次呼叫會回傳資料的連續部分。 除了最後一次呼叫外,每個呼叫都會回傳 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 欄是錯誤。 因此,應用程式應確保在選取清單的末尾放置較長的資料欄位。

  • 若呼叫 SQLFetchSQLFetchScroll 以取得多於一列,則無法使用。 更多資訊請參見 使用區塊游標

有些駕駛人並未執行這些限制。 互通應用程式應假設其存在,或透過呼叫 SQLGetInfo 並啟用 SQL_GETDATA_EXTENSIONS 選項來判斷哪些限制未被強制執行。

如果應用程式不需要字元或二進位資料欄位中的所有資料,可以在基於資料庫管理系統的驅動程式中,透過在執行語句前設定 SQL_ATTR_MAX_LENGTH 陳述式屬性來減少網路流量。 這限制了任何字元或二進位欄位可回傳的資料位元組數。 例如,假設一欄包含長篇文字文件。 瀏覽包含此欄位的表格的應用程式可能只需顯示每份文件的第一頁。 雖然這個陳述屬性可以在驅動程式中模擬,但其實沒有必要這麼做。 特別是,如果應用程式想要截斷字元或二進位資料,應該用 SQLBindCol 綁定一個小緩衝區到欄位,並讓驅動程式自行截斷資料。