假设我有以下表结构:
| ID | ParentID |姓名|
我想编写一个递归的PostgreSQL函数,用于将传递给它的节点ID的所有子节点作为参数。
这是我到目前为止的代码(我只有一部分函数可以获取传递的ID的所有子代,现在我需要递归部分):
CREATE OR REPLACE FUNCTION GetAllChildren(IN NodeID INTEGER) RETURNS INTEGER AS $$
DECLARE
Crs CURSOR FOR SELECT ID, ParentID, Name FROM Tree WHERE ParentID=NodeID;
VarRow Tree%ROWTYPE;
BEGIN
OPEN Crs;
CREATE TEMPORARY TABLE TBL(
ID SERIAL,
ParentID INTEGER,
Name CHARACTER(100)
);
LOOP
FETCH Crs INTO VarRow;
IF VarRow IS NULL THEN
EXIT;
END IF;
INSERT INTO TBL(ID, ParentID, Name) VALUES(VarRow.ID, VarRow.ParentID, VarRow.Name);
END LOOP;
CLOSE Crs;
RETURN 0;
END;
$$ LANGUAGE plpgsql;
也许最大的问题是我不知道在递归调用之间保存输出的位置。
如果到目前为止还没有想到,那就是关于邻接列表,获取节点的所有子节点并将它们打印到表格中。
有没有人有解决方案?
答案 0 :(得分:4)
有关信息,Postgres中有常见的表格表达式,这可能对此有所帮助:
http://www.postgresql.org/docs/current/static/queries-with.html
调整文档中的示例:
WITH RECURSIVE rec_tree(parent_id, node_id, data, depth) AS (
SELECT t.parent_id, t.node_id, t.data, 1
FROM tree t
UNION ALL
SELECT t.parent_id, t.node_id, t.data, rt.depth + 1
FROM tree t, rec_tree rt
WHERE t.parent_id = rt.node_id
)
SELECT * FROM rec_tree;
(有关阻止图表循环的示例,请参阅文档。)
答案 1 :(得分:4)
PostgreSQL不知道本地(程序)有限的临时表 - 你的临时表在所有被调用函数的实例中都是可见的,它也会在你的函数外面显示 - 它具有会话可见性。
但是PostgreSQL函数(PostgreSQL没有程序)可以直接返回表 - 所以你不需要使用辅助表来存储数据
CREATE OR REPLACE FUNCTION children_by_parent(_parent_id int) RETURNS SETOF children AS $$ -- children is table name DECLARE r children; BEGIN FOR r IN SELECT * FROM children WHERE parent_id = _parent_id LOOP RETURN NEXT r; -- return node RETURN QUERY SELECT * FROM children_by_parent(r.id); -- return children END LOOP; RETURN; END; $$ LANGUAGE plpgsql STRICT;
这个表单更快,因为你没有填充任何表格(虽然临时表通常只在RAM中)。
你不需要在PostgreSQL中使用显式游标 - 语句FOR do all,它更短,更友好。
答案 2 :(得分:0)
是。它位于PostgreSQL wiki,首先在google上点击。