提取結果資料
ODBC 應用程式具備三個提取結果資料的選項。
第一個選項是以 SQLBindCol 為基礎。提取結果集前,應用程式會使用 SQLBindCol,將結果集中的每個資料行繫結到程式變數。繫結資料行之後,每次應用程式呼叫 SQLFetch 或 SQLFetchScroll 時,驅動程式會將目前資料列的資料轉換為繫結到結果集資料行的變數。如果結果集資料行和程式變數的資料類型不同,驅動程式會處理資料轉換。如果應用程式將 SQL_ATTR_ROW_ARRAY_SIZE 設定為大於 1,它可以將結果資料行繫結至變數陣列,這將會針對 SQLFetchScroll 的每個呼叫填滿。
第二個選項是以 SQLGetData 為基礎。應用程式不會使用 SQLBindCol 將結果集資料行繫結至程式變數。每次呼叫 SQLFetch 之後,應用程式會針對結果集中的每個資料行呼叫 SQLGetData 一次。SQLGetData 會指示驅動程式將資料從特定的結果集資料行轉換為特定的程式變數,並指定資料行和變數的資料類型。如果結果資料行和程式變數的資料類型不同,這會讓驅動程式轉換資料。Text、ntext 和 image 資料行通常太大,而無法容納到程式變數,但是仍然可以使用 SQLGetData 來擷取。如果結果資料行中的 text、ntext 或 image 資料大於程式變數,SQLGetData 會傳回 SQL_SUCCESS_WITH_INFO 和 SQLSTATE 01004 (右側截斷的字串資料)。連續呼叫 SQLGetData 會傳回 text 或 image 資料的連續區塊。到達資料的結尾時,SQLGetData 會傳回 SQL_SUCCESS。如果 SQL_ATTR_ROW_ARRAY_SIZE 大於 1,每次提取都會傳回一組資料列或資料列集。使用 SQLGetData 前,您必須先使用 SQLSetPos 來指定資料列集中的特定資料列,做為目前的資料列。
第三個選項為混用 SQLBindCol 和 SQLGetData。例如,應用程式可以繫結結果集的前 10 個資料行,然後在每次提取時,呼叫 SQLGetData 三次來擷取三個未繫結資料行中的資料。當結果集包含一或多個 text 或 image 資料行時,通常會使用這個方式。
根據針對結果集設定的資料指標選項,應用程式也可以使用 SQLFetchScroll 的捲動選項來捲動結果集。
過度使用 SQLBindCol 將結果集資料行繫結至程式變數相當費時,因為 SQLBindCol 會使 ODBC 驅動程式配置記憶體。當您將結果資料行繫結至變數時,該繫結仍會保持作用中,直到您呼叫 SQLFreeHandle 來釋放陳述式控制代碼,或在 fOption 設定為 SQL_UNBIND 時呼叫 SQLFreeStmt。當陳述式完成時,不會自動復原繫結。
此邏輯可讓您利用不同的參數,有效地處理執行相同的 SELECT 陳述式數次。結果集會保留相同的結構,因此,您可以繫結結果集一次、處理所有 SELECT 陳述式,然後在最後一次執行後,將 fOption 設定為 SQL_UNBIND 的情況下,呼叫 SQLFreeStmt。如果沒有在 fOption 設定為 SQL_UNBIND 來釋放先前所有繫結的情況下先呼叫 SQLFreeStmt,您不應該呼叫 SQLBindCol 來繫結結果集中的資料行。
使用 SQLBindCol 時,您可以進行資料列取向或資料行取向的繫結。資料列取向的繫結比資料行取向的繫結稍快。
您可以使用 SQLGetData 逐資料行擷取資料,而非使用 SQLBindCol 繫結結果集資料行。如果結果集僅包含少數資料列,使用 SQLGetData (而非 SQLBindCol) 較快,否則SQLBindCol 會提供最佳的效能。如果您不想永遠將資料放在相同一組變數中,您應該使用 SQLGetData 而非不斷重新繫結。使用 SQLBindCol 繫結所有資料行之後,您僅能在選取清單中的資料行上使用 SQLGetData。此資料行也必須出現在您已經使用 SQLGetData 的任何資料行後面。
處理將資料移入或移出程式變數的 ODBC 函數 (例如,SQLGetData、SQLBindCol 和 SQLBindParameter) 支援隱含的資料類型轉換。例如,如果應用程式將整數資料行繫結至字元字串程式變數,驅動程式會先自動將資料從整數轉換為字元,然後再將其放入程式變數中。
在應用程式中進行的資料轉換應該降至最低。出非需要進行資料轉換才能讓應用程式完成處理,否則,應用程式應該將資料行和參數繫結至相同資料類型的程式變數。不過,如果資料必須從一種類型轉換為另一種類型,讓驅動程式執行轉換比在應用程式中進行轉換還要有效率。SQL Server Native Client ODBC 驅動程式一般只會直接將資料從網路緩衝區轉換到應用程式的變數。要求驅動程式執行資料轉換會強制驅動程式緩衝處理資料,並使用 CPU 循環轉換資料。
程式變數必須夠大,才能容納從資料行傳入的資料 (除了 text、ntext 和 image 資料之外)。如果應用程式嘗試擷取結果集資料,並將其放入太小而無法容納它的變數中,驅動程式會產生警告。這會強迫驅動程式為訊息配置記憶體,而且驅動程式和應用程式都必須花費 CPU 循環來處理訊息並進行錯誤處理。應用程式應該配置夠大的變數來容納要擷取的資料,或使用選取清單中的 SUBSTRING 函數來縮減資料行在結果集中的大小。
使用 SQL_C_DEFAULT 來指定 C 變數的類型時請務必小心。SQL_C_DEFAULT 指定 C 變數的類型必須符合資料行或參數的 SQL 資料類型。如果針對 ntext、nchar 或 nvarchar 資料行指定 SQL_C_DEFAULT,則會將 Unicode 資料傳回到應用程式。如果尚未撰寫應用程式的程式碼來處理 Unicode 資料,這可能會導致各種問題。uniqueidentifier (SQL_GUID) 資料類型可能會發生相同類型的問題。
text、ntext 和 image 資料通常太大,而無法容納到單一程式變數,但是通常會以 SQLGetData 而非 SQLBindCol 來處理。使用伺服器資料指標時,SQL Server Native Client ODBC 驅動程式會經過最佳化,不會在提取資料列時傳送未繫結之 text、ntext 或 image 資料行的資料。在應用程式針對資料行發出 SQLGetData 前,不會從伺服器實際擷取 text、ntext 或 image 資料。
此最佳化可以套用到應用程式,因此在使用者上下捲動資料指標時,不會顯示 text、ntext 或 image 資料。使用者選取資料列之後,應用程式可以呼叫 SQLGetData 來擷取 text、ntext 或 image 資料。這樣就不用傳送使用者沒有選取之任何資料列的 text、ntext 或 image 資料,也不用傳送非常大量的資料。