使用 ODBC 資料表值參數
適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Platform System (PDW)
本主題討論搭配 ODBC 使用資料表值參數的主要使用者案例:
具有完整係結多重瀏覽緩衝區的數據表值參數(以具有記憶體中所有值的 TVP 傳送資料)
具有資料列串串流的資料表值參數(使用資料執行時以TVP傳送資料)
從系統目錄擷取數據表值參數元數據
擷取備妥語句的數據表值參數元數據
具有完整係結多重瀏覽緩衝區的數據表值參數(以具有記憶體中所有值的 TVP 傳送資料)
搭配完整系結多重流覽緩衝區使用時,所有參數值都可在記憶體中使用。 例如,這是 OLTP 交易的一般情況,其中數據表值參數可以封裝成單一預存程式。 如果沒有數據表值參數,這牽涉到動態產生複雜的多語句批次,或對伺服器進行多個呼叫。
數據表值參數本身會使用 SQLBindParameter 與其他參數係結。 系結所有參數之後,應用程式會在每個數據表值參數上設定參數焦點屬性SQL_SOPT_SS_PARAM_FOCUS,並針對數據表值參數的數據行呼叫 SQLBindParameter。
數據表值參數的伺服器類型是新的 SQL Server 特定類型,SQL_SS_TABLE。 SQL_SS_TABLE的系結 C 類型一律必須SQL_C_DEFAULT。 數據表值參數係結參數不會傳輸任何數據;它用來傳遞數據表元數據,並控制如何在數據表值參數的組成數據行中傳遞數據。
數據表值參數的長度會設定為傳送至伺服器的數據列數目。 數據表值參數之 SQLBindParameter 的 ColumnSize 參數會指定可以傳送的數據列數目上限;這是數據行緩衝區的數位大小。 ParameterValuePtr 是參數緩衝區;對於 SQLBindParameter 中的數據表值參數, ParameterValuePtr 及其相關聯的 BufferLength 會在必要時用來傳遞數據表值參數的類型名稱。 預存過程調用不需要類型名稱,但 SQL 語句則不需要此名稱。
呼叫 SQLBindParameter 時指定資料表值參數類型名稱時,它一律必須指定為 Unicode 值,即使在建置為 ANSI 應用程式的應用程式中也是如此。 當您使用 SQLSetDescField 指定資料表值參數類型名稱時,可以使用符合應用程式建置方式的常值。 ODBC 驅動程式管理員會執行任何必要的 Unicode 轉換。
您可以使用 SQLGetDescRec、SQLSetDescRec、SQLGetDescRec、SQLGetDescField 和 SQLSetDescField,個別和明確操作數據表值參數數據行的元數據。 不過,在大部分情況下,多載 SQLBindParameter 通常比較方便,而且不需要明確描述元存取。 此方法與其他數據類型的 SQLBindParameter 定義一致,不同之處在於數據表值參數受影響的描述元欄位稍有不同。
有時候,應用程式會使用具有動態 SQL 的數據表值參數,而且必須提供資料表值參數的類型名稱。 如果是這種情況,而且數據表值參數未定義於連線的目前預設架構中,則必須使用 SQLSetDescField 來設定SQL_CA_SS_SCHEMA_NAME。 因為數據表類型定義和數據表值參數必須位於相同的資料庫中,因此如果應用程式使用數據表值參數,則SQL_CA_SS_CATALOG_NAME不得設定。 否則,SQLSetDescField 會報告錯誤。
此案例的範例程式代碼位於使用數據表值參數 (ODBC) 中的程式中demo_fixed_TVP_binding
。
具有資料列串串流的資料表值參數(使用資料執行時以TVP傳送資料)
在此案例中,應用程式會在要求數據列時,提供給驅動程序的數據列,並將其串流處理至伺服器。 這可避免在記憶體中緩衝所有數據列。 這是大量插入/更新案例的代表。 數據表值參數提供參數數位與大量複製之間某處的效能點。 也就是說,數據表值參數與參數數位一樣容易進行程序設計,但它們在伺服器上提供更大的彈性。
數據表值參數及其數據行會系結,如上一節所述,數據表值參數與完整系結 Multirow 緩衝區,但數據表值參數本身的長度指標會設定為SQL_DATA_AT_EXEC。 驅動程式會藉由傳回SQL_NEED_DATA,以一般方式回應 SQLExecute 或 SQLExecuteDirect 的數據執行參數。 當驅動程式準備好接受數據表值參數的數據時,SQLParamData 會傳回 SQLBindParameter 中 ParameterValuePtr 的值。
應用程式會針對數據表值參數使用 SQLPutData 來指出數據表值參數組成數據行的數據可用性。 針對數據表值參數呼叫 SQLPutData 時,DataPtr 一律為 null,且StrLen_or_Ind必須小於或等於數據表值參數緩衝區所指定的數位大小(SQLBindParameter 的 ColumnSize 參數)。 0 表示數據表值參數沒有其他數據列,而且驅動程式會繼續處理下一個實際程序參數。 當StrLen_or_Ind不是 0 時,驅動程式會以與非數據表值參數係結參數相同的方式處理資料表值參數組成數據行:每個數據表值參數數據行都可以指定其實際數據長度,SQL_NULL_DATA,也可以透過長度/指標緩衝區指定執行中的數據。 數據表值參數數據行值可以在字元或二進位值傳入片段時,重複呼叫 SQLPutData 來傳遞。
處理所有數據表值參數數據行時,驅動程式會返回數據表值參數,以處理數據表值參數數據的進一步數據列。 因此,針對執行中數據表值參數的數據,驅動程式不會遵循係結參數的一般循序掃描。 系結數據表值參數將會輪詢,直到呼叫 SQLPutData 且 StrLen_Or_IndPtr等於 0 為止,此時驅動程式會略過數據表值參數數據行,並移至下一個實際的預存程式參數。 當 SQLPutData 傳遞大於或等於 1 的指標值時,驅動程式會循序處理數據表值參數數據行和數據列,直到其具有所有系結數據列和數據行的值為止。 然後驅動程式會返回數據表值參數。 從 SQLParamData 接收資料表值參數的令牌,以及呼叫數據表值參數的 SQLPutData(hstmt、NULL、n)之間,應用程式必須設定數據表值參數組成數據行數據和指標緩衝區內容,才能將下一個數據列或數據列傳遞至伺服器。
此案例的範例程式代碼位於使用數據表值參數 (ODBC) 中的例程demo_variable_TVP_binding
。
從系統目錄擷取數據表值參數元數據
當應用程式呼叫具有數據表值參數之程式的 SQLProcedureColumns 時,DATA_TYPE會傳回為 SQL_SS_TABLE,TYPE_NAME是數據表值參數的數據表類型名稱。 SQLProcedureColumns 傳回的結果集會新增兩個額外的數據行:SS_TYPE_CATALOG_NAME傳回定義 table-value 參數之數據表類型的目錄名稱,SS_TYPE_SCHEMA_NAME傳回定義 table-value 參數之數據表類型所在之架構的名稱。 與 ODBC 規格一致,SS_TYPE_CATALOG_NAME和SS_TYPE_SCHEMA_NAME會出現在舊版 SQL Server 中新增的所有驅動程式特定數據行之前,以及 ODBC 本身所授權的所有數據行之後。
新的數據行不僅會針對數據表值參數填入,也會填入CLR用戶定義型別參數。 UDT 參數的現有架構和目錄數據行仍會填入,但對於需要這些參數的數據類型,具有常見的架構和目錄數據行,將會在未來簡化應用程式開發。 (請注意,XML 架構集合有些不同,且未包含在這項變更中。
應用程式會使用 SQLTable 來判斷資料表類型的名稱,與持續性數據表、系統數據表和檢視表的名稱相同。 引進新的數據表類型 TABLE TYPE,讓應用程式能夠識別與數據表值參數相關聯的數據表類型。 數據表類型和一般數據表使用不同的命名空間。 這表示您可以針對資料表類型和實際數據表使用相同的名稱。 為了處理此狀況,已引進新的語句屬性SQL_SOPT_SS_NAME_SCOPE。 這個屬性會指定將數據表名稱當做參數的 SQLTable 和其他目錄函式,是否應該將資料表名稱解譯為實際數據表的名稱或數據表類型的名稱。
應用程式會使用 SQLColumns 來判斷資料表類型的數據行,其方式與持續性數據表相同,但必須先設定SQL_SOPT_SS_NAME_SCOPE,以指出它正在使用數據表類型,而不是實際數據表。 SQLPrimaryKeys 也可以與數據表類型搭配使用,再次使用 SQL_SOPT_SS_NAME_SCOPE。
此案例的範例程式代碼位於使用數據表值參數 (ODBC) 中的例程demo_metadata_from_catalog_APIs
。
擷取備妥語句的數據表值參數元數據
在此案例中,應用程式會使用 SQLNumParameters 和 SQLDescribeParam 來擷取數據表值參數的元數據。
IPD 欄位SQL_CA_SS_TYPE_NAME用來擷取數據表值參數的類型名稱。 IPD 欄位SQL_CA_SS_SCHEMA_NAME和SQL_CA_SS_CATALOG_NAME分別用來擷取其目錄和架構。
數據表類型定義和數據表值參數必須位於相同的資料庫中。 如果應用程式在使用數據表值參數時設定SQL_CA_SS_CATALOG_NAME,SQLSetDescField 將會回報錯誤。
SQL_CA_SS_CATALOG_NAME和SQL_CA_SS_SCHEMA_NAME也可以用來擷取與CLR用戶定義型別參數相關聯的目錄和架構。 SQL_CA_SS_CATALOG_NAME和SQL_CA_SS_SCHEMA_NAME是CLR UDT類型現有類型特定目錄架構屬性的替代方案。
此案例中,應用程式也會使用 SQLColumns 來擷取數據表值參數的數據行元數據,因為 SQLDescribeParam 不會傳回數據表值參數數據行之數據行的元數據。
此使用案例的範例程式代碼位於使用數據表值參數 (ODBC) 中的例程demo_metadata_from_prepared_statement
。