コンピュータ サイエンスでは、データベース カーソルは、データベース内のレコードをトラバースできるメカニズムです。カーソルは、データベース レコードの取得、追加、削除など、トラバースと連動した後続の処理を容易にします。トラバースというデータベース カーソルの特性により、カーソルはプログラミング言語の反復子の概念に似ています。
カーソルは、データベース プログラマーがデータベース システムクエリによって返された個々の行を処理するために使用されます。カーソルを使用すると、結果セット全体を一度に操作できます。このシナリオでは、カーソルによって結果セット内の行を順番に処理できます。
SQL プロシージャでは、カーソルを使用すると、結果セット (データ行のセット) を定義し、行ごとに複雑なロジックを実行できます。同じメカニズムを使用することで、SQL プロシージャでも結果セットを定義し、それを SQL プロシージャの呼び出し元またはクライアント アプリケーションに直接返すことができます。
カーソルは、行セット内の 1 行へのポインターとして考えることができます。カーソルは一度に 1 行しか参照できませんが、必要に応じて結果セットの他の行に移動できます。
使用法
SQL プロシージャでカーソルを使用するには、次の操作を行う必要があります。
- 結果セットを定義するカーソルを宣言する
- カーソルを開いて結果セットを確立する
- 必要に応じてカーソルからデータを1行ずつローカル変数に取得します。
- 完了したらカーソルを閉じます
カーソルを操作するには、次のSQL文を使用する必要があります。
このセクションでは、 SQL:2003標準が埋め込み SQL のアプリケーションでカーソルを使用する方法を定義する方法を紹介します。リレーショナル データベース システムのアプリケーション バインディングがすべてこの標準に準拠しているわけではなく、一部 ( CLIやJDBCなど) は異なるインターフェイスを使用します。
プログラマーは、 ...ステートメントを使用してカーソルに (必須の) 名前を割り当てること
で、カーソルをDBMSに認識させます。DECLARECURSOR
DECLARE cursor_name CURSOR IS SELECT ... FROM ...
コードがデータにアクセスする前に、OPENステートメントを使用してカーソルを開く必要があります。カーソルが正常に開かれると、カーソルは結果セットの最初の行
の前に配置されます。
カーソル名を開く
アプリケーションは、ステートメントを使用して、結果セット内の特定の行にカーソルを配置しますFETCH。フェッチ操作により、行のデータがアプリケーションに転送されます。
FETCHカーソル名INTO ...
アプリケーションが利用可能なすべての行を処理するか、フェッチ操作が存在しない行に配置されると (以下のスクロール可能なカーソルと比較してください)、DBMS は結果セットの終了を示すために SQLSTATE '02000' (通常は SQLCODE +100 が伴います) を返します。
最後のステップでは、次のステートメントを使用してカーソルを閉じますCLOSE。
カーソル名を閉じる
カーソルを閉じた後、プログラムはそれを再度開くことができます。これは、DBMS が同じクエリまたは別のクエリを再評価し、新しい結果セットを構築することを意味します。
スクロール可能なカーソル
プログラマーは、カーソルをスクロール可能またはスクロール不可能として宣言できます。スクロール可能性は、カーソルが移動できる方向を示します。
スクロール不可能な(または前方のみの) カーソルでは、各行を最大 1 回だけフェッチできFETCH、カーソルは自動的に次の行に移動します。最後の行をフェッチした後、再度フェッチすると、カーソルは最後の行の後に配置され、次のコードが表示されますSQLSTATE 02000 (SQLCODE +100)。
プログラムは、 SQL ステートメントを使用して、結果セット内の任意の場所にスクロール可能なFETCHカーソルを配置できます。カーソルを宣言するときに、キーワード SCROLL を指定する必要があります。デフォルトは ですNO SCROLLが、JDBC などの異なる言語バインディングでは異なるデフォルトが適用される場合があります。
DECLARE cursor_name 感度 SCROLL CURSOR FOR SELECT ... FROM ...
スクロール可能なカーソルのターゲット位置は、相対的 (現在のカーソル位置から) または絶対的 (結果セットの先頭から) に指定できます。
FETCH [ 次 | 前 | 最初 | 最後 ]カーソル名から
FETCH ABSOLUTE n FROMカーソル名
FETCH RELATIVE n FROM cursor_name ;
スクロール可能なカーソルは、結果セット内の同じ行に複数回アクセスする可能性があります。したがって、他のトランザクションからのデータ変更 (挿入、更新、削除操作) が結果セットに影響を与える可能性があります。カーソルは、このようなデータ変更に対して SENSITIVE または INSENSITIVE になります。Sensitive カーソルは、カーソルの結果セットに影響を与えるデータ変更を検出しますが、Insensitive カーソルは検出しません。また、カーソルが INSENSITIVE になる場合もあり、その場合、DBMS は可能な限り Sensitive を適用しようとします。
「保留」
カーソルは通常、トランザクションの終了時、つまり COMMIT または ROLLBACK (またはトランザクションの暗黙的な終了) の発生時に自動的に閉じられます。カーソルが WITH HOLD 句を使用して宣言されている場合、その動作を変更できます (デフォルトは WITHOUT HOLD)。ホールド可能なカーソルは COMMIT の間は開いたままで、ROLLBACK 時に閉じられます。(一部の DBMS はこの標準動作から外れ、ROLLBACK の間もホールド可能なカーソルを開いたままにします。)
DECLARE cursor_name CURSOR WITH HOLD FOR SELECT .... FROM ....
COMMIT が発生すると、保持可能なカーソルが次の行の前に配置されます。したがって、位置指定UPDATEまたは位置指定DELETEステートメントは、トランザクションで最初に FETCH 操作が発生した後にのみ成功します。
JDBC ではカーソルがデフォルトで保持可能として定義されていることに注意してください。これは、JDBC がデフォルトで自動コミットも有効にするためです。
位置指定更新/削除ステートメント
カーソルは、DBMS からアプリケーションにデータをフェッチするだけでなく、更新または削除するテーブル内の行を識別するためにも使用できます。SQL:2003 標準では、この目的のために位置指定更新および位置指定削除 SQL ステートメントが定義されています。このようなステートメントでは、述語を含む通常のWHERE句は使用されません。代わりに、カーソルが行を識別します。カーソルは、ステートメントによって開かれ、行に配置されている必要がありますFETCH。
テーブル名の更新 セット ...カーソル名の現在の 場所
消去テーブル名 から カーソル名の現在の 位置
位置指定更新または削除ステートメントを正常に実行するには、カーソルは更新可能な結果セットで動作する必要があります。そうしないと、DBMS はカーソルで参照される基になるテーブルにデータの変更を適用する方法を認識できません。
分散トランザクションにおけるカーソル
トランザクション モニターを使用して制御される分散トランザクション ( X/Open XA環境) でのカーソルの使用は、非分散トランザクションでのカーソルの使用と変わりません。
ただし、ホールド可能カーソルを使用する場合は注意が必要です。接続はさまざまなアプリケーションで使用される可能性があります。したがって、トランザクションが終了してコミットされると、後続のトランザクション (別のアプリケーションで実行されている) が既存のホールド可能カーソルを継承する可能性があります。したがって、アプリケーション開発者は、その状況に注意する必要があります。
XQuery のカーソル
XQuery言語では、 subsequence()関数を使用してカーソルを作成できます。
形式は次のとおりです。
$表示シーケンス:=サブシーケンス( $結果, $開始, $項目数)とします。
ここで、$ resultは最初の XQuery の結果、$start は開始する項目番号、$item-countは返される項目の数です。
同様に、述語を使用してこれを行うこともできます。
$表示シーケンス:= $結果[ $開始から$終了まで]
$end終了シーケンスは
どこですか。
完全な例については、
XQuery/検索、ページング、ソート#Wikibooks のページング。
カーソルの欠点
以下の情報は、特定のデータベース システムによって異なる場合があります。
カーソルから行をフェッチすると、毎回ネットワーク ラウンド トリップが発生する可能性があります。これにより、DELETE などの単一の SQL ステートメントの実行に通常必要なネットワーク帯域幅よりもはるかに多くのネットワーク帯域幅が使用されます。ネットワーク ラウンド トリップが繰り返されると、カーソルを使用した操作の速度が大幅に低下する可能性があります。一部の DBMS では、ブロック フェッチを使用してこの影響を軽減しようとします。ブロック フェッチでは、複数の行がサーバーからクライアントにまとめて送信されます。クライアントは、行のブロック全体をローカル バッファーに格納し、バッファーが使い果たされるまでそこから行を取得します。
カーソルは、ロック、パッケージ、プロセス、一時ストレージなどのリソースをサーバー上に割り当てます。たとえば、Microsoft SQL Server は、一時テーブルを作成し、クエリの結果セットをそのテーブルに設定することでカーソルを実装します。カーソルが適切に閉じられていない (割り当て解除されていない) 場合、SQL セッション (接続) 自体が閉じられるまでリソースは解放されません。サーバー上のリソースがこのように浪費されると、パフォーマンスの低下や障害につながる可能性があります。
例
従業員テーブル
SQL > desc EMPLOYEES_DETAILS ;名前 Null? タイプ--------------- -------- ------------ EMPLOYEE_ID NOT NULL NUMBER(6) FIRST_NAME VARCHAR2(20) LAST_NAME NOT NULL VARCHAR2(25) EMAIL NOT NULL VARCHAR2(30) PHONE_NUMBER VARCHAR2(20) HIRE_DATE NOT NULL DATE JOB_ID NOT NULL VARCHAR2(10) SALARY NUMBER(8,2) COMMISSION_PCT NUMBER(2,2) MANAGER_ID NUMBER(6) DEPARTMENT_ID NUMBER(4)
EEと呼ばれるサンプルカーソル
手順EE をBEGINとして作成または置換します
v_employeeID EMPLOYEES_DETAILS.EMPLOYEE_ID % TYPE を宣言します。v_FirstName EMPLOYEES_DETAILS.FIRST_NAME % TYPE を宣言します。v_LASTName EMPLOYEES_DETAILS.LAST_NAME %TYPE を宣言します。v_JOB_ID EMPLOYEES_DETAILS.JOB_ID % TYPE := 'IT_PROG' を宣言します。
カーソルc_EMPLOYEES_DETAILS IS SELECT EMPLOYEE_ID 、FIRST_NAME 、LAST_NAME FROM EMPLOYEES_DETAILS WHERE JOB_ID = 'v_JOB_ID' ;
c_EMPLOYEES_DETAILSをオープンし始めます。
ループ
c_EMPLOYEES_DETAILS をv_employeeID 、v_FirstName 、v_LASTNameにフェッチします。
DBMS_OUTPUT.put_line ( v_employeeID ) ; DBMS_OUTPUT.put_line ( v_FirstName ) ; DBMS_OUTPUT.put_line ( v_LASTName ) ;
c_EMPLOYEES_DETAILS %NOTFOUNDの場合は終了;ループを終了;
c_EMPLOYEES_DETAILSを閉じます。終了です。
終わり;
参照
参考文献
- Christopher J. Date : Database in Depth、O'Reilly & Associates、ISBN 0-596-10012-4
- Thomas M. Connolly、Carolyn E. Begg:データベースシステム、Addison-Wesley、ISBN 0-321-21025-5
- Ramiz Elmasri、Shamkant B. Navathe:データベースシステムの基礎、Addison-Wesley、ISBN 0-201-54263-3
- Neil Matthew、Richard Stones: PostgreSQL によるデータベース入門: 初心者からプロまで、Apress、ISBN 1-59059-478-9
- トーマス・カイト:エキスパート・ワン・オン・ワン:オラクル、Apress、ISBN 1-59059-525-4
- Kevin Loney: Oracle Database 10g: 完全リファレンス、Oracle Press、ISBN 0-07-225351-7
外部リンク
- ポートランドパターンリポジトリからの説明
- Berkeley DB リファレンス ガイド: カーソル操作
- PostgreSQL カーソル
- MySQL のカーソルドキュメント
- FirebirdSQL カーソルのドキュメント
