在阅读了几个分层数据表的文章之后,我已经进入了一个看起来像这样的表: LOCAL:
|id|name |parent_id|abbreviature | path |
-------------------------------------------------------
|1 |"Shoping" |NULL | "Sh" | "Sh" |
|2 |"Building A"|1 | "A" | "Sh.A" |
|3 |"Building B"|1 | "B" | "Sh.B" |
|4 |"Building C"|1 | "C" | "Sh.C" |
|5 |"Floor -1" |2 | "-1" | "Sh.A.-1" |
|6 |"Floor 0" |2 | "0" | "Sh.A.0" |
|7 |"Floor 1" |2 | "1" | "Sh.A.1" |
|8 |"Floor 2" |2 | "2" | "Sh.A.2" |
|9 |"Room 101" |7 | "101" | "Sh.A.1.101"|
|10|"Hospital" |NULL | "Hosp" | "Hosp" |
|11|"Secretary" |10 | "Secrt" | "Secrt" |
等等。这样,选择节点的所有后代特别容易。
我创建了这个函数来生成路径:
CREATE OR REPLACE FUNCTION teste1_trig () RETURNS TRIGGER AS '
DECLARE
dot varchar := ''.'';
npath local.path%TYPE;
BEGIN
IF NEW.parent_id IS NULL THEN
NEW.path:=NEW.abbreviature;
RETURN NEW;
ELSEIF NEW.parent_id IS NOT NULL THEN
SELECT path INTO npath FROM local WHERE id=NEW.parent_id;
NEW.path:=npath||dot||NEW.abbreviature;
RETURN NEW;
END IF;
END;' LANGUAGE 'plpgsql';
此功能由以下触发器激活:
CREATE TRIGGER trigger_teste
BEFORE INSERT OR UPDATE
ON local
FOR EACH ROW
EXECUTE PROCEDURE teste1_trig();
除非我从一个有孩子的节点更新一个缩略图,孩子们仍然保留旧路径,否则每件事都能完美无瑕。
我想更改函数以更新当前行中的所有子项。 以下是选择所有子项的查询:
SELECT id,name,parent_id FROM local WHERE id IN (
(WITH RECURSIVE parent AS
(
SELECT id, parent_id from local WHERE id = id_from_the_modified_node
UNION ALL
SELECT t.id, t.parent_id FROM parent
INNER JOIN local t ON parent.id = t.parent_id
)
SELECT id FROM parent
WHERE id <> id_from_the_modified_node) );
如果更新了abbreviature(即更改缩写词的名称或更改parent_id),如何更改要在一系列行中执行的功能?
我正在使用Postgresql v9.1。
提前谢谢。
答案 0 :(得分:1)
我已经找到了答案,我认为这是最好的情况。如果我错了,请纠正我!
DECLARE
id_upd INT[];
...
BEGIN
...
SELECT array ( SELECT id FROM local WHERE parent_id=NEW.id ) into id_upd; --- select direct childs
IF id_upd IS NOT NULL THEN
FOREACH i IN ARRAY id_upd LOOP
UPDATE local SET path=NEW.path||'.'||abbreviature where id=i; --- update them
END loop;
END IF;
END;
这样我只更新节点的所有直接子节点,触发器再次为子节点的子节点触发,等等。
不要忘记检查父节点是否不是节点的后代,这样你就会创建一个无限循环。
最好的问候