預存程式 - 在 SQL Server Native Client 中呼叫
適用於: SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Analytics Platform System (PDW)
重要
SQL Server Native Client (通常縮寫為 SNAC) 已從 SQL Server 2022 (16.x) 和 SQL Server Management Studio 19 (SSMS) 中移除。 不建議使用 SQL Server Native Client OLE DB 提供者 (SQLNCLI 或 SQLNCLI11) 和舊版 Microsoft OLE DB Provider for SQL Server (SQLOLEDB) 進行新的開發。 請切換至新的 Microsoft OLE DB Driver (MSOLEDBSQL) for SQL Server 以繼續使用。
預存程序可以有零或多個參數。 它也可以傳回值。 使用 SQL Server Native Client OLE DB 提供者時,預存程式的參數可以透過下列方式傳遞:
將資料值寫入程式碼。
使用參數標記 (?) 來指定參數、將程式變數繫結至參數標記,然後將資料值放在程式變數中。
注意
搭配 OLE DB 使用具名參數呼叫 SQL Server 預存程序時,參數名稱開頭必須是 '@' 字元。 這是 SQL Server 特定限制。 SQL Server Native Client OLE DB 提供者會比 MDAC 更嚴格地強制執行這項限制。
為支援參數,會在命令物件上公開 ICommandWithParameters 介面。 為使用參數,取用者會先呼叫 ICommandWithParameters::SetParameterInfo 方法 (或選擇性地準備呼叫 GetParameterInfo 方法的呼叫陳述式) 來描述提供者的參數。 接著,取用者會建立指定緩衝區結構的存取子,並將參數值放在此緩衝區中。 最後,它會將存取子的控制代碼與緩衝區的指標傳遞到 Execute 的緩衝區。 稍後呼叫 Execute 時,取用者會將新的參數值放在緩衝區中,並利用存取子控制代碼和緩衝區指標呼叫 Execute。
使用參數呼叫暫存程式的命令必須先呼叫 ICommandWithParameters::SetParameterInfo 來定義參數資訊,才能順利備妥命令。 這是因為暫存程式的內部名稱與用戶端所使用的外部名稱不同,SQLOLEDB 無法查詢系統數據表來判斷暫存程式的參數資訊。
以下是參數係結程式中的步驟:
在 DBPARAMBINDINFO 結構的陣列中填入參數資訊;也就是參數名稱、參數資料類型的提供者專屬名稱,或標準資料類型名稱等等。 陣列中的每個結構會描述一個參數。 接著,就會將此陣列傳遞到 SetParameterInfo 方法。
呼叫 ICommandWithParameters::SetParameterInfo 方法來描述提供者的參數。 SetParameterInfo 會指定每個參數的原生資料類型。 SetParameterInfo 引數為:
用於設定類型資訊之參數的數目。
用於設定類型資訊之參數序數的陣列。
DBPARAMBINDINFO 結構的陣列。
使用 IAccessor::CreateAccessor 命令建立參數存取子。 存取子會指定緩衝區的結構,並將參數值放在緩衝區中。 CreateAccessor 命令會從一組繫結建立存取子。 這些繫結可由取用者使用 DBBINDING 結構的陣列描述。 每個繫結都會與取用者緩衝區的單一參數產生關聯,而且會包含資訊,例如:
套用繫結之參數的序數。
繫結的項目 (資料值、其長度及其狀態)。
緩衝區中對每一個部分的位移。
存在於取用者緩衝區內之資料值的長度和類型。
存取子是由其類型為 HACCESSOR 的控制代碼識別。 此控制代碼會由 CreateAccessor 方法傳回。 每當取用者完成使用存取子時,取用者必須呼叫 ReleaseAccessor 方法來釋放所保留的記憶體。
當取用者呼叫 ICommand::Execute 之類的方法時,它會將控制代碼傳遞到存取子以及緩衝區本身的指標。 提供者會使用此存取子決定如何傳送包含在緩衝區中的資料。
填入 DBPARAMS 結構。 從中取用輸入參數值的取用者變數以及寫入輸出參數的取用者變數在執行階段都會傳遞到 DBPARAMS 結構的 ICommand::Execute 中。 DBPARAMS 結構包含三個元素:
根據存取子控制代碼指定的繫結,提供者從其中擷取輸入參數資料的緩衝區指標以及提供者傳回輸出參數資料的緩衝區指標。
緩衝區中的參數集數目。
存取子控制代碼會在步驟 3 中建立。
使用 ICommand::Execute 執行命令。
呼叫預存程式的方法
在 SQL Server 中執行預存程序時,SQL Server Native Client OLE DB 提供者支援:
ODBC CALL 逸出序列。
遠端程序呼叫 (RPC) 逸出序列。
Transact-SQL EXECUTE 陳述式。
ODBC CALL 逸出序列
如果您知道參數資訊,請呼叫 ICommandWithParameters::SetParameterInfo 方法來描述提供者的參數。 否則,在呼叫預存程序中使用 ODBC CALL 語法時,提供者會呼叫 Helper 函數來尋找預存程序參數資訊。
如果您不確定參數資訊 (參數元數據),建議使用ODBC CALL 語法。
使用 ODBC CALL 逸出序列呼叫程序的一般語法為:
{[?=]callprocedure_name[([parameter][,[parameter]]...)]}
例如:
{call SalesByCategory('Produce', '1995')}
RPC 逸出序列
RPC 逸出序列類似於呼叫預存程序的 ODBC CALL 語法。 如果您要多次呼叫程式,RPC 逸出序列會在呼叫預存程式的三種方法之間提供最佳效能。
當 RPC 逸出序列用來執行預存程式時,提供者不會呼叫任何協助程式函式來判斷參數資訊(如同 ODBC CALL 語法的情況所示)。 RPC 語法比 ODBC CALL 語法簡單,因此命令集的剖析速度較快,可以增進效能。 在此情況下,您需要執行 ICommandWithParameters::SetParameterInfo 來提供參數資訊。
RPC 逸出序列要求您擁有傳回值。 如果預存程式未傳回值,則伺服器預設會傳回 0。 此外,您無法在預存程式上開啟 SQL Server 數據指標。 預存程序會以隱含的方式準備,而 ICommandPrepare::Prepare 的呼叫將會失敗。 由於無法準備 RPC 呼叫,因此您無法查詢資料行元數據;IColumnsInfo::GetColumnInfo 和 IColumnsRowset::GetColumnsRowset 會傳回DB_E_NOTPREPARED。
如果您知道所有參數中繼資料,RPC 逸出序列是執行預存程序的建議方式。
這是呼叫預存程式的 RPC 逸出序列範例:
{rpc SalesByCategory}
如需示範 RPC 逸出序列的範例應用程式,請參閱執行預存程序 (使用 RPC 語法) 與處理傳回碼和輸出參數 (OLE DB)。
Transact-SQL EXECUTE 語句
ODBC CALL 逸出序列和 RPC 逸出序列都是呼叫預存程序而非 EXECUTE 陳述式的慣用方法。 SQL Server Native Client OLE DB 提供者會使用 SQL Server 的 RPC 機制來優化命令處理。 此 RPC 通訊協定可藉由消除伺服器上完成的大部分參數處理和語句剖析,來提升效能。
這是 Transact-SQL EXECUTE 語句的範例:
EXECUTE SalesByCategory 'Produce', '1995'