2016-04-19 13 views
1

postgres関数から異なるタイプのいくつかの結果セットを返すことは可能ですか?以下のようなPostgres関数:複数のテーブルを返す

何か:ユーザーのためのいくつかの電話が可能ですので、私は使用したくない

CREATE OR REPLACE FUNCTION getUserById() 
RETURNS setof ??? 
AS 
$$ 
BEGIN 

return query select id, name /* and other columns */ from users where id = 1; 
return query select id, phone_number from user_phones where user_id = 1 

END 
$$ 
LANGUAGE plpgsql; 

が参加します。また、カーソルの使用を避けることは素晴らしいことです。 MS SQLで可能であり、postgresでも同じことをしたいと思います。

+0

これはあなたの求めるものです。 http://stackoverflow.com/questions/756689/postgresql-function-returning-multiple-result-sets –

+1

@JanisS。これらの例には1つの違いがあります - すべてのソリューションは1つのタイプの複数のセットを返します。私の場合、私は2つの異なるデータ型を持っています。 – user1820686

答えて

1

シーク後、カーソルを使用するより良い解決策が見つかりませんでした。私はすでにこれを見ていると仮定します。https://blog.dsl-platform.com/multiple-result-sets-alternatives-in-postgres-3/

CREATE FUNCTION load_page(_session INT) RETURNS setof refcursor AS 
$$ 
DECLARE c_top_items refcursor; 
DECLARE c_shopping_cart refcursor; 
BEGIN 
    OPEN c_top_items FOR 
     SELECT t.name, t.description 
     FROM top_item t 
     ORDER BY t.popularity DESC 
     LIMIT 10; 
    RETURN NEXT c_top_items; 
    OPEN c_shopping_cart FOR 
     SELECT c.product_id, c.product_name, c.quantity 
     FROM shopping_cart c 
     WHERE c.session_id = _session 
     ORDER BY c.id; 
    RETURN NEXT c_shopping_cart; 
END; 
$$ LANGUAGE plpgsql; 

、呼び出し:ユーザーのためのいくつかの電話が可能ですので、私は使用したくない

BEGIN; 
SELECT load_page(mySession); 
FETCH ALL IN "<server cursor 1>"; 
FETCH ALL IN "<server cursor 2>"; 
COMMIT; 
+0

はい、私はこの記事を見ました。とにかく、あなたの研究のおかげで:) – user1820686

0

が加入します。

これはPostgreSQLのJOINを避ける理由ではありません。まったく。

PostgreSQLは、あなたが配列に電話番号を集約することができます:

CREATE OR REPLACE FUNCTION getUserById() 
RETURNS TABLE (
    id INTEGER, 
    name TEXT, 
    /* and other columns */ 
    phone_numbers TEXT[] 
) 
AS 
$$ 
    select 
     users.id, 
     users.name, 
     /* and other columns */ 
     -- Remove NULL because you get an array containing just NULL 
     -- if user_phones doesn't contain any matching rows. 
     array_remove(array_agg(user_phones.phone_number), NULL) as phone_numbers 
    from users 
    left join user_phones on user_phones.user_id = users.id 
    where users.id = 1 
    -- Note that grouping by a table's primary key allows you to use 
    -- any column from that table in the select in PostgreSQL 
    group by users.id 
    ; 
$$ 
LANGUAGE SQL 
STABLE 
; 

これは非常にシンプルでより直感的です。

電話番号のないユーザーに対してゼロ行を返すことができれば、内部結合に切り替えることができます。その場合、array_removeコールをドロップすることができます。

私も(それが任意のテーブルのデータを変更しないため)関数にSTABLE仕様を追加し、SQLの代わりに、PGPLSQL(それだけで単一のクエリなので)にそれを切り替えます。これによりPGの最適化が可能になります。特に、クエリをインライン化し、場合によってフィルタをプッシュダウンすることができます。実際には機能は必要ないかもしれません。

関連する問題