バージョンごとのドキュメント一覧

43.5. 基本的な文 #

<title>Basic Statements</title>

In this section and the following ones, we describe all the statement types that are explicitly understood by <application>PL/pgSQL</application>. Anything not recognized as one of these statement types is presumed to be an SQL command and is sent to the main database engine to execute, as described in <xref linkend="plpgsql-statements-general-sql"/>. 本節および次節では、明示的にPL/pgSQLで解釈される、全ての種類の文について説明します。 これらの種類の文として認められないものはすべて、SQLコマンドであると仮定され、43.5.2において記述したように、メインデータベースエンジンに送信され実行されます。

43.5.1. 代入 #

<title>Assignment</title>

An assignment of a value to a <application>PL/pgSQL</application> variable is written as: 値をPL/pgSQL変数に代入する場合は以下のように記述します。

variable { := | = } expression;

As explained previously, the expression in such a statement is evaluated by means of an SQL <command>SELECT</command> command sent to the main database engine. The expression must yield a single value (possibly a row value, if the variable is a row or record variable). The target variable can be a simple variable (optionally qualified with a block name), a field of a row or record target, or an element or slice of an array target. Equal (<literal>=</literal>) can be used instead of PL/SQL-compliant <literal>:=</literal>. 上述した通り、このような文中にある式は、メインデータベースエンジンに送信されるSELECT SQLコマンドによって評価されます。 式は1つの値を生成しなければなりません (変数が行変数またはレコード変数の場合は行値となるかもしれません)。 対象の変数は単純な変数(ブロック名で修飾可能)、行またはレコードの対象のフィールド、または配列の対象の要素またはスライスとすることができます。 等号(=)がPL/SQLにおける代入記号(:=)の代わりに使用できます。

If the expression's result data type doesn't match the variable's data type, the value will be coerced as though by an assignment cast (see <xref linkend="typeconv-query"/>). If no assignment cast is known for the pair of data types involved, the <application>PL/pgSQL</application> interpreter will attempt to convert the result value textually, that is by applying the result type's output function followed by the variable type's input function. Note that this could result in run-time errors generated by the input function, if the string form of the result value is not acceptable to the input function. 式の結果データ型が変数のデータ型に一致しない場合、値は代入キャスト(10.4を参照)と同様に変換されます。 関係する二つのデータ型のための代入キャストが無いときには、PL/pgSQLインタプリタは結果値を、変数のデータ型の入力関数に続けて結果データ型の出力関数を適用することで、テキストとして変換しようとします。 結果値の文字列形式が入力関数で受け付けることができない場合に、入力関数において実行時エラーが発生するかもしれないことに注意してください。

Examples: 例:

tax := subtotal * 0.06;
my_record.user_id := 20;
my_array[j] := 20;
my_array[1:3] := array[1,2,3];
complex_array[n].realpart = 12.3;

43.5.2. SQLコマンドの実行 #

<title>Executing SQL Commands</title>

In general, any SQL command that does not return rows can be executed within a <application>PL/pgSQL</application> function just by writing the command. For example, you could create and fill a table by writing 一般に、行を返さないSQLコマンドはPL/pgSQL関数内にそのコマンドを書くだけで実行されます。 例えば、テーブルを作成してデータを入れるには以下のように書けます。

CREATE TABLE mytable (id int primary key, data text);
INSERT INTO mytable VALUES (1,'one'), (2,'two');

If the command does return rows (for example <command>SELECT</command>, or <command>INSERT</command>/<command>UPDATE</command>/<command>DELETE</command> with <literal>RETURNING</literal>), there are two ways to proceed. When the command will return at most one row, or you only care about the first row of output, write the command as usual but add an <literal>INTO</literal> clause to capture the output, as described in <xref linkend="plpgsql-statements-sql-onerow"/>. To process all of the output rows, write the command as the data source for a <command>FOR</command> loop, as described in <xref linkend="plpgsql-records-iterating"/>. コマンドが行を返すのであれば(例えばSELECTRETURNINGを伴うINSERT/UPDATE/DELETEなど)、処理する方法が2つあります。 コマンドが多くても1行を返す場合、もしくは出力の最初の行だけに関心がある場合には、43.5.3に書かれているように、出力を取得するためのINTO句を追加する以外は通常通りコマンドを書いてください。 出力行をすべて処理するためには、43.6.6に書かれているように、FORループに対するデータソースとしてコマンドを書いてください。

Usually it is not sufficient just to execute statically-defined SQL commands. Typically you'll want a command to use varying data values, or even to vary in more fundamental ways such as by using different table names at different times. Again, there are two ways to proceed depending on the situation. 通常、静的に定義されたSQLコマンドを実行するだけでは十分ではありません。 典型的には、可変のデータ値を使ったり、さらには異なる時には異なるテーブル名を使うなどより基本的な方法で変化したりするコマンドを使いたいでしょう。 今回も、状況に応じて2つの方法があります。

<application>PL/pgSQL</application> variable values can be automatically inserted into optimizable SQL commands, which are <command>SELECT</command>, <command>INSERT</command>, <command>UPDATE</command>, <command>DELETE</command>, <command>MERGE</command>, and certain utility commands that incorporate one of these, such as <command>EXPLAIN</command> and <command>CREATE TABLE ... AS SELECT</command>. In these commands, any <application>PL/pgSQL</application> variable name appearing in the command text is replaced by a query parameter, and then the current value of the variable is provided as the parameter value at run time. This is exactly like the processing described earlier for expressions; for details see <xref linkend="plpgsql-var-subst"/>. PL/pgSQL変数値は、最適化可能なSQLコマンドに自動的に挿入できます。最適化可能なSQLコマンドとは、SELECTINSERTUPDATEDELETEMERGEEXPLAINCREATE TABLE ... AS SELECTのようなこのうちの1つを含む特定のユーティリティコマンドのことです。 このコマンドでは、コマンドテキストに現れるすべてのPL/pgSQL変数名は、問い合わせパラメータで置き換えられ、その後、実行時のパラメータ値として、その時点の変数値が提供されます。 これは以前に述べた式に関する処理と全く同じです。詳細は43.11.1を参照してください。

When executing an optimizable SQL command in this way, <application>PL/pgSQL</application> may cache and re-use the execution plan for the command, as discussed in <xref linkend="plpgsql-plan-caching"/>. 最適化可能なSQLコマンドがこのように実行されると、43.11.2に記述したように、PL/pgSQLはコマンドのために、実行計画をキャッシュして再利用します。

Non-optimizable SQL commands (also called utility commands) are not capable of accepting query parameters. So automatic substitution of <application>PL/pgSQL</application> variables does not work in such commands. To include non-constant text in a utility command executed from <application>PL/pgSQL</application>, you must build the utility command as a string and then <command>EXECUTE</command> it, as discussed in <xref linkend="plpgsql-statements-executing-dyn"/>. 最適化可能ではないSQLコマンド(ユーティリティコマンドとも呼ばれます)は問い合わせパラメータを受け付けられません。 そのため、PL/pgSQL変数の自動置換はそのようなコマンド内では機能しません。 PL/pgSQLから実行されるユーティリティコマンドに不変ではないテキストを含めるには、43.5.4で述べたように、ユーティリティコマンドを文字列として構築し、それをEXECUTEしなければなりません。

<command>EXECUTE</command> must also be used if you want to modify the command in some other way than supplying a data value, for example by changing a table name. 例えば、テーブル名を変更するなど、データ値を提供する以外の方法でコマンドを修正したい場合にも、EXECUTEを使わなければなりません。

Sometimes it is useful to evaluate an expression or <command>SELECT</command> query but discard the result, for example when calling a function that has side-effects but no useful result value. To do this in <application>PL/pgSQL</application>, use the <command>PERFORM</command> statement: 式またはSELECT問い合わせを評価して結果を破棄することが、役に立つ場合があります。 例えば、関数の呼び出しにおいて、副次的な成果を取得できるが、結果は無用である場合です。 このような時PL/pgSQLでは、PERFORM文を使用してください。

PERFORM query;

This executes <replaceable>query</replaceable> and discards the result. Write the <replaceable>query</replaceable> the same way you would write an SQL <command>SELECT</command> command, but replace the initial keyword <command>SELECT</command> with <command>PERFORM</command>. For <command>WITH</command> queries, use <command>PERFORM</command> and then place the query in parentheses. (In this case, the query can only return one row.) <application>PL/pgSQL</application> variables will be substituted into the query just as described above, and the plan is cached in the same way. Also, the special variable <literal>FOUND</literal> is set to true if the query produced at least one row, or false if it produced no rows (see <xref linkend="plpgsql-statements-diagnostics"/>). これはqueryを実行し、その結果を破棄します。 SQLのSELECT文と同じ方法でqueryを記述しますが、最初のキーワードSELECTPERFORMに置き換えてください。 WITH問い合わせに対しては、PERFORM を使用して、問い合わせをカッコ内に配置してください。 (この場合、問い合わせは1行だけ返すことができます。) 上述のように、PL/pgSQL変数は問い合わせ内に置き換えられ、計画は同様にキャッシュされます。 また、特殊な変数であるFOUNDは問い合わせ結果が1行でも生成された場合は真に設定され、生成されない場合は偽に設定されます(43.5.5を参照してください)。

注記

One might expect that writing <command>SELECT</command> directly would accomplish this result, but at present the only accepted way to do it is <command>PERFORM</command>. An SQL command that can return rows, such as <command>SELECT</command>, will be rejected as an error unless it has an <literal>INTO</literal> clause as discussed in the next section. 直接SELECTを記述すれば、この結果を得ることができると考えるかもしれませんが、現時点でこれを行う方法はPERFORMしかありません。 SELECTのように行を返すSQLコマンドは、エラーとして拒絶されます。 なお、INTO句を有する時は例外であり、次節で説明します。

An example: 以下に例を示します。

PERFORM create_mv('cs_session_page_requests_mv', my_query);

43.5.3. 1行の結果を返すコマンドの実行 #

<title>Executing a Command with a Single-Row Result</title>

The result of an SQL command yielding a single row (possibly of multiple columns) can be assigned to a record variable, row-type variable, or list of scalar variables. This is done by writing the base SQL command and adding an <literal>INTO</literal> clause. For example, (多分、複数列の)1行を返すSQLコマンドの結果は、レコード変数、行型の変数、スカラ変数のリストに代入することができます。 これは、基本的なSQLコマンドを記述して、それにINTO句を追加することによって行われます。 以下に例を示します。

SELECT select_expressions INTO [STRICT] target FROM ...;
INSERT ... RETURNING expressions INTO [STRICT] target;
UPDATE ... RETURNING expressions INTO [STRICT] target;
DELETE ... RETURNING expressions INTO [STRICT] target;

where <replaceable>target</replaceable> can be a record variable, a row variable, or a comma-separated list of simple variables and record/row fields. <application>PL/pgSQL</application> variables will be substituted into the rest of the command (that is, everything but the <literal>INTO</literal> clause) just as described above, and the plan is cached in the same way. This works for <command>SELECT</command>, <command>INSERT</command>/<command>UPDATE</command>/<command>DELETE</command> with <literal>RETURNING</literal>, and certain utility commands that return row sets, such as <command>EXPLAIN</command>. Except for the <literal>INTO</literal> clause, the SQL command is the same as it would be written outside <application>PL/pgSQL</application>. ここで、targetはレコード変数、行変数、あるいは、単純な変数とレコード/行変数のフィールドをカンマで区切ったリストです。 上述のようにPL/pgSQL変数によりコマンドの残り(すなわち、INTO句以外のすべて)が置換され、同じように計画がキャッシュされます。 このように作動するのは、SELECTRETURNINGを伴ったINSERT/UPDATE/DELETEとおよびEXPLAINのような行セットの結果を返す特定のユーティリティコマンドです。 INTO句以外では、SQLコマンドはPL/pgSQLの外部に記述したものと同じです。

ヒント

Note that this interpretation of <command>SELECT</command> with <literal>INTO</literal> is quite different from <productname>PostgreSQL</productname>'s regular <command>SELECT INTO</command> command, wherein the <literal>INTO</literal> target is a newly created table. If you want to create a table from a <command>SELECT</command> result inside a <application>PL/pgSQL</application> function, use the syntax <command>CREATE TABLE ... AS SELECT</command>. 通常のPostgreSQLSELECT INTO文では、INTOの対象は新しく作成されるテーブルです。 しかし、INTOを伴ったSELECTでは、この解釈が通常と大きく異なることに注意してください。 PL/pgSQL関数内部でSELECTの結果からテーブルを作成したい場合は、CREATE TABLE ... AS SELECT構文を使用してください。

If a row variable or a variable list is used as target, the command's result columns must exactly match the structure of the target as to number and data types, or else a run-time error occurs. When a record variable is the target, it automatically configures itself to the row type of the command's result columns. 行変数または変数リストが対象に使用された場合、列数とデータ型においてコマンドの結果と対象の構造が正確に一致しなければなりません。 さもないと、実行時エラーが発生します。 レコード変数が対象の場合は、コマンドの結果の列の行型に自身を自動的に設定します。

The <literal>INTO</literal> clause can appear almost anywhere in the SQL command. Customarily it is written either just before or just after the list of <replaceable>select_expressions</replaceable> in a <command>SELECT</command> command, or at the end of the command for other command types. It is recommended that you follow this convention in case the <application>PL/pgSQL</application> parser becomes stricter in future versions. INTO句はSQLコマンドのほとんど任意の場所に記述することができます。 習慣的には、SELECT文においてはselect_expressionsの直前または直後に、他のコマンドにおいては文の終わりに記述されます。 将来のバージョンでPL/pgSQLのパーサがより厳格になる場合に備えて、この習慣に従うことを推奨します。

If <literal>STRICT</literal> is not specified in the <literal>INTO</literal> clause, then <replaceable>target</replaceable> will be set to the first row returned by the command, or to nulls if the command returned no rows. (Note that <quote>the first row</quote> is not well-defined unless you've used <literal>ORDER BY</literal>.) Any result rows after the first row are discarded. You can check the special <literal>FOUND</literal> variable (see <xref linkend="plpgsql-statements-diagnostics"/>) to determine whether a row was returned: INTO句においてSTRICTが指定されない場合、targetはコマンドが返す最初の行となり、コマンドが行を返さない時はNULLとなります。 (最初の行とはORDER BYを使用しないと定義できないことに注意してください。) 2行目以降の行の結果は、全て破棄されます。 以下のように、特殊なFOUND変数(43.5.5を参照してください)を調べて、行が返されたかどうかを検査することができます。

SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
    RAISE EXCEPTION 'employee % not found', myname;
END IF;

If the <literal>STRICT</literal> option is specified, the command must return exactly one row or a run-time error will be reported, either <literal>NO_DATA_FOUND</literal> (no rows) or <literal>TOO_MANY_ROWS</literal> (more than one row). You can use an exception block if you wish to catch the error, for example: STRICTオプションが指定された場合、コマンドは正確に1行を返さなければなりません。 さもないと、行がない時はNO_DATA_FOUND、2行以上が返った時はTOO_MANY_ROWSという実行時エラーが生じます。 エラーを捕捉したい時は、例外ブロックを使用できます。 以下に例を示します。

BEGIN
    SELECT * INTO STRICT myrec FROM emp WHERE empname = myname;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            RAISE EXCEPTION 'employee % not found', myname;
        WHEN TOO_MANY_ROWS THEN
            RAISE EXCEPTION 'employee % not unique', myname;
END;

Successful execution of a command with <literal>STRICT</literal> always sets <literal>FOUND</literal> to true. STRICTを指定したコマンドが成功すると、FOUND変数は常に真に設定されます。

For <command>INSERT</command>/<command>UPDATE</command>/<command>DELETE</command> with <literal>RETURNING</literal>, <application>PL/pgSQL</application> reports an error for more than one returned row, even when <literal>STRICT</literal> is not specified. This is because there is no option such as <literal>ORDER BY</literal> with which to determine which affected row should be returned. PL/pgSQLSTRICTが指定されない場合でも、RETURNINGを伴ったINSERT/UPDATE/DELETEが2行以上を返した時は、エラーとなります。 なぜなら、どの1行を返すか決定するORDER BYのようなオプションが存在しないからです。

If <literal>print_strict_params</literal> is enabled for the function, then when an error is thrown because the requirements of <literal>STRICT</literal> are not met, the <literal>DETAIL</literal> part of the error message will include information about the parameters passed to the command. You can change the <literal>print_strict_params</literal> setting for all functions by setting <varname>plpgsql.print_strict_params</varname>, though only subsequent function compilations will be affected. You can also enable it on a per-function basis by using a compiler option, for example: print_strict_paramsが関数に利用可能であり、かつ要求がSTRICTでないためにエラーが発生した場合、エラーメッセージのDETAIL部分はコマンドに渡したパラメータに関する情報を含みます。 plpgsql.print_strict_paramsを指定することにより、全ての関数のprint_strict_params設定を変更できます。 しかし、変更後にコンパイルした関数にだけ有効です。 コンパイルオプションを使用すれば、個々の関数を基準とした設定変更もできます。 例を示します。

CREATE FUNCTION get_userid(username text) RETURNS int
AS $$
#print_strict_params on
DECLARE
userid int;
BEGIN
    SELECT users.userid INTO STRICT userid
        FROM users WHERE users.username = get_userid.username;
    RETURN userid;
END;
$$ LANGUAGE plpgsql;

On failure, this function might produce an error message such as 失敗したとき、この関数は次のようなエラーメッセージを生成します。

ERROR:  query returned no rows
DETAIL:  parameters: $1 = 'nosuchuser'
CONTEXT:  PL/pgSQL function get_userid(text) line 6 at SQL statement

注記

The <literal>STRICT</literal> option matches the behavior of Oracle PL/SQL's <command>SELECT INTO</command> and related statements. STRICTオプションは、OracleのPL/SQLのSELECT INTOおよび関連した文に対応します。

43.5.4. 動的コマンドの実行 #

<title>Executing Dynamic Commands</title>

Oftentimes you will want to generate dynamic commands inside your <application>PL/pgSQL</application> functions, that is, commands that will involve different tables or different data types each time they are executed. <application>PL/pgSQL</application>'s normal attempts to cache plans for commands (as discussed in <xref linkend="plpgsql-plan-caching"/>) will not work in such scenarios. To handle this sort of problem, the <command>EXECUTE</command> statement is provided: PL/pgSQL関数の内部で、動的コマンド、つまり実行する度に別のテーブルや別のデータ型を使用するコマンドを生成したいということがよくあるでしょう。 PL/pgSQLが通常行うコマンドの計画のキャッシュは(43.11.2で述べたように)このような状況では動作しません。 この種の問題を扱うために、以下のEXECUTE文が用意されています。

EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ];

where <replaceable>command-string</replaceable> is an expression yielding a string (of type <type>text</type>) containing the command to be executed. The optional <replaceable>target</replaceable> is a record variable, a row variable, or a comma-separated list of simple variables and record/row fields, into which the results of the command will be stored. The optional <literal>USING</literal> expressions supply values to be inserted into the command. ここで、command-stringは実行されるコマンドを含む(text型の)文字列を生成する式です。 オプションのtargetはレコード変数、行変数、あるいは、単純な変数とレコード/行変数のフィールドをカンマで区切ったリストで、その中にコマンドの結果が格納されます。 オプションのUSING式は コマンドに挿入される値を与えます。

No substitution of <application>PL/pgSQL</application> variables is done on the computed command string. Any required variable values must be inserted in the command string as it is constructed; or you can use parameters as described below. PL/pgSQL変数は、この演算用のコマンド文字列へ置換されません。 必要な変数の値はすべてコマンド文字列を作成する時に埋め込まなければなりません。 もしくは、以下に説明するパラメータを使用することもできます。

Also, there is no plan caching for commands executed via <command>EXECUTE</command>. Instead, the command is always planned each time the statement is run. Thus the command string can be dynamically created within the function to perform actions on different tables and columns. また、EXECUTEを介して実行されるコマンド計画をキャッシュすることはありません。 代わりに、コマンドは文が実行されるとき常に計画されます。 したがって、異なるテーブルと列に対する操作を実行できるように、コマンド文字列を関数内部で動的に作成することができます。

The <literal>INTO</literal> clause specifies where the results of an SQL command returning rows should be assigned. If a row variable or variable list is provided, it must exactly match the structure of the command's results; if a record variable is provided, it will configure itself to match the result structure automatically. If multiple rows are returned, only the first will be assigned to the <literal>INTO</literal> variable(s). If no rows are returned, NULL is assigned to the <literal>INTO</literal> variable(s). If no <literal>INTO</literal> clause is specified, the command results are discarded. INTO句は、行を返すSQLコマンドの結果を代入するべき場所を指定します。 行変数または変数リストが用いられる時、それはコマンドの結果の構造と正確に一致しなければなりません。レコード変数が使用される時、自動的に結果の構造と一致するように自身を構築させます。 複数の行が返された時、最初の行だけがINTO変数に代入されます。 1行も返されない時、NULLがINTO変数に代入されます。 INTO句が指定されない時、コマンドの結果は捨てられます。

If the <literal>STRICT</literal> option is given, an error is reported unless the command produces exactly one row. STRICTオプションが指定された時、コマンドの結果が正確に1行の場合を除き、エラーとなります。

The command string can use parameter values, which are referenced in the command as <literal>$1</literal>, <literal>$2</literal>, etc. These symbols refer to values supplied in the <literal>USING</literal> clause. This method is often preferable to inserting data values into the command string as text: it avoids run-time overhead of converting the values to text and back, and it is much less prone to SQL-injection attacks since there is no need for quoting or escaping. An example is: コマンド文字列はパラメータ値を使用可能で、それらは$1$2等としてコマンドの中で参照されます。 これらの記号はUSINGで与えられる値を参照します。 この方式はデータの値をテキストとしてコマンド文字列の中に挿入する際、よく好まれます。 それは値をテキストに変換、そしてその逆を行う場合の実行時オーバーヘッドを防止するとともに、引用符付けするとか、エスケープをする必要がないため、SQLインジェクション攻撃に対してより襲われにくくなります。 以下に例を示します。

EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
   INTO c
   USING checked_user, checked_date;

Note that parameter symbols can only be used for data values &mdash; if you want to use dynamically determined table or column names, you must insert them into the command string textually. For example, if the preceding query needed to be done against a dynamically selected table, you could do this: パラメータ記号はデータ値のみ使用可能です。 もし動的に決定されるテーブルや列名を使用したい場合、テキストでコマンド文字列にそれらを挿入する必要があります。 例えば、先行する問い合わせが、動的に選択されたテーブルに対して処理される必要がある時は、次のようにします。

EXECUTE 'SELECT count(*) FROM '
    || quote_ident(tabname)
    || ' WHERE inserted_by = $1 AND inserted <= $2'
   INTO c
   USING checked_user, checked_date;

A cleaner approach is to use <function>format()</function>'s <literal>%I</literal> specification to insert table or column names with automatic quoting: よりきれいな方法は、format()%I指定を使い自動引用符付けされたテーブル名または列名を挿入することです。

EXECUTE format('SELECT count(*) FROM %I '
   'WHERE inserted_by = $1 AND inserted <= $2', tabname)
   INTO c
   USING checked_user, checked_date;

(This example relies on the SQL rule that string literals separated by a newline are implicitly concatenated.) (この例は、改行により分割された文字列リテラルが暗黙に連結されるというSQL規則に依存しています。)

Another restriction on parameter symbols is that they only work in optimizable SQL commands (<command>SELECT</command>, <command>INSERT</command>, <command>UPDATE</command>, <command>DELETE</command>, <command>MERGE</command>, and certain commands containing one of these). In other statement types (generically called utility statements), you must insert values textually even if they are just data values. 他にもパラメータ記号は最適化可能なSQLコマンド(SELECTINSERTUPDATEDELETEMERGE、およびこのうちの1つを含む特定のコマンド)でしか動作しない、という制限があります。 他の種類の文(一般的にユーティリティ文と呼ばれます)では、単なるデータ値であったとしてもテキストの値として埋め込まなければなりません。

An <command>EXECUTE</command> with a simple constant command string and some <literal>USING</literal> parameters, as in the first example above, is functionally equivalent to just writing the command directly in <application>PL/pgSQL</application> and allowing replacement of <application>PL/pgSQL</application> variables to happen automatically. The important difference is that <command>EXECUTE</command> will re-plan the command on each execution, generating a plan that is specific to the current parameter values; whereas <application>PL/pgSQL</application> may otherwise create a generic plan and cache it for re-use. In situations where the best plan depends strongly on the parameter values, it can be helpful to use <command>EXECUTE</command> to positively ensure that a generic plan is not selected. 最初の例のように、単純な定数コマンドとUSINGパラメータを使ったEXECUTEは、コマンドを直接PL/pgSQLで書いて、PL/pgSQL変数を自動的に置換したものと機能的に同じです。 重要な差異として、EXECUTEが現在のパラメータ値に特化した計画を生成し、コマンドを実行する度に計画を再作成することです。 一方、PL/pgSQLはその他に汎用的な計画を作成し、再使用に備えキャッシュします。 最適な計画がパラメータ値に大きく依存する場合、汎用的な計画が選択されないことを確保するために、EXECUTEの使用は助けになります。

<command>SELECT INTO</command> is not currently supported within <command>EXECUTE</command>; instead, execute a plain <command>SELECT</command> command and specify <literal>INTO</literal> as part of the <command>EXECUTE</command> itself. SELECT INTOEXECUTEでは現在サポートされません。 代わりに、普通のSELECTコマンドを実行し、EXECUTEの一部としてINTOを記述してください。

注記

The <application>PL/pgSQL</application> <command>EXECUTE</command> statement is not related to the <link linkend="sql-execute"><command>EXECUTE</command></link> SQL statement supported by the <productname>PostgreSQL</productname> server. The server's <command>EXECUTE</command> statement cannot be used directly within <application>PL/pgSQL</application> functions (and is not needed). PL/pgSQL EXECUTE文はPostgreSQLサーバでサポートされているEXECUTE SQL文とは関連がありません。 サーバのEXECUTE文はPL/pgSQL関数内で使用することはできません(使用する必要もありません)。

例43.1 動的問い合わせの中の値の引用符付け

<title>Quoting Values in Dynamic Queries</title>

When working with dynamic commands you will often have to handle escaping of single quotes. The recommended method for quoting fixed text in your function body is dollar quoting. (If you have legacy code that does not use dollar quoting, please refer to the overview in <xref linkend="plpgsql-quote-tips"/>, which can save you some effort when translating said code to a more reasonable scheme.) 動的コマンドを使用する時、しばしば単一引用符をエスケープしなければなりません。 関数本体における固定のテキストを引用符付けする推奨方法は、ドル引用符を使用する方法です。 (ドル引用符を用いない旧式のコードを保有している場合は、43.12.1の概要を参照することが、理解しやすいコードへの変換作業の手助けになります)。

Dynamic values require careful handling since they might contain quote characters. An example using <function>format()</function> (this assumes that you are dollar quoting the function body so quote marks need not be doubled): 動的な値は引用符を含んでいる可能性があるので注意深い取り扱いが必要です。 以下にformat()を使う例を示します(ここでは関数にドル引用符を用いる方法を使用すると仮定しているので、引用符を二重化する必要はありません)。

EXECUTE format('UPDATE tbl SET %I = $1 '
   'WHERE key = $2', colname) USING newvalue, keyvalue;

It is also possible to call the quoting functions directly: クオート関数を直接呼び出すことも可能です。

EXECUTE 'UPDATE tbl SET '
        || quote_ident(colname)
        || ' = '
        || quote_literal(newvalue)
        || ' WHERE key = '
        || quote_literal(keyvalue);

This example demonstrates the use of the <function>quote_ident</function> and <function>quote_literal</function> functions (see <xref linkend="functions-string"/>). For safety, expressions containing column or table identifiers should be passed through <function>quote_ident</function> before insertion in a dynamic query. Expressions containing values that should be literal strings in the constructed command should be passed through <function>quote_literal</function>. These functions take the appropriate steps to return the input text enclosed in double or single quotes respectively, with any embedded special characters properly escaped. この例は、quote_identquote_literal関数(9.4を参照)の使用方法を示しています。 安全のため、列またはテーブル識別子を含む式は動的問い合わせに挿入する前にquote_identを介して渡されなくてはなりません。 組み立てられるコマンドの中のリテラル文字列となるはずの値を含む式は、quote_literalを介して渡されなければなりません。 これらの関数は、すべての特殊文字を適切にエスケープして埋め込んだ、二重引用符または単一引用符で囲まれた入力テキストを返すために、適切な手順を踏みます。

Because <function>quote_literal</function> is labeled <literal>STRICT</literal>, it will always return null when called with a null argument. In the above example, if <literal>newvalue</literal> or <literal>keyvalue</literal> were null, the entire dynamic query string would become null, leading to an error from <command>EXECUTE</command>. You can avoid this problem by using the <function>quote_nullable</function> function, which works the same as <function>quote_literal</function> except that when called with a null argument it returns the string <literal>NULL</literal>. For example, quote_literalSTRICTラベル付けされているため、NULL引数で呼び出された場合、常にNULLを返します。 上記の例で、newvalueまたはkeyvalueがNULLの場合、動的問合せ文字列全体がNULLとなり、EXECUTEからのエラーを導きます。 quote_nullable関数を使用することで、この問題を回避することができます。 その動作は、NULL引数付きで呼び出された場合に文字列NULLを返すことを除いてquote_literalと同一です。 以下に例を示します。

EXECUTE 'UPDATE tbl SET '
        || quote_ident(colname)
        || ' = '
        || quote_nullable(newvalue)
        || ' WHERE key = '
        || quote_nullable(keyvalue);

If you are dealing with values that might be null, you should usually use <function>quote_nullable</function> in place of <function>quote_literal</function>. NULLの可能性のある値を処理するのであれば、通常quote_literalの代わりにquote_nullableを使用しなければなりません。

As always, care must be taken to ensure that null values in a query do not deliver unintended results. For example the <literal>WHERE</literal> clause いつものように、問い合わせの中のNULL値は意図しない結果を確実にもたらさないよう配慮をしなければなりません。 例えば次のようなWHERE句の結果はどうなるのでしょう。

'WHERE key = ' || quote_nullable(keyvalue)

will never succeed if <literal>keyvalue</literal> is null, because the result of using the equality operator <literal>=</literal> with a null operand is always null. If you wish null to work like an ordinary key value, you would need to rewrite the above as これはkeyvalueがNULLである限り成功しません。 その理由は、等価演算子=をNULLオペランドで使用するとその結果は常にNULLとなるからです。 NULLを通常のキーの値と同じように動作させたい場合、上記を、以下のように書き換えなければなりません。

'WHERE key IS NOT DISTINCT FROM ' || quote_nullable(keyvalue)

(At present, <literal>IS NOT DISTINCT FROM</literal> is handled much less efficiently than <literal>=</literal>, so don't do this unless you must. See <xref linkend="functions-comparison"/> for more information on nulls and <literal>IS DISTINCT</literal>.) (現時点では、IS NOT DISTINCT FROM=よりもより効率性が少なく扱われますので、必要に迫られた場合以外は行わないようにしてください。 NULLとIS DISTINCTについての更なる情報は9.2を参照してください。)

Note that dollar quoting is only useful for quoting fixed text. It would be a very bad idea to try to write this example as: ドル引用符は固定のテキストを引用符付けする場合のみ有用であるということに注意してください。 この例を次のように記述するのは非常に悪い考えです。

EXECUTE 'UPDATE tbl SET '
        || quote_ident(colname)
        || ' = $$'
        || newvalue
        || '$$ WHERE key = '
        || quote_literal(keyvalue);

because it would break if the contents of <literal>newvalue</literal> happened to contain <literal>$$</literal>. The same objection would apply to any other dollar-quoting delimiter you might pick. So, to safely quote text that is not known in advance, you <emphasis>must</emphasis> use <function>quote_literal</function>, <function>quote_nullable</function>, or <function>quote_ident</function>, as appropriate. なぜなら、newvalueの内容がたまたま$$を含む時は、途中で次の処理へ移ってしまうからです。 同様の不測事態は、ドル引用符の他の区切り文字を選んだ時も起こります。 したがって、テキストの内容を把握していない時は、安全にテキストを引用符付けするために、quote_literalquote_nullable、またはquote_ident関数を適切に使用しなければなりません

Dynamic SQL statements can also be safely constructed using the <function>format</function> function (see <xref linkend="functions-string-format"/>). For example: 動的なSQL文もformat関数(9.4.1を参照)を使って安全に作ることができます。例を示します。

EXECUTE format('UPDATE tbl SET %I = %L '
   'WHERE key = %L', colname, newvalue, keyvalue);

<literal>%I</literal> is equivalent to <function>quote_ident</function>, and <literal>%L</literal> is equivalent to <function>quote_nullable</function>. The <function>format</function> function can be used in conjunction with the <literal>USING</literal> clause: %Iquote_identと同等で、%Lquote_nullableと同等です。 format関数はUSING句と共に使用できます。

EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname)
   USING newvalue, keyvalue;

This form is better because the variables are handled in their native data type format, rather than unconditionally converting them to text and quoting them via <literal>%L</literal>. It is also more efficient. 変数が、無条件にテキストに変換されて%Lで引用符付けされることなく、固有のデータ形式で処理されるため、この形式はより優れています。


A much larger example of a dynamic command and <command>EXECUTE</command> can be seen in <xref linkend="plpgsql-porting-ex2"/>, which builds and executes a <command>CREATE FUNCTION</command> command to define a new function. 動的問い合わせとEXECUTEの長大な例は例 43.10にあります。 それは新しい関数を定義するためにCREATE FUNCTIONコマンドを組み立て実行するものです。

43.5.5. 結果ステータスの取得 #

<title>Obtaining the Result Status</title>

There are several ways to determine the effect of a command. The first method is to use the <command>GET DIAGNOSTICS</command> command, which has the form: コマンドの効果を判断するにはいくつか方法があります。 最初の方法は以下のような形式のGET DIAGNOSTICSを使用する方法です。

GET [ CURRENT ] DIAGNOSTICS variable { = | := } item [ , ... ];

This command allows retrieval of system status indicators. <literal>CURRENT</literal> is a noise word (but see also <command>GET STACKED DIAGNOSTICS</command> in <xref linkend="plpgsql-exception-diagnostics"/>). Each <replaceable>item</replaceable> is a key word identifying a status value to be assigned to the specified <replaceable>variable</replaceable> (which should be of the right data type to receive it). The currently available status items are shown in <xref linkend="plpgsql-current-diagnostics-values"/>. Colon-equal (<literal>:=</literal>) can be used instead of the SQL-standard <literal>=</literal> token. An example: このコマンドによってシステムステータスインジケータを取り出すことができます。 CURRENTは無意味な単語です(しかし43.6.8.1GET STACKED DIAGNOSTICSも参照してください)。 各itemは、指定されたvariable(これは受け取るために正しいデータ型でなければなりません)に代入されるステータス値を識別するキーワードです。 現在使用可能なステータス項目は、表 43.1で示されています。 代入記号(:=)が標準SQLにおける等号(=)の代わりに使用できます。 以下に例を示します。

GET DIAGNOSTICS integer_var = ROW_COUNT;

表43.1 使用できるステータス項目

<title>Available Diagnostics Items</title>
名前説明
ROW_COUNTbigint最後のSQLコマンドにより処理された行数
PG_CONTEXTtext現在の呼び出しスタックを記述したテキストの行 (43.6.9を参照)
PG_ROUTINE_OIDoid現在の関数のOID

The second method to determine the effects of a command is to check the special variable named <literal>FOUND</literal>, which is of type <type>boolean</type>. <literal>FOUND</literal> starts out false within each <application>PL/pgSQL</application> function call. It is set by each of the following types of statements: コマンドの効果を判断する2番目の方法は、FOUNDというboolean型の特殊な変数を検査することです。 PL/pgSQLの各関数呼び出しで使用される際、FOUNDは最初は偽に設定されています。 以下のように、それぞれの文の種類によって設定が変更されます。

  • A <command>SELECT INTO</command> statement sets <literal>FOUND</literal> true if a row is assigned, false if no row is returned. SELECT INTO文は、行が代入された場合は真、返されなかった場合は偽をFOUNDに設定します。

  • A <command>PERFORM</command> statement sets <literal>FOUND</literal> true if it produces (and discards) one or more rows, false if no row is produced. PERFORM文は、1つ以上の行が生成(破棄)された場合は真、まったく生成されなかった場合は偽をFOUNDに設定します。

  • <command>UPDATE</command>, <command>INSERT</command>, <command>DELETE</command>, and <command>MERGE</command> statements set <literal>FOUND</literal> true if at least one row is affected, false if no row is affected. UPDATEINSERTDELETE、およびMERGE文は、少なくとも1行が影響を受けた場合は真、まったく影響を受けなかった場合は偽をFOUNDに設定します。

  • A <command>FETCH</command> statement sets <literal>FOUND</literal> true if it returns a row, false if no row is returned. FETCH文は、行が返された場合は真、まったく返されなかった場合は偽をFOUNDに設定します。

  • A <command>MOVE</command> statement sets <literal>FOUND</literal> true if it successfully repositions the cursor, false otherwise. MOVE文は、カーソルの移動が成功した場合は真、失敗した場合は偽をFOUNDに設定します。

  • A <command>FOR</command> or <command>FOREACH</command> statement sets <literal>FOUND</literal> true if it iterates one or more times, else false. <literal>FOUND</literal> is set this way when the loop exits; inside the execution of the loop, <literal>FOUND</literal> is not modified by the loop statement, although it might be changed by the execution of other statements within the loop body. FOR文またはFOREACH文は、1回以上繰り返しが行われた場合は真、行われなかった場合は偽をFOUNDに設定します。 FOUNDはループが終了した際、このように設定されます。 ループ実行中はループ文によるFOUNDの変更はありません。 ただし、ループ本体内の他種類の文を実行することによって、変更されるかもしれません。

  • <command>RETURN QUERY</command> and <command>RETURN QUERY EXECUTE</command> statements set <literal>FOUND</literal> true if the query returns at least one row, false if no row is returned. RETURN QUERYRETURN QUERY EXECUTE文は、問い合わせが行を1つでも返せば真、行が返されなければ偽をFOUNDに設定します。

Other <application>PL/pgSQL</application> statements do not change the state of <literal>FOUND</literal>. Note in particular that <command>EXECUTE</command> changes the output of <command>GET DIAGNOSTICS</command>, but does not change <literal>FOUND</literal>. 他のPL/pgSQL文はFOUNDの状態を変更しません。 特に、EXECUTEGET DIAGNOSTICSの出力を変更しますが、FOUNDを変更しないことに注意してください。

<literal>FOUND</literal> is a local variable within each <application>PL/pgSQL</application> function; any changes to it affect only the current function. FOUNDはそれぞれのPL/pgSQL関数内部のローカル変数です。 FOUNDに対して行われた全ての変更は、現在の関数にのみ影響します。

43.5.6. まったく何もしない #

<title>Doing Nothing At All</title>

Sometimes a placeholder statement that does nothing is useful. For example, it can indicate that one arm of an if/then/else chain is deliberately empty. For this purpose, use the <command>NULL</command> statement: 何もしないプレースホルダ文が有用になることがあります。 例えば、IF/THEN/ELSE文の一部が空文であることを明示したい時です。 このような目的にはNULL文を使用します。

NULL;

For example, the following two fragments of code are equivalent: 例えば、次の2つのコードは同等です。

BEGIN
    y := x / 0;
EXCEPTION
    WHEN division_by_zero THEN

        NULL;  &#45;- ignore the error

        NULL;  -- 誤りを無視する
END;

BEGIN
    y := x / 0;
EXCEPTION

    WHEN division_by_zero THEN  &#45;- ignore the error

    WHEN division_by_zero THEN  -- 誤りを無視する
END;

Which is preferable is a matter of taste. どちらが望ましいと思うかは、好みの問題です。

注記

In Oracle's PL/SQL, empty statement lists are not allowed, and so <command>NULL</command> statements are <emphasis>required</emphasis> for situations such as this. <application>PL/pgSQL</application> allows you to just write nothing, instead. OracleのPL/SQLでは無記述の文は許されませんので、こうした状況ではNULL文が必須です。 しかしPL/pgSQLでは無記述の文が許可されています。