本節および次節では、明示的にPL/pgSQLで解釈される、全ての種類の文について説明します。これらの種類の文として認められないものは全て、SQLコマンドであると仮定され、項40.5.2および項40.5.3において記述したように、メインデータベースエンジンに送信され実行されます。値をPL/pgSQL変数に代入する場合は以下のように記述します。SQLコマンドによって評価されます。(変数が行変数またはレコード変数の場合は行値となるかもしれません)。対象の変数は単純な変数(ブロック名で修飾可能)、行変数またはレコード変数のフィールド、または単純な変数またはフィールドとなる配列要素とすることができます。PL/pgSQLインタプリタによって、結果の型の出力関数と変数の型の入力関数を使用して暗黙的に変換されます。これにより、結果値の文字列形式を入力関数で受け付けることができない場合に、入力関数において実行時エラーが発生する可能性があることに注意してください。RETURNING句のないINSERTのように、行を返さない任意のSQLのコマンドについては、単にそのコマンドを記述することによってPL/pgSQL関数の内部でコマンドを実行できます。コマンドテキストに現れる全てのPL/pgSQL変数名は、パラメータとして扱われます。その後、実行時のパラメータ値として、その時点の変数値が提供されます。これは以前に述べた式に関する処理と同じです。項40.10.1を参照してください。SQLコマンドがこのように実行されると、項40.10.2に記述したように、PL/pgSQLはコマンドのために、実行計画をキャッシュして再利用します。式またはSELECT問い合わせを評価して結果を破棄することが、役に立つ場合があります。関数の呼び出しにおいて、副次的な成果を取得できるが、結果は無用である場合です。このような時PL/pgSQLでは、PERFORM文を使用してください。query;これはqueryを実行し、その結果を破棄します。SQLのSELECT文と同じ方法でqueryを記述しますが、最初のキーワードSELECTをPERFORMに置き換えてください。使用して、問い合わせをカッコ内に配置してください。(この場合、問い合わせは1行だけ返すことができます。結果を返さないコマンドと同様に、PL/pgSQL変数は問い合わせ内に置き換えられ、計画は同様にキャッシュされます。特殊な変数であるFOUNDは問い合わせ結果が1行でも生成された場合は真に設定され、生成されない場合は偽に設定されます(項40.5.5を参照してください)。SELECTを記述すれば、この結果を得ることができると考えるかもしれませんが、現時点でこれを行う方法はPERFORMしかありません。SELECTのように行を返すSQLコマンドは、エラーとして拒絶されます。INTO句を有する時は例外であり、次節で説明します。1行の結果を返す問い合わせの実行(多分、複数列の)1行を返すSQLコマンドの結果は、レコード変数、行型の変数、スカラ変数のリストに代入することができます。これは、基本的なSQLコマンドを記述して、それにINTO句を追加することによって行われます。target;ここで、targetはレコード変数、行変数、あるいは、単純な変数とレコード/行変数のフィールドをカンマで区切ったリストです。PL/pgSQL変数により残りの問い合わせが置換され、行を返さないコマンドにおいて述べたように計画がキャッシュされます。このように作動するのは、RETURNINGを伴ったINSERT/UPDATE/DELETEとSELECTおよび行セットの結果を返すユーティリティコマンド(例えば、EXPLAIN)です。INTO句以外では、SQLコマンドはPL/pgSQLの外部に記述したものと同じです。INTO文では、INTOの対象は新しく作成されるテーブルです。INTOを伴ったSELECTでは、この解釈が通常と大きく異なることに注意してください。SELECT構文を使用してください。行または変数リストが対象に使用された場合、列数とデータ型において問い合わせの結果と対象の構造が正確に一致しなければなりません。ないと、実行時エラーが発生します。レコード変数が対象の場合は、問い合わせ結果の列の行型に自身を自動的に設定します。INTO句はSQLコマンドのほとんど任意の場所に記述することができます。習慣的には、SELECT文においてはselect_expressionsの直前または直後に、他のコマンドにおいては文の終わりに記述されます。将来のバージョンでPL/pgSQLのパーサがより厳格になる場合に備えて、この習慣に従うことを推奨します。INTO句においてSTRICTが指定されない場合、targetは問い合わせが返す最初の行となり、行を返さない時はNULLとなります。BYを使用しないと定義できないことに注意してください。2行目以降の行の結果は、全て破棄されます。以下のように、特殊なFOUND変数(項40.5.5を参照してください)を調べて、行が返されたかどうかを検査することができます。IF;STRICTオプションが指定された場合、問い合わせは正確に1行を返さなければなりません。ないと、行がない時はNO_DATA_FOUND、2行以上が返った時はTOO_MANY_ROWSという実行時エラーが生じます。エラーを捕捉したい時は、例外ブロックを使用できます。myname;END;STRICTを指定したコマンドが成功すると、FOUND変数は常に真に設定されます。STRICTが指定されない場合でも、RETURNINGを伴ったINSERT/UPDATE/DELETEが2行以上を返した時は、エラーとなります。BYのようなオプションが存在しないからです。INTOおよび関連した文に対応します。SQLの問い合わせが返す複数行の結果を処理したい場合は、項40.6.4を参照してください。動的コマンドの実行PL/pgSQL関数の内部で、動的コマンド、つまり実行する度に別のテーブルや別のデータ型を使用するコマンドを生成したいということがよくあるでしょう。PL/pgSQLが通常行うコマンドの計画のキャッシュは(項40.10.2で述べたように)このような状況では動作しません。この種の問題を扱うために、以下のEXECUTE文が用意されています。];ここで、command-stringは実行されるコマンドを含む(text型の)文字列を生成する式です。オプションのtargetはレコード変数、行変数、あるいは、単純な変数とレコード/行変数のフィールドをカンマで区切ったリストで、その中にコマンドの結果が格納されます。コマンドに挿入される値を与えます。PL/pgSQL変数は、この演算用のコマンド文字列へ置換されません。必要な変数の値はすべてコマンド文字列を作成する時に埋め込まなければなりません。以下に説明するパラメータを使用することもできます。EXECUTEを介して実行されるコマンド計画をキャッシュすることはありません。代わりに、コマンドは文が実行されるとき常に計画されます。したがって、異なるテーブルと列に対する操作を実行できるように、コマンド文字列を関数内部で動的に作成することができます。INTO句は、行を返すSQLコマンドの結果を代入するべき場所を指定します。(レコード変数が使用される時、自動的に結果の構造と一致するように自身を構築させます)。複数の行が返された時、最初の行だけがINTO変数に代入されます。INTO変数に代入されます。INTO句が指定されない時、問い合わせの結果は捨てられます。STRICTオプションが指定された時、問い合わせの結果が正確に1行の場合を除き、エラーとなります。コマンド文字列はパラメータ値を使用可能で、それらは$1、$2等としてコマンドの中で参照されます。これらの記号はUSINGで与えられる値を参照します。この方式はデータの値をテキストとしてコマンド文字列の中に挿入する際、よく好まれます。それは値をテキストに変換、そしてその逆を行う場合の実行時オーバーヘッドを防止するとともに、引用符付けするとか、エスケープをする必要がないため、SQLインジェクション攻撃に対してより襲われにくくなります。checked_date;パラメータ記号はデータ値のみ使用可能です。動的に決定されるテーブルや列名を使用したい場合、テキストでコマンド文字列にそれらを挿入する必要があります。先行する問い合わせが、動的に選択されたテーブルに対して処理される必要がある時は、次のようにします。checked_date;他にもパラメータ記号はSELECT、INSERT、UPDATE、DELETEコマンドでしか動作しない、という制限があります。他の種類の文(一般的にユーティリティ文と呼ばれます)では、単なるデータ値であったとしてもテキストの値として埋め込まなければなりません。最初の例のように、単純な定数コマンドとUSINGパラメータを使ったEXECUTEは、コマンドを直接PL/pgSQLで書いて、PL/pgSQL変数を自動的に置換したものと機能的に同じです。重要な差異として、EXECUTEが現在のパラメータ値に特化した計画を生成し、コマンドを実行する度に計画を再作成することです。PL/pgSQLはその他に一般的な計画を作成し、再使用に備えキャッシュします。最適な計画がパラメータ値に大きく依存する場合、一般的な計画が選択されないことを確保するために、EXECUTEの使用は助けになります。INTOはEXECUTEでは現在サポートされません。代わりに、普通のSELECTコマンドを実行し、EXECUTEの一部としてINTOを記述してください。EXECUTE文はPostgreSQLサーバでサポートされているEXECUTESQL文とは関連がありません。サーバのEXECUTE文はPL/pgSQL関数内で使用することはできません(使用する必要もありません)。動的問い合わせの中の値の引用符付け動的コマンドを使用する時、しばしばPL/pgSQLでは単一引用符をエスケープしなければなりません。関数本体における固定のテキストを引用符付けする推奨方法は、ドル引用符を使用する方法です。(ドル引用符を用いない旧式のコードを保有している場合は、項40.11.1の概要を参照することが、理解しやすいコードへの変換作業の手助けになります)。作成した問い合わせに挿入すべき動的な値は、それ自身の内部に引用符を含む可能性があるため、注意深い処理が必要です。以下に例を示します(ここでは関数にドル引用符を用いる方法を使用すると仮定しているので、引用符を二重化する必要はありません)。quote_literal(keyvalue);この例は、quote_identとquote_literal関数(項9.4を参照)の使用方法を示しています。安全のため、列またはテーブル識別子を含む式は動的問い合わせに挿入する前にquote_identを介して渡されなくてはなりません。組み立てられるコマンドの中のリテラル文字列となるはずの値を含む式は、quote_literalを介して渡されなければなりません。これらの関数は、すべての特殊文字を適切にエスケープして埋め込んだ、二重引用符または単一引用符で囲まれた入力テキストを返すために、適切な手順を踏みます。quote_literalはSTRICTラベル付けされているため、NULL引数で呼び出された場合、常にNULLを返します。上記の例で、newvalueまたはkeyvalueがNULLの場合、動的問合せ文字列全体がNULLとなり、EXECUTEからのエラーを導きます。quote_nullable関数を使用することで、この問題を回避することができます。その動作は、NULL引数付きで呼び出された場合に文字列NULLを返すことを除いてquote_literalと同一です。quote_nullable(keyvalue);NULLの可能性のある値を処理するのであれば、通常quote_literalの代わりにquote_nullableを使用しなければなりません。いつものように、問い合わせの中のNULL値は意図しない結果を確実にもたらさないよう配慮をしなければなりません。次のようなWHERE句の結果はどうなるのでしょう。quote_nullable(keyvalue)これはkeyvalueがNULLである限り成功しません。その理由は、等価演算子=をNULLオペランドで使用するとその結果は常にNULLとなるからです。NULLを通常のキーの値と同じように動作させたい場合、上記を、以下のように書き換えなければなりません。FROMは=よりもより効率性が少なく扱われますので、必要に迫られた場合以外は行わないようにしてください。DISTINCTについての更なる情報は項9.2を参照してください。)ドル引用符は固定のテキストを引用符付けする場合のみ有用であるということに注意してください。この例を次のように記述するのは非常に悪い考えです。quote_literal(keyvalue);なぜなら、newvalueの内容がたまたま$$を含む時は、途中で次の処理へ移ってしまうからです。同様の不測事態は、ドル引用符の他の区切り文字を選んだ時も起こります。したがって、テキストの内容を把握していない時は、安全にテキストを引用符付けするために、quote_literal、quote_nullable、またはquote_ident関数を適切に使用しなければなりません。文はformat関数を使用しても安全に作成できます(項9.4参照)。keyvalue);format関数はUSING句と共に使用できます。keyvalue;この形式はさらに有効です。newvalueとkeyvalueパラメータは、テキスト型に変換されないからです。動的問い合わせとEXECUTEの長大な例は例40-9にあります。FUNCTIONコマンドを組み立て実行するものです。結果ステータスの取得コマンドの効果を判断するにはいくつか方法があります。DIAGNOSTICSを使用する方法です。];このコマンドによってシステムステータスインジケータを取り出すことができます。各itemは、指定された変数(これは受け取るために正しいデータ型でなければなりません)に代入されるステータス値を識別するキーワードです。現在使用可能なステータス項目は、SQLエンジンに送信された最終SQLコマンドにより処理された行数を示すROW_COUNT、および、最も最近のSQLコマンドにより挿入された最後の行のOIDを示すRESULT_OIDです。RESULT_OIDはOIDを保有するテーブルへのINSERTコマンドの後でのみ有意であることに注意してください。ROW_COUNT;コマンドの効果を判断する2番目の方法は、FOUNDというboolean型の特殊な変数を検査することです。PL/pgSQLの各関数呼び出しで使用される際、FOUNDは最初は偽に設定されています。以下のように、それぞれの文の種類によって設定が変更されます。INTO文は、行が代入された場合は真、返されなかった場合は偽をFOUNDに設定します。PERFORM文は、1つ以上の行が生成(破棄)された場合は真、まったく生成されなかった場合は偽をFOUNDに設定します。UPDATE、INSERT、およびDELETE文は、少なくとも1行が影響を受けた場合は真、まったく影響を受けなかった場合は偽をFOUNDに設定します。FETCH文は、行が返された場合は真、まったく返されなかった場合は偽をFOUNDに設定します。MOVE文は、カーソルの移動が成功したが場合は真、失敗した場合は偽をFOUNDに設定します。FOR文またはFOREACH文は、1回以上繰り返しが行われた場合は真、行われなかった場合は偽をFOUNDに設定します。FOUNDはループが終了した際、このように設定されます。ループ実行中はループ文によるFOUNDの変更はありません。ループ本体内の他種類の文を実行することによって、変更されるかもしれません。EXECUTE文は、問い合わせが行を1つでも返せば真、行が返されなければ偽を設定します。他のPL/pgSQL文はFOUNDの状態を変更しません。DIAGNOSTICSの出力を変更しますが、FOUNDを変更しないことに注意してください。FOUNDはそれぞれのPL/pgSQL関数内部のローカル変数です。FOUNDに対して行われた全ての変更は、現在の関数にのみ影響します。何もしない何もしないプレースホルダ文が有用になることがあります。IF/THEN/ELSE文の一部が空文であることを明示したい時です。このような目的にはNULL文を使用します。NULL;例えば、次の2つのコードは同等です。誤りを無視するEND;どちらが望ましいと思うかは、好みの問題です。OracleのPL/SQLでは無記述の文は許されませんので、こうした状況ではNULL文が必須です。PL/pgSQLでは無記述の文が許可されています。