web-dev-qa-db-ja.com

PostgreSQL関数における言語sqlと言語plpgsqlの違い

データベース開発は非常に新しいので、次の例に関して疑問があります:

関数f1()-language sql

_ create or replace function f1(istr  varchar) returns text as $$ 
 select 'hello! '::varchar || istr;
 $$ language sql;
_

関数f2()-language plpgsql

_ create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin select 'hello! '::varchar || istr; end;
 $$ language plpgsql;
_
  • 両方のfunctionsは、select f1('world')またはselect f2('world')のように呼び出すことができます。

  • select f1('world')を呼び出すと、outputは次のようになります。

    _`hello! world`
    _
  • select f2('world')の場合、output

    エラー:クエリには結果データの宛先がありませんヒント:SELECTの結果を破棄する場合は、代わりにPERFORMを使用します。 CONTEXT:PL/pgSQL関数f11(文字可変)SQLステートメントの行2 **​​***エラー**​​***

  • 違いと、どのような状況で_language sql_または_language plpgsql_を使用する必要があるかを知りたい。

機能に関する有用なリンクまたは回答は大歓迎です。

36
user3814846

SQL関数

より良い選択です:

  • 単純なスカラークエリの場合。計画する必要はありません。オーバーヘッドを節約してください。

  • セッションごとの単一(またはごく少数)の呼び出しの場合。 PL/pgSQLが提供する準備済みステートメントを介したプランキャッシングから得られるものは何もありません。下記参照。

  • 通常、より大きなクエリのコンテキストで呼び出され、 inlined になるほど単純な場合.

  • PL/pgSQLのような手続き型言語でexperienceがないため。多くの人がSQLをよく知っているので、SQL関数に必要なのはそれだけです。 PL/pgSQLについて同じことを言える人はほとんどいません。 (それはかなり簡単ですが。)

  • 少し短いコード。ブロックのオーバーヘッドはありません。

PL/pgSQL関数

より良い選択です:

  • SQLで利用できない手続き要素または変数が必要な場合機能、明らかに。

  • あらゆる種類のdynamic SQLで、ステートメントを動的に構築し、 EXECUTE を使用します。 SQLインジェクションを回避するには特別な注意が必要です。詳細:

  • computationsがあり、いくつかの場所とCTEでreused目的のために伸ばすことはできません。 SQL関数では、変数がなく、繰り返し計算するか、テーブルに書き込む必要があります。 dba.SEに関するこの関連する回答には、SQL関数/ plpgsql関数/クエリを使用して同じ問題を解決するためのサイドバイサイドコード例がありますCTE:

    割り当ては、他の手続き言語よりもいくぶん高価です。必要以上の割り当てを使用しないプログラミングスタイルを採用します。

  • 関数をインライン化できず、繰り返し呼び出される場合。 SQL関数とは異なり、 クエリプランは、PL/pgSQL関数内のすべてのSQLステートメントに対してキャッシュできます ;それらはprepared statementのように扱われ、同じセッション内で繰り返される呼び出しのためにプランがキャッシュされます(Postgresがキャッシュされた(汎用)プランがそれが、PL/pgSQL関数が通常より高速である理由です最初の後にそのような場合の呼び出しのカップル。

    これらの項目のいくつかについて議論するpgsql-performanceのスレッドは次のとおりです。
    Re:pl/pgsql関数はSQLのものよりも優れていますか?

  • エラーをトラップする必要がある場合

  • trigger procedure (これも単なる関数です)。

  • オブジェクトを変更したり、後続のコマンドに関連する方法でシステムカタログを変更したりするDDLステートメントを含める場合-SQL関数内のすべてのステートメントは一度に解析され、PL/pgSQL関数は各ステートメントを順番に計画および実行します(準備済みステートメントなど)。見る:

以下も検討してください。


PL/pgSQL関数から実際にreturnするには、次のように書くことができます:

CREATE FUNCTION f2(istr varchar)
  RETURNS text AS
$func$
BEGIN
   RETURN 'hello! ';  -- defaults to type text anyway
END
$func$ LANGUAGE plpgsql;

他の方法があります:

48

PL/PgSQLは、SQLに基づくPostgreSQL固有の手続き型言語です 。ループ、変数、エラー/例外処理などがあります。すべてのSQLが有効なPL/PgSQLであるわけではありません。たとえば、SELECTまたはRETURN QUERYなしではINTOを使用できません。 PL/PgSQLは、ワンショットプロシージャのDOブロックでも使用できます。

sql functions は純粋なSQLのみを使用できますが、多くの場合、より効率的で、BEGIN ... END;ブロックなどを必要としないため、記述が簡単です。SQL関数はインライン、PL/PgSQLには当てはまりません。

人々は手続き型の考え方に慣れているため、プレーンSQLで十分なPL/PgSQLをよく使用します。ほとんどの場合、PL/PgSQLが必要だと思うとき、おそらく実際には必要ありません。再帰的CTE、ラテラルクエリなどは、通常、ほとんどのニーズを満たします。

詳細については、マニュアルを参照してください。

15
Craig Ringer

戻り値として関数内に記述した選択クエリを作成します。

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin return(select 'hello! '::varchar || istr); end;
 $$ language plpgsql;
0
ZORRO_BLANCO