ツリー構造のレコードから列のセットを再帰的に返すplpgsql
関数を記述しようとしています。
データテーブルとデータをリンクするためのテーブルがあります。
DATATABLE
-----------
id integer
value text
info text
LINKTABLE
-----------
link integer
parent integer
私の考えは次の関数のようにすることでした:
CREATE OR REPLACE FUNCTION my_function(itemID integer)
RETURNS TABLE(id integer, value text) AS
$BODY$
BEGIN
RETURN QUERY SELECT my_function(A.link) FROM linktable A, datatable B
WHERE A.parent = B.id AND B.id = itemID) C;
RETURN QUERY SELECT id, value FROM datatable WHERE id = itemID;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
しかし、それは機能しません。最初のクエリでエラーが発生します。
エラー:クエリの構造が関数の結果のタイプと一致しません
私のJust-In-Brainコンパイラは問題を検出しないので、ここで何が問題になっていますか?
関数はまったく必要ありません。これは単一のSQLステートメントで実行できます。
with recursive tree as (id, parent) (
select link as id,
parent
from linktable
where id = itemid
union all
select c.link as id,
c.parent
from linktable c
join tree p on p.id = c.parent
)
select dt.id, dt.value
from tree
join datatable dt on dt.id = tree.id
再帰クエリの概要については、マニュアルを参照してください: http://www.postgresql.org/docs/current/static/queries-with.html
これをplpgsql関数で実行したい場合は、いくつかの変更を加えるだけでうまくいきます。
CREATE OR REPLACE FUNCTION my_function(itemID integer)
RETURNS TABLE(id integer, value text) AS
$BODY$
BEGIN
RETURN QUERY
SELECT (my_function(A.link)).*
FROM linktable A
JOIN datatable B ON A.parent = B.id AND B.id = itemID;
RETURN QUERY
SELECT d.id, d.value
FROM datatable d
WHERE d.id = itemID;
END;
$BODY$
LANGUAGE plpgsql;
.*
を後に追加しますdatatable
と同じ列名があるため、2番目のクエリで列名を修飾する必要があります) C
を削除とにかく、CTEの使用についてa_horse_with_no_nameに同意します。