web-dev-qa-db-ja.com

PostgreSQLの既存のテーブルでRETURNS TABLEを使用する方法

PostgreSQLから ドキュメントはこちら

関数をセットを返すものとして宣言するには、構文RETURNS TABLE(columns)を使用する別の方法があります。 ...この表記は、SQL標準の最近のバージョンで指定されているため、SETOFを使用するよりも移植性が高い場合があります。

これは、_RETURNS TABLE_が複数の行を返す新しい、よりポータブルなスタイルであるかのように聞こえます。しかし、2つの構文が同等であるかどうかはわかりません。

実際に_RETURNS TABLE_ toreplace_RETURNS SETOF_を使用できるかどうか疑問に思っていました。

特に、私が理解していない1つのケースは、既存のテーブルfooとそれに関連する複合型がある場合、どのように_RETURNS TABLE_で使用できるかです。

上記のリンクの例を使用すると、_RETURNS TABLE_を使用して以下を書き換えることができます。

_CREATE TABLE foo (fooid int, foosubid int, fooname text);
CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
_

これまでのところ、機能しないRETURNS TABLE (foo.*)およびRETURNS TABLE (foo)を使用しようとしました。

4
tinlyx

PS:申し訳ありませんが、私は複雑なコードを開発していて、「テーブルの再起動」の部分に対するPostgreSQLの愚かな制限と思われる小さなエラーが発生しました...集中して解決するのではなく、インターネットを使用しました(検索エンジンは私をここに置いた)。現在、このwiki回答は、検索エンジンから呼び出され、質問のタイトルに惹かれ、他の読者を支援するためのものです。

@dezsoのおかげで(正解でした)、すべての読者にお願いしますこの質問を編集して教訓的にすることができます。Wikiです。


PostgreSQL-v8以来、私たちはそれを行うことができます! EXISTING_TABLE_NAMEを返品できます

そのガイドでは、すべてのPostgreSQLバージョンの pg v8以降 から 現在のバージョン まで、すべてのセクションに「テーブルソースとしてのSQL関数」という名前が付いています。いくつかの簡略化を行って、ガイドの例を再現してみましょう。

CREATE TABLE foo (fooid int, foosubid int, fooname text);
INSERT INTO foo VALUES (1, 1, 'Joe'), (1, 2, 'Ed'), (2, 1, 'Mary');

CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;

SELECT * FROM getfoo(1);

さすがに走っていて、バッチリです!

 fooid | foosubid | fooname
-------+----------+---------
     1 |        1 | Joe
     1 |        2 | Ed

「PostgreSQLの既存のテーブルでRETURNS TABLEを使用する方法」という質問pg v8以来良い答えがあります...これは、過去15年間のやり方です構文は次のとおりです。
RETURNS SETOF <EXISTING_TABLE_NAME>

返すための瞬時のCREATE TABLEとして句TABLEを使用します

彼の質問で説明されている@tinlyxの混乱は、TABLEではなくSETOF句の使用についてです...「PostgreSQL構文ロジック」を使用して考えるには、まずRETURN <EXISTING_TABLE_NAME>を覚えておく必要がありますも有効で、RETURN <EXISTING_TYPE_NAME>と同じ動作をします。 1行だけを返すのが自然です。

次のステップでは、CREATE TABLE句()を使用してタプルを宣言していることを思い出してください。したがって、「インスタント定義タプルテーブル」を表現するための適切な構文はRETURN TABLE()であり、TABLE -typeを返すことは理にかなっています。配列型のようで、いくつかのインスタンスを返します(TABLEはタプルのセットです)。

次のステップでは、CREATE TABLE (<Tuple_description>)句を使用して Tuple を宣言しているため、「瞬間的なテーブル定義」を表現するための適切な構文はRETURN TABLE (<Tuple_description>)です。そして、配列タイプのようなテーブルタイプを返すことは理にかなっています、それらは複数のインスタンスを返します(テーブルはタプルのセットです)。

PostgreSQLの「現代的なもの」(!)は、@ ZiggyCrueltyfreeZeitgeisterが示したRETURNS TABLE (LIKE <table_name>)構文です。

CREATE FUNCTION getfoo2(int) RETURNS TABLE (LIKE foo) AS $$ -- working fine!
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
SELECT * FROM getfoo2(1); -- same result as getfoo(1)

同じことをする多くの方法、要約:

テーブル名(2つの方法)または型名を明示する:

  • RETURNS SETOF <table_name>(古くても良い)
  • RETURNS TABLE (LIKE <table_name>)(モダン)
  • RETURNS SETOF <type_name>CREATE TYPE <type_name> (<Tuple_description>)の後)

匿名型による暗黙的/汎用的な方法:

  • RETURNS SETOF RECORD(一般的ですが、問題があります)
  • (何か存在しますか?)RETURNS SETOF ROW?

瞬時のテーブル定義:

  • RETURNS TABLE (<Tuple_description>)
  • RETURNSなし)パラメータリストでOUTを使用します。

最後のケースでは、例を使用して説明します。
CREATE FUNCTION getfoo(int, OUT fooid int, OUT foosubid int, OUT fooname text)

動的および/または多形入力の場合は、 この説明を確認 する必要があります。

ベストプラクティス?

同じことをする方法はたくさんあるので、「ベストな方法」はありますか?

構文として、私はTABLEの使用を好みます。これは明示的です。「暗黙のRECORD」との混乱、非互換性の恐れはありません...しかし、基本はライブラリ管理にあります(テーブル名を使用する場合)たとえば、DELETE TABLE foo CASCADEを実行すると(テストしてください)、関数も削除されます。

1
Peter Krauss

異なるモードは状況によっては交換可能ですが、異なります。 _RETURNS TABLE_のメリットは、上記の引用から削除した文で説明されています。

これは、1つ以上のOUTパラメーターを使用し、関数にSETOFレコード(または必要に応じて単一の出力パラメーターのタイプをSETOF)を返すようにマークを付けることと同じです。

つまり、_CREATE FUNCTION ... RETURNS TABLE_は、カスタムの戻り値の型を指定することを目的としています。つまり、CREATE TYPE xxx_t AS ([fields...,]); CREATE FUNCTION xxx ... RETURNS SETOF xxx_t、およびCREATE FUNCTION xxx ([in params...,] out [fields...,]) RETURNS SETOF RECORDと同等です。

つまり、関数は他のテーブルタイプのテーブルを返すことができません。そのためには、直接__RETURNS SETOF_を使用してください(質問のスニペットで行ったように)。