資料表值參數和資料行值的繫結與資料傳送

資料表值參數與其他參數一樣,必須先繫結,然後才能傳遞至伺服器。應用程式繫結資料表值參數與其他參數的方式都相同:使用 SQLBindParameter 或是 SQLSetDescFieldSQLSetDescRec 的對等呼叫。資料表值參數的伺服器資料類型是 SQL_SS_TABLE。C 類型可以指定為 SQL_C_DEFAULT 或 SQL_C_BINARY。

在 SQL Server 2008 或更新版本中,只支援輸入資料表值參數。因此,如果您嘗試將 SQL_DESC_PARAMETER_TYPE 設定為 SQL_PARAM_INPUT 以外的值,將會傳回含有 SQLSTATE = HY105 和「無效的參數類型」訊息的 SQL_ERROR。

您可以使用屬性 SQL_CA_SS_COL_HAS_DEFAULT_VALUE,將預設值指派給整個資料表值參數資料行。不過,您無法在 StrLen_or_IndPtr 中使用 SQL_DEFAULT_PARAM 搭配 SQLBindParameter,將預設值指派給個別的資料表值參數資料行值。您無法在 StrLen_or_IndPtr 中使用 SQL_DEFAULT_PARAM 搭配 SQLBindParameter,將整個資料表值參數設定為預設值。如果沒有遵循這些規則,SQLExecuteSQLExecDirect 就會傳回 SQL_ERROR。此時,系統會產生含有 SQLSTATE=07S01 和「參數 <p> 的預設參數用法無效」訊息的診斷記錄,其中 <p> 是查詢陳述式中 TVP 的序數。

繫結資料表值參數之後,應用程式必須接著繫結每個資料表值參數資料行。若要這樣做,應用程式會先呼叫 SQLSetStmtAttr,將 SQL_SOPT_SS_PARAM_FOCUS 設定為資料表值參數的序數。然後,應用程式會呼叫下列常式,藉以繫結資料表值參數的資料行:SQLBindParameterSQLSetDescRecSQLSetDescField。將 SQL_SOPT_SS_PARAM_FOCUS 設定為 0 會還原 SQLBindParameterSQLSetDescRecSQLSetDescField 針對一般最上層參數運作的一般作用。

雖然不會針對資料表值參數本身傳送或接收任何實際資料,但是會針對每個構成的資料行傳送或接收資料。因為資料表值參數是虛擬資料行,所以 SQLBindParameter 的參數是用來參考不同的屬性而非資料類型,如下所示:

參數

非資料表值參數類型的相關屬性,包括資料行

資料表值參數的相關屬性

InputOutputType

IPD 中的 SQL_DESC_PARAMETER_TYPE。

若為資料表值參數資料行,這必須與資料表值參數本身的設定相同。

IPD 中的 SQL_DESC_PARAMETER_TYPE。

這必須是 SQL_PARAM_INPUT。

ValueType

APD 中的 SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

APD 中的 SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

這必須是 SQL_C_DEFAULT 或 SQL_C_BINARY。

ParameterType

IPD 中的 SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

IPD 中的 SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

這必須是 SQL_SS_TABLE。

ColumnSize

IPD 中的 SQL_DESC_LENGTH 或 SQL_DESC_PRECISION。

這會因 ParameterType 的值而不同。

SQL_DESC_ARRAY_SIZE

當參數焦點設定為資料表值參數時,也可以使用 SQL_ATTR_PARAM_SET_SIZE 來設定。

如果是資料表值參數,這就是資料表值參數資料行緩衝區中的資料列數目。

DecimalDigits

IPD 中的 SQL_DESC_PRECISION 或 SQL_DESC_SCALE。

未使用。這必須是 0。

如果這個參數不是 0,SQLBindParameter 就會傳回 SQL_ERROR,並產生含有 SQLSTATE= HY104 和「無效的有效位數或小數位數」訊息的診斷記錄。

ParameterValuePtr

APD 中的 SQL_DESC_DATA_PTR。

SQL_CA_SS_TYPE_NAME。

這個參數對於預存程序呼叫而言是選擇性的,如果不需要的話可以指定 NULL。您必須針對不是程序呼叫的 SQL 陳述式指定這個參數。

這個參數也會當做一個唯一值,應用程式可以在使用變動資料列繫結時使用這個值來識別這個資料表值參數。如需詳細資訊,請參閱本主題後面的「變動資料表值參數資料列繫結」一節。

當資料表值參數類型名稱是指定於對 SQLBindParameter 的呼叫時,您必須將該名稱指定為 Unicode 值,即使在建置為 ANSI 應用程式的應用程式中也是如此。用於參數 StrLen_or_IndPtr 的值必須是 SQL_NTS,或名稱的字串長度乘以 sizeof(WCHAR)。

BufferLength

APD 中的 SQL_DESC_OCTET_LENGTH。

資料表值參數類型名稱的長度 (以位元組為單位)。

如果此類型名稱以 Null 結尾,這項設定可以是 SQL_NTS;如果不需要資料表值參數類型名稱則為 0。

StrLen_or_IndPtr

APD 中的 SQL_DESC_OCTET_LENGTH_PTR。

APD 中的 SQL_DESC_OCTET_LENGTH_PTR。

若為資料表值參數,這就是資料列計數而非資料長度。

資料表值參數支援兩種資料傳送模式:固定資料列繫結和變動資料列繫結。

固定資料表值參數資料列繫結

對於固定資料列繫結而言,應用程式會針對所有可能的輸入資料行值配置夠大的緩衝區 (或緩衝區陣列)。應用程式會進行下列作業:

  1. 使用 SQLBindParameterSQLSetDescRecSQLSetDescField 呼叫來繫結所有參數。

    1. 將 SQL_DESC_ARRAY_SIZE 設定為可針對每個資料表值參數傳送的最大資料列數目。這項作業可以在 SQLBindParameter 呼叫中完成。
  2. 呼叫 SQLSetStmtAttr,以便將 SQL_SOPT_SS_PARAM_FOCUS 設定為每個資料表值參數的序數。

    1. 針對每個資料表值參數,使用 SQLBindParameterSQLSetDescRecSQLSetDescField 呼叫來繫結資料表值參數資料行。

    2. 針對要設為預設值的每個資料表值參數資料行,呼叫 SQLSetDescField,以便將 SQL_CA_SS_COL_HAS_DEFAULT_VALUE 設定為 1。

  3. 呼叫 SQLSetStmtAttr,以便將 SQL_SOPT_SS_PARAM_FOCUS 設定為 0。這項作業必須在呼叫 SQLExecuteSQLExecDirect 之前完成。否則,系統將傳回 SQL_ERROR,並產生包含 SQLSTATE=HY024 和「屬性值 SQL_SOPT_SS_PARAM_FOCUS 無效 (在執行時間必須為零)」訊息的診斷記錄。

  4. 將 StrLen_or_IndPtr 或 SQL_DESC_OCTET_LENGTH_PTR 設定為 SQL_DEFAULT_PARAM (針對不含任何資料列的資料表值參數),或是下一次呼叫 SQLExecuteSQLExecDirect 時要傳送的資料列數目 (如果資料表值參數包含資料列的話)。StrLen_or_IndPtr 或 SQL_DESC_OCTET_LENGTH_PTR 無法針對資料表值參數設定為 SQL_NULL_DATA,因為資料表值參數不可為 Null (不過,資料表值參數的構成資料行可為 Null)。如果這個參數設定為無效的值,SQLExecuteSQLExecDirect 就會傳回 SQL_ERROR,並產生包含 SQLSTATE=HY090 和「參數 <p> 的字串或緩衝區長度無效」訊息的診斷記錄,其中 p 是參數編號。

  5. 呼叫 SQLExecuteSQLExecDirect

如果資料行的 StrLen_or_IndPtr 設定為 SQL_LEN_DATA_AT_EXEC(length) 或 SQL_DATA_AT_EXEC,就可以分段傳遞輸入資料表值參數資料行值。這與使用參數陣列時分段傳遞值一樣。如同所有資料執行中參數,SQLParamData 不會指出驅動程式要求資料的陣列資料列。應用程式必須負責處理這點。應用程式無法針對驅動程式要求值的順序提出任何假設。

變動資料表值參數資料列繫結

對於變動資料列繫結而言,資料列會在執行階段按照批次傳送,而且應用程式會視需要將資料列傳遞至驅動程式。這與個別參數值的資料執行中一樣。應用程式會針對變動資料列繫結,執行下列作業:

  1. 依照上一節「固定資料表值參數資料列繫結」的步驟 1 到 3 所述,繫結參數和資料表值參數資料行。

  2. 針對要在執行階段傳遞的任何資料表值參數,將 StrLen_or_IndPtr 或 SQL_DESC_OCTET_LENGTH_PTR 設定為 SQL_DATA_AT_EXEC。如果沒有設定任何項目,就會依照上一節所述的方式處理此參數。

  3. 呼叫 SQLExecuteSQLExecDirect。如果有任何 SQL_PARAM_INPUT 或 SQL_PARAM_INPUT_OUTPUT 參數要當做資料執行中參數處理,這就會傳回 SQL_NEED_DATA。在此情況下,應用程式會進行下列作業:

    • 呼叫 SQLParamData。這會傳回資料執行中參數的 ParameterValuePtr 值和 SQL_NEED_DATA 的傳回碼。當所有參數資料都已經傳遞至驅動程式時,SQLParamData 就會傳回 SQL_SUCCESS、SQL_SUCCESS_WITH_INFO 或 SQL_ERROR。對於資料執行中參數而言,ParameterValuePtr (與描述項欄位 SQL_DESC_DATA_PTR 相同) 可以被視為 Token,以便唯一識別需要值的參數。這個 "Token" 會在繫結階段從應用程式傳遞至驅動程式,然後在執行階段傳回應用程式。
  4. 為了針對 Null 資料表值參數傳送資料表值參數資料列資料,如果資料表值參數沒有任何資料列,應用程式就會呼叫 SQLPutData 並將 StrLen_or_Ind 設定為 SQL_DEFAULT_PARAM。

    應用程式會針對非 NULL TVP:

    • 將所有資料表值參數資料行的 Str_Len_or_Ind 設定為適當的值,並且針對非資料執行中參數的資料表值參數資料行,填入資料緩衝區。您可以利用一般參數分段傳遞至驅動程式的相同方式來運用資料表值參數資料行的資料執行中。

    • 呼叫 SQLPutData 並將 Str_Len_or_Ind 設定為要傳送至伺服器的資料列數目。超出 0 到 SQL_DESC_ARRAY_SIZE 或 SQL_DEFAULT_PARAM 之範圍以外的任何值都是錯誤,而且將傳回 SQLSTATE HY090 以及「無效的字串或緩衝區長度」訊息。0 表示已經傳送所有資料列,而且資料表值參數沒有其他資料 (如此清單中第二個項目符號項目所述)。只有當驅動程式第一次要求資料表值參數的資料時,才能使用 SQL_DEFAULT_PARAM (如此清單中第一個項目符號項目所述)。

  5. 已經傳送所有資料列時,針對 Str_Len_or_Ind 值為 0 的資料表值參數呼叫 SQLPutData,然後繼續進行上面的步驟 3a。

  6. 再次呼叫 SQLParamData。如果資料表值參數資料行之間存在任何資料執行中參數,SQLParamData 所傳回的 ValuePtrPtr 值將會識別這些參數。當所有資料行值都可以使用時,SQLParamData 將再次傳回資料表值參數的 ParameterValuePtr 值,而且應用程式會再次啟動。

請參閱

概念