ストアド プロシージャは、0 個以上のパラメータを受け取ることができます。また、値を返すこともできます。SQL Native Client OLE DB プロバイダを使用しているときは、ストアド プロシージャのパラメータを次の方法で渡すことができます。
- データ値をハードコーディングする。
- パラメータ マーカー (?) を使用してパラメータを指定し、プログラム変数をパラメータ マーカーにバインドしてから、データ値をプログラム変数に格納する。
メモ : |
|---|
| OLE DB で名前付きパラメータを使用して SQL Server ストアド プロシージャを呼び出す場合は、パラメータ名の先頭に '@' 文字を付ける必要があります。これは、SQL Server 固有の制限です。SQL Native Client OLE DB プロバイダは、この制限を MDAC よりも厳密に適用します。 |
パラメータをサポートするには、コマンド オブジェクトで ICommandWithParameters インターフェイスを公開します。パラメータを使用するには、コンシューマは、まず ICommandWithParameters::SetParameterInfo メソッドを呼び出して、プロバイダに渡すパラメータを記述します (または、必要に応じて、GetParameterInfo メソッドを呼び出す呼び出し元ステートメントを準備します)。次に、バッファの構造を指定するアクセサを作成し、このバッファにパラメータ値を格納します。最後に、アクセサのハンドルとバッファへのポインタを Execute に渡します。その後 Execute を呼び出す場合は、バッファに新しいパラメータ値を格納し、アクセサ ハンドルとバッファ ポインタを指定して Execute を呼び出します。
パラメータを使用する一時ストアド プロシージャを呼び出すコマンドは、まず、ICommandWithParameters::SetParameterInfo を呼び出してパラメータ情報を定義しないと、コマンドは適切に準備されません。これは、一時ストアド プロシージャの内部名がクライアントで使用される外部名とは異なるので、SQLOLEDB がシステム テーブルをクエリして、一時ストアド プロシージャのパラメータ情報を判断できないためです。
次に、パラメータのバインド プロセスの手順を示します。
- DBPARAMBINDINFO 構造体の配列にパラメータ情報を格納します。パラメータ情報には、パラメータ名、パラメータのデータ型を表すプロバイダ固有の名前、標準のデータ型名などが含まれます。配列内の構造体 1 つが、1 つのパラメータを表します。この配列に情報を格納して、SetParameterInfo メソッドに渡します。
- ICommandWithParameters::SetParameterInfo メソッドを呼び出し、パラメータをプロバイダに示します。SetParameterInfo は、各パラメータのネイティブ データ型を指定します。SetParameterInfo 引数は次のとおりです。
- 型情報を設定するパラメータの数
- 型情報を設定するパラメータの序数の配列
- DBPARAMBINDINFO 構造体の配列
- IAccessor::CreateAccessor コマンドを使用してパラメータ アクセサを作成します。このアクセサにより、バッファの構造を指定し、パラメータ値をバッファに格納します。CreateAccessor コマンドは、バインドのセットからアクセサを作成します。このバインドは、コンシューマが DBBINDING 構造体の配列を使用して記述します。各バインドでは、1 つのパラメータをコンシューマのバッファに関連付けます。バインドには、次のような情報が含まれます。
- バインドが適用されるパラメータの序数
- バインドの対象 (データ値、データ値の長さと状態)
- これらの各情報に関するバッファ内のオフセット
- コンシューマのバッファ内にあるデータ値の長さと型
アクセサは、アクセサのハンドルにより識別されます。このハンドルは HACCESSOR 型です。このハンドルは、CreateAccessor メソッドから返されます。コンシューマはアクセサを使い終わるたびに、ReleaseAccessor メソッドを呼び出してアクセサが保持しているメモリを解放する必要があります。
コンシューマが ICommand::Execute などのメソッドを呼び出す場合、アクセサのハンドルとバッファ自体へのポインタを渡します。プロバイダはこのアクセサを使用して、バッファ内にあるデータを送信する方法を決定します。
- DBPARAMS 構造体にデータを格納します。入力パラメータ値の取得と出力パラメータ値の書き込みに使われるコンシューマの変数が、実行時に DBPARAMS 構造体の ICommand::Execute に渡されます。DBPARAMS 構造体には、次の 3 つの要素が含まれます。
- アクセサ ハンドルで指定されているバインドに従ってプロバイダが入力パラメータ データを取得し、出力パラメータ データを返すための、バッファへのポインタ
- バッファ内のパラメータ セットの数
- 手順 3. で作成したアクセサ ハンドル
- ICommand::Execute を使用してコマンドを実行します。
ストアド プロシージャを呼び出す方法
SQL Server でストアド プロシージャを実行する場合、SQL Native Client OLE DB プロバイダは次の方法をサポートします。
- ODBC CALL エスケープ シーケンス
- リモート プロシージャ コール (RPC) エスケープ シーケンス
- Transact-SQL EXECUTE ステートメント
ODBC CALL エスケープ シーケンス
パラメータ情報を把握している場合は、ICommandWithParameters::SetParameterInfo メソッドを呼び出し、パラメータをプロバイダに示します。それ以外の場合は、ストアド プロシージャの呼び出しに ODBC CALL 構文を使用すると、プロバイダはヘルパ関数を呼び出してストアド プロシージャのパラメータ情報を取得します。
パラメータ情報 (パラメータのメタデータ) を把握していない場合は、ODBC CALL 構文の使用をお勧めします。
ODBC CALL エスケープ シーケンスを使用してプロシージャを呼び出す場合の一般的な構文は、次のとおりです。
{[?=]callprocedure_name[([parameter][,[parameter]]...)]}
次に例を示します。
{call SalesByCategory('Produce', '1995')}
RPC エスケープ シーケンス
RPC エスケープ シーケンスは、ストアド プロシージャを呼び出す ODBC CALL 構文と似ています。プロシージャを複数回呼び出す場合は、ストアド プロシージャを呼び出す 3 つの方法のうち、RPC エスケープ シーケンスのパフォーマンスが最も優れています。
RPC エスケープ シーケンスを使用してストアド プロシージャを実行する場合、プロバイダはパラメータ情報の決定にヘルパ関数を呼び出しません (ODBC CALL 構文では、ヘルパ関数が呼び出されます)。RPC 構文は ODBC CALL 構文よりも簡単です。そのためコマンドが高速に解析され、パフォーマンスが向上します。この場合は、ICommandWithParameters::SetParameterInfo を実行してパラメータ情報を提供する必要があります。
RPC エスケープ シーケンスを使用する場合は、戻り値が必要です。ストアド プロシージャが値を返さない場合、サーバーが既定で 0 を返します。また、ストアド プロシージャ上で SQL Server カーソルを開くことはできません。ストアド プロシージャは暗黙的に準備され、実際に ICommandPrepare::Prepare を呼び出すと失敗します。
パラメータのメタデータを把握できている場合は、ストアド プロシージャの実行方法として RPC エスケープ シーケンスの使用をお勧めします。
次に、ストアド プロシージャを呼び出す RPC エスケープ シーケンスの例を示します。
{rpc SalesByCategory}
Transact-SQL EXECUTE ステートメント
ストアド プロシージャを呼び出す方法としては、EXECUTE ステートメントよりも、ODBC CALL エスケープ シーケンスや RPC エスケープ シーケンスをお勧めします。SQL Native Client OLE DB プロバイダは、SQL Server の RPC メカニズムを使用して、コマンド処理を最適化します。この RPC プロトコルでは、サーバー側で実行されるパラメータ処理やステートメントの解析作業の多くを排除することで、パフォーマンスを向上しています。
次に、Transact-SQL EXECUTE ステートメントの例を示します。
EXECUTE SalesByCategory 'Produce', '1995'
メモ :