DECLARE — カーソルを定義する
DECLAREname[ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FORquery
DECLAREを使うと、カーソルが使用できるようになります。
これは、巨大な問い合わせの結果から一度に少数の行を取り出す機能です。
カーソルを作成した後、FETCHを使用して行を取り出します。
このマニュアルページではSQLコマンドレベルでのカーソルの使用方法について説明します。 PL/pgSQL内でカーソルを使用するつもりであれば、規則が異なりますので、43.7を参照してください。
name作成されるカーソルの名前です。 これはセッションで実行中の他のカーソルの名前とは異なるものでなければなりません。
BINARYカーソルによるデータの取得が、テキスト形式ではなくバイナリ形式になります。
ASENSITIVEINSENSITIVE
カーソルの感度とは、カーソルの背後にあるデータが、カーソルが宣言された後に、同じトランザクション内で変更された場合、それがそのカーソル内で可視かどうかを決めるものです。
INSENSITIVEは可視ではないことを意味し、ASENSITIVEは、その振舞いが実装依存であることを意味します。
第3の振舞いであるSENSITIVEはそのような変更がカーソル内で可視であることを意味しますが、PostgreSQLでは利用できません。
PostgreSQLでは、カーソルはすべてinsensitiveですので、このキーワードを使用しても効果はなく、このキーワードは標準SQLとの互換性を保持するために存在しています。
INSENSITIVEをFOR UPDATEまたはFOR SHAREといっしょに指定するとエラーになります。
SCROLLNO SCROLLSCROLLは、そのカーソルから通常の順序通りでない方法で(例えば後方から)行を取り出し可能であることを指定します。
問い合わせの実行計画が複雑になると、SCROLLの指定によって問い合わせの実行時間が増大する可能性があります。
NO SCROLLは、そのカーソルから順序通りでない方法では行を取り出せないことを指定します。
デフォルトでは、いくつかの場合でスクロール可能です。
これはSCROLLの指定と同じではありません。
詳細は注釈を参照してください。
WITH HOLDWITHOUT HOLDWITH HOLDは、カーソルを生成したトランザクションが正常にコミット処理を行った後も、そのカーソルの使用を続けられることを指定します。
WITHOUT HOLDは、カーソルを生成したトランザクションの外部では、そのカーソルを使用できないことを指定します。
WITH HOLDもWITHOUT HOLDも指定されない場合、WITHOUT HOLDがデフォルトとなります。
query
ASENSITIVE、BINARY、INSENSITIVE、SCROLLキーワードは任意の順番で指定することができます。
通常のカーソルは、SELECTの出力と同じテキスト形式でデータを返します。
BINARYは、カーソルがバイナリ形式でデータを返すことを示します。
これによりサーバ、クライアントの両方で変換に関する作業を省くことができますが、プラットフォームに依存するバイナリデータ書式を扱うためのプログラマの作業が大きくなります。
例えば、問い合わせが整数の列から値として1を返す場合、デフォルトのカーソルからは1という文字列を取得することになりますが、バイナリ形式のカーソルからは、内部表現を使った4バイトの値を(ビッグエンディアンのバイト順で)取得することになります。
バイナリ形式のカーソルは注意して使わなければなりません。 psqlなどの多くのアプリケーションは、データはテキスト形式で返されることを期待しており、バイナリ形式のカーソルを扱うことができません。
クライアントアプリケーションが「拡張問い合わせ」プロトコルを使用してFETCHコマンドを発行する場合、テキスト形式とバイナリ形式のどちらでデータを受け取るのかは、バインドプロトコルメッセージで指定します。
この選択は、カーソル定義での指定を上書きします。
全てのカーソルをテキスト形式/バイナリ形式のどちらでも扱うことができる拡張問い合わせプロトコルでは、バイナリカーソルという概念は旧式なものです。
WITH HOLDが指定されなければ、このコマンドで生成されるカーソルは現在のトランザクションの中でのみ使用することができます。
したがって、WITH HOLDのないDECLAREはトランザクションブロックの外側では意味がありません。
その場合、カーソルはこの文が完了するまでのみ有効です。
そのため、PostgreSQLはトランザクションブロックの外部でこうしたコマンドが使用された場合エラーを報告します。
トランザクションブロックを定義するには、BEGINとCOMMIT(またはROLLBACK)を使用してください。
WITH HOLDが指定され、カーソルを作成したトランザクションのコミットに成功した場合、同一セッション内のその後のトランザクションからそのカーソルにアクセスすることができます
(ただし、トランザクションがアボートされた場合、そのカーソルは削除されます)。
WITH HOLD付きで作成されたカーソルは、そのカーソルに対して明示的なCLOSEが発行された場合やセッションが終了した時に閉じられます。
現在の実装では、保持されたカーソルを使って表される行は、その後のトランザクションでも利用できるように、一時ファイルかメモリ領域にコピーされます。
問い合わせがFOR UPDATEまたはFOR SHAREを含む場合、WITH HOLDを指定することはできません。
カーソルから逆方向にデータを取り出す時には、SCROLLオプションを指定するべきです。
これは標準SQLでは必須となっています。
しかし、以前のバージョンとの互換性を保持するために、PostgreSQLでは、カーソルの問い合わせ計画が単純であり、そのサポートに余計なオーバーヘッドが必要ない場合、 SCROLLなしでも逆方向にデータを取り出すことができます。
しかし、SCROLLを付けなくても逆方向にデータが取り出せることを利用してアプリケーションを開発するのはお勧めしません。
NO SCROLLを指定した場合は、どのような場合でも逆方向に取り出すことはできません。
また、問い合わせがFOR UPDATEまたはFOR SHAREを含む場合は、逆方向の取り出しは許されません。
このためこの場合はSCROLLを指定することはできません。
スクロール可能なカーソルが揮発関数(38.7参照)を含む場合、想定しない結果をもたらす可能性があります。
これまで取り出した行を再度取り出した時、関数は再実行される可能性があり、この場合おそらく初回と異なる結果をもたらします。
揮発関数を含む問い合わせに対してはNO SCROLLを指定するのが最善です。
それが現実的でないのなら、回避方法の1つは、カーソルをWITH HOLDと宣言し、そこから何か行を読み取る前にトランザクションをコミットすることです。
これにより強制的にカーソルの出力全体が一時領域に具現化され、揮発関数は各行に対して厳密に1度だけ実行されます。
カーソルの問い合わせがFOR UPDATEまたはFOR SHAREを含む場合、このオプションを持つ通常のSELECTコマンドと同様、返される行は取り出した時点でロックされます。
さらに、返される行はもっとも最新のバージョンになります。
カーソルをUPDATE ... WHERE CURRENT OFまたはDELETE ... WHERE CURRENT OFで使用するつもりならば、FOR UPDATEの使用を通常勧めます。
FOR UPDATEを使用することで、取り出してから更新されるまでの間に他のセッションが行を変更することを防止します。
FOR UPDATEがなければ、カーソル作成後に行が変更された場合に後に行うWHERE CURRENT OFコマンドは効果がなくなります。
FOR UPDATEを使用する他の理由は、「簡単に更新可能」にするためにカーソル問い合わせが標準SQLに合わない場合(具体的にはカーソルは1つのテーブルのみを参照しなければならず、また、グループ化やORDER BYを使用してはならない)、これがないと後に実行されるWHERE CURRENT OFが失敗するかもしれないことです。
計画選択の詳細によっては、簡単に更新可能でないカーソルは動作するかもしれませんし、動作しないかもしれません。
このため最悪の場合、アプリケーションは試験時に動作するが、運用時に失敗するかもしれません。
FOR UPDATEが指定されていれば、カーソルは更新可能であることが保証されています。
FOR UPDATEをWHERE CURRENT OFといっしょに使用しない大きな理由は、カーソルをスクロール可能にする必要がある、または同時並行の更新から隔離する(つまり古いデータを表示し続けるようにする)必要がある場合のためです。
これが必要ならば、上記の警告に十分注意してください。
標準SQLでは、組み込みSQLにおけるカーソルのみが規定されています。
PostgreSQLサーバはカーソル用のOPEN文を実装していません。
カーソルは宣言された時に開いたものとみなされています。
しかし、PostgreSQL用の埋め込みSQLプリプロセッサであるECPGでは、DECLAREとOPEN文などを含め、標準SQLのカーソル規定をサポートしています。
開いたカーソルの基礎となるサーバデータ構造はポータルと呼ばれます。
ポータル名はクライアントプロトコルで公開されます。クライアントは、ポータル名を知っていれば、開いたポータルから直接行を取り出すことができます。
DECLAREを使用してカーソルを作成する場合、ポータル名はカーソル名と同じです。
pg_cursorsシステムビューを問い合わせることで、利用可能なすべてのカーソルを確認することができます。
標準SQLでは、カーソルを埋め込みSQL内とモジュール内でのみ使用できます。 PostgreSQLでは、対話式にカーソルを使うことができます。
標準SQLに従えば、UPDATE ... WHERE CURRENT OFとDELETE ... WHERE CURRENT OF文によりinsensitiveカーソルで行なわれた変更は、同じカーソルでは可視です。
PostgreSQLは、これらの文をその他のデータを変更する文すべてと同様に扱い、insensitiveカーソルでは変更は可視ではありません。
バイナリカーソルはPostgreSQLの拡張です。