API サーバー カーソル

OLE DB、ODBC、および ADO の各 API は、実行された SQL ステートメントの結果セットへのカーソルのマッピングをサポートしています。Microsoft SQL Server Native Client OLE DB プロバイダと SQL Server Native Client ODBC ドライバは、API サーバー カーソルを使用してこれらの操作を実装します。API サーバー カーソルとは、サーバーに実装され、API カーソル関数により管理されるカーソルです。アプリケーションから API カーソル関数を呼び出すと、そのカーソル操作は OLE DB プロバイダまたは ODBC ドライバによってサーバーに送信されます。

OLE DB、ODBC、および ADO で API サーバー カーソルを使用するときは、API の関数またはメソッドを使用して次の操作を行います。

  1. 接続を開きます。

  2. API が各結果セットに自動的にマップするカーソルの特性を定義する属性またはプロパティを設定します。

  3. 1 つ以上の Transact-SQL ステートメントを実行します。

  4. API 関数またはメソッドを使用して、結果セットの行をフェッチします。

API カーソルの属性またはプロパティが既定値に設定されている場合、SQL Server Native Client OLE DB プロバイダと SQL Server Native Client ODBC ドライバは既定の結果セットを使用します。技術的に言えば API はカーソルを要求しているのですが、既定のカーソル特性は既定の結果セットの動作と一致しています。このため、OLE DB プロバイダと ODBC ドライバは、既定の結果セットを使用して既定のカーソル オプションを実装します。これは、サーバーから行を取得する最も効率的な方法です。既定の結果セットを使用すると、アプリケーションは任意の Transact-SQL ステートメントやバッチを実行できますが、1 つの接続には未完了のステートメントを 1 つしか保持できません。つまり、アプリケーションがその接続で他のステートメントを実行するには、1 つのステートメントによって返されたすべての結果セットを処理するか、取り消す必要があります。

API カーソルの属性またはプロパティが既定値以外に設定されている場合、SQL Server Native Client OLE DB プロバイダと SQL Server Native Client ODBC ドライバは、既定の結果セットの代わりに API サーバー カーソルを使用します。行をフェッチする API 関数を呼び出すたびに、サーバーとの間にやり取りが発生し、API サーバー カーソルから行がフェッチされます。

API サーバー カーソルの制限事項

アプリケーションで API サーバー カーソルを使用する場合、次のステートメントを実行できません。

  • SQL Server がサーバー カーソルでの使用をサポートしていない Transact-SQL ステートメント

  • 複数の結果セットを返すバッチまたはストアド プロシージャ

  • COMPUTE、COMPUTE BY、FOR BROWSE、または INTO 句を伴う SELECT ステートメント

  • リモート ストアド プロシージャを参照する EXECUTE ステートメント

API サーバー カーソルの実装

SQL Server Native Client OLE DB プロバイダと SQL Server Native Client ODBC ドライバは、次の特殊なシステム ストアド プロシージャを使用して、カーソル操作をサーバーに通知します。

  • sp_cursoropen は、カーソルに関連付ける SQL ステートメントおよびカーソル オプションを定義してから、カーソルにデータを格納します。

  • sp_cursorfetch は、行または行のブロックをカーソルからフェッチします。

  • sp_cursorclose は、カーソルを閉じ、割り当てを解除します。

  • sp_cursoroption は、さまざまなカーソル オプションを設定するために使用されます。

  • sp_cursor は、位置指定更新を要求するために使用されます。

  • sp_cursorprepare は、カーソルに関連付けられた Transact-SQL ステートメントまたはバッチをコンパイルして実行プランを作成します。カーソルは作成しません。

  • sp_cursorexecute は、sp_cursorprepare によって作成された実行プランからカーソルを作成してデータを格納します。

  • sp_cursorunprepare は、sp_cursorprepare で作成された実行プランを破棄します。

  • sp_cursorprepexec は、カーソルに関連付けられた送信済みの Transact-SQL ステートメントまたはバッチに対応するプランをコンパイルしてカーソルを作成し、データを格納します。sp_cursorprepexec には、sp_cursorpreparesp_cursorexecute の動作が組み合わされています。

上記のシステム ストアド プロシージャは、API サーバー カーソルを使用する ADO、OLE DB、および ODBC アプリケーションを SQL Server Profiler でトレースするときに使用されます。これらは SQL Server Native Client OLE DB プロバイダと SQL Server Native Client ODBC ドライバが内部で使用することのみを目的としたプロシージャです。アプリケーションは、データベース API のカーソル機能によって、上記のプロシージャの機能をすべて利用できます。これらのプロシージャをアプリケーションから直接指定することはできません。

SQL Server である接続に対してステートメントが実行されると、その最初のステートメントから返された結果がすべて処理されるか、取り消されるまで、その接続で他のステートメントを実行できません。この規則は API サーバー カーソルを使用するときにも適用されますが、アプリケーションからは、SQL Server が 1 つの接続で複数のステートメントをアクティブにできるようになったように見えます。これは、完全な結果セットがサーバー カーソルに格納されていて、SQL Server に送信されるステートメントだけが sp_cursor システム ストアド プロシージャを実行するためです。SQL Server がこのストアド プロシージャを実行した後、クライアントがその結果セットを取得した直後に他のステートメントを実行できるようになります。OLE DB プロバイダと ODBC ドライバは、常に sp_cursor ストアド プロシージャから返されたすべての結果を取得してからアプリケーションに制御を返します。これにより、アプリケーションは、アクティブなサーバー カーソルが複数にならないようにフェッチをインターリーブできます。

次の表に、アプリケーションが 2 つのステートメント ハンドルを使用して、1 つの接続で同時に 2 つのカーソルを処理する方法を示します。

ステートメント ハンドル 1

ステートメント ハンドル 2

API サーバー カーソルを使用するようにカーソル属性を設定します。

 

SQLExecDirect で SQL ステートメントを実行します。ODBC ドライバが sp_cursoropen を呼び出し、プロシージャによって返された結果セットを取得します。

 

 

API サーバー カーソルを使用するようにカーソル属性を設定します。

 

SQLExecDirect で SQL ステートメントを実行します。ODBC ドライバが sp_cursoropen を呼び出し、プロシージャによって返された結果セットを取得します。

SQLFetchScroll を呼び出して行の最初のブロックを取得します。ドライバが sp_cursorfetch を呼び出し、プロシージャによって返された結果セットを取得します。

 

 

SQLFetchScroll を呼び出して行の最初のブロックを取得します。ドライバが sp_cursorfetch を呼び出し、プロシージャによって返された結果セットを取得します。

SQLFetchScroll を呼び出して行の別のブロックを取得します。ドライバが sp_cursorfetch を呼び出し、プロシージャによって返された結果セットを取得します。

 

 

SQLFetchScroll を呼び出して行の別のブロックを取得します。ドライバが sp_cursorfetch を呼び出し、プロシージャによって返された結果セットを取得します。

SQLFreeStmt または SQLCloseCursor を呼び出します。ドライバが sp_cursorclose を呼び出します。

 

 

SQLFreeStmt または SQLCloseCursor を呼び出します。ドライバが sp_cursorclose を呼び出します。

sp_cursor ストアド プロシージャの呼び出し後、接続には未完了の結果が残っていないので、Transact-SQL ステートメントをすべて API サーバー カーソルで実行する場合に限り、1 つの接続で複数のステートメントを同時に実行できます。

API サーバー カーソルの指定

次に、API での API サーバー カーソルの使用方法をまとめます。

  • OLE DB

    • セッション オブジェクトを開き、コマンド オブジェクトを開いて、コマンド テキストを指定します。

    • カーソルの動作を制御するために、DBPROP_OTHERINSERT、DBPROP_OTHERUPDATEDELETE、DBPROP_OWNINSERT、DBPROP_OWNUPDATEDELETE などの行セットプロパティを設定します。

    • コマンド オブジェクトを実行します。

    • IRowset::GetNextRows、IRowsetLocate::GetRowsAt、IRowsetLocate::GetRowsAtBookmark、IRowsetScroll::GetRowsAtRatio などのメソッドを使用して結果セットの行をフェッチします。

  • ODBC

    • 接続を開き、SQLAllocHandle を呼び出してステートメント ハンドルを割り当てます。

    • SQLSetStmtAttr を呼び出し、SQL_ATTR_CURSOR_TYPE、SQL_ATTR_CONCURRENCY、および SQL_ATTR_ROW_ARRAY_SIZE 属性を設定します。SQL_ATTR_CURSOR_SCROLLABLE 属性と SQL_ATTR_CURSOR_SENSITIVITY 属性を設定することによってカーソルの動作を指定することもできます。

    • SQLExecDirect、または SQLPrepareSQLExecute を使用して Transact-SQL ステートメントを実行します。

    • SQLFetch または SQLFetchScroll を使用して行または行のブロックをフェッチします。

  • ADO

    • Connection オブジェクトと Recordset オブジェクトを定義してから、Connection オブジェクトの Open メソッドを実行します。

    • CursorType パラメータと LockType パラメータのいずれかまたは両方を指定して、Recordset オブジェクトの Open メソッドを実行します。

    • Move、MoveFirst、MoveLast、MoveNext、および MovePrevious レコードセット メソッドを使用して行をフェッチします。

API サーバー カーソルと SET オプション

SQL Server で、フェッチ ステートメントが実行され、次に示すような、プランに影響するオプションあるいはインデックス付きビューまたは計算列に必要なオプションが変更されたとします。この場合、カーソルは、カーソルが開かれたときに有効であったオプション値のスナップショットを使用します。これらの値は、その後のすべてのフェッチ操作に使用されます。また、現在のコンテキストの変更は無視されます。

プランに影響するオプション

ARITHABORT

NUMERIC_ROUNDABORT

FORCEPLAN

QUOTED_IDENTIFIER

ANSI_NULL_DFLT_ON

ANSI_WARNINGS

ANSI_PADDING

ANSI_NULLS

CONCAT_NULL_YIELDS_NULL

DATEFIRST

DATEFORMAT

LANGUAGE

TEXTSIZE

インデックス付きビューと計算列

ANSI_NULLS

ANSI_PADDING

ANSI_WARNINGS

ARITHABORT (互換性レベルが 80 以下の場合) CONCAT_NULL_YIELDS_NULL

QUOTED_IDENTIFIER

NUMERIC_ROUNDABORT