階層データ テーブルに関するいくつかの記事を読んだ後、次のようなテーブルにたどり着きました: 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) );
略語が更新された場合、一連の行で実行される関数を変更するにはどうすればよいですか (つまり、略語の名前を変更するか、parent_id を変更します)?
Postgresql v9.1 を使用しています。
前もって感謝します。