web-dev-qa-db-ja.com

SELECTを使用したSQL関数とRETURN QUERY SELECTを使用したPLPGSQL関数?

SQLクエリを実行するプレーンSQL関数の間に違いはありますか?

create function get_sports() returns setof sport as
$body$
    select * from sport;
$body$
language sql stable;

そして、同じSQLクエリを返すPLPGSQL関数:

create function get_sports() returns setof sport as
$body$
begin
    return query select * from sport;
end
$body$
language plpgsql stable;

パフォーマンスに関して?どのバージョンでどのバージョンを使用する必要がありますか?

そして、引数を渡した場合、それは何かを変更しますか?といった:

create function get_sports(status int) returns setof sport as
$body$
    select * from sport where status = $1;
$body$
language sql stable;

create function get_sports(status int) returns setof sport as
$body$
begin
    return query select * from sport where status = $1;
end
$body$
language plpgsql stable;
5
Katrin

さまざまな微妙な違いがあります。

単純なSQL関数は、外部クエリにネストされている場合、 インライン化 にすることができます-それらがいくつかの前提条件を満たす場合。 PL/pgSQL関数では不可能です。

同じSQL関数内のすべてのステートメントは呼び出し時に一度に計画されますが、PL/pgSQL関数はネストされたSQL DMLステートメントを準備済みステートメントのように扱います-初めて実行されるときのみそれぞれを計画し、場合によってはクエリ計画を保存しますセッション。これは、動作とパフォーマンスに影響を与えるmajorの違いです。

たとえば、(一時)テーブルを作成して後で同じSQL関数で使用することはできません。これは、後のステートメントを計画するために呼び出し時に存在する必要があるためです。そのためにはPL/pgSQLが必要です。

到達せず、計画も実行もされていないPL/pgSQL関数のコードブランチは、最終的に実行されるまで、未検出のバグを抱えている可能性があります。 PL/pgSQL関数は、作成時に表面的にのみテストされます。

また、SQL関数はlastクエリの出力のみを返します。 マニュアル:

SQL関数がSETOFsometypeを返すように宣言されている場合、関数の最後のクエリが最後まで実行され、出力する各行が結果セットの要素として返されます。

大胆な強調鉱山。 (UNIONALL)を使用して、複数のクエリ結果を組み合わせることができます。)

RETURN QUERY一方、は結果に追加され複数回呼び出すことができますマニュアル:

RETURN NEXTおよびRETURN QUERY実際に関数から返らない—関数の結果セットに0個以上の行を追加するだけです。その後、PL/pgSQL関数の次のステートメントから実行が続行されます。連続RETURN NEXTまたはRETURN QUERYコマンドが実行され、結果セットが作成されます。引数をとらない最後のRETURNは、制御を関数から終了させます(または、制御を関数の最後に到達させることができます)。

関連:

argumentsを渡すことは、どちらのPLでもほとんど同じように機能します。 (以前はoldバージョンに多くの違いがありました。SQL関数はパラメーター名を参照できませんでしたが、それは歴史です。)

他にも、多かれ少なかれ微妙な違いがあります。見る:

6