我想檢測層次結構中的潛在週期。我有三個表,每個表有一個父,和一個孩子柱:使用sql檢測週期
表1中包含一些節點(列名兒童)和他們的父母(在列父); Table2包含Table1的所有父項(在子列中)及其父項(在父列中)等等。
例如,如果A是B的子項,以及B是C的子和C是A的一個子,然後我有一個週期。
是否有可能檢測到使用SQL命令的週期?
我想檢測層次結構中的潛在週期。我有三個表,每個表有一個父,和一個孩子柱:使用sql檢測週期
表1中包含一些節點(列名兒童)和他們的父母(在列父); Table2包含Table1的所有父項(在子列中)及其父項(在父列中)等等。
例如,如果A是B的子項,以及B是C的子和C是A的一個子,然後我有一個週期。
是否有可能檢測到使用SQL命令的週期?
這裏是與任意深度有效的解決方案。在一個表中
存儲您所有的關係:
Table t
Parent | Child
------ | -----
B | A
C | B
A | C
E | D
F | E
然後你就可以使用這個WITH RECURSIVE
查詢來查找循環:
WITH RECURSIVE working(parent, last_visited, already_visited, cycle_detected) AS (
SELECT parent, child, ARRAY[parent], false FROM t
UNION ALL
SELECT t.parent, t.child, already_visited || t.parent, t.parent = ANY(already_visited)
FROM t
JOIN working ON working.last_visited = t.parent
WHERE NOT cycle_detected
)
SELECT parent, already_visited FROM working WHERE cycle_detected
它會給你的parent
s表示是一個循環的一部分,也是他們所處的循環:
A | A,C,B,A
B | B,A,C,B
C | C,B,A,C
它的工作原理是這樣的(因爲這是關鍵字RECURSIVE
指示Postgres的做):
SELECT
,從表t
選擇所有條目,將它們放置在一個名爲working
臨時表。SELECT
,與表t
加入working
表中查找每個條目的孩子。這些孩子被添加到已經看過的孩子們的陣列中。SELECT
,只要輸入被添加到working
表。當其中一個條目在這種情況下cycle_detected
設置爲true訪問它以前(t.parent = ANY(already_visited)
)參觀了一個孩子,沒有更多的孩子加入到項檢測謝謝你的偉大的東西,併爲您的全面解釋。很有用。 – geek2000
您的任務中的表格之間有非常奇怪的引用。然而,這是我的方法來檢查現有的循環。
示例表1:
CREATE OR REPLACE FUNCTION fn_table1_check() RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
PERFORM 1 FROM table2
JOIN table3 ON table3.parent=table2.child
WHERE table2.parent=NEW.child AND table3.child=NEW.parent
LIMIT 1;
IF FOUND THEN
RAISE EXCEPTION 'Found recursive loop!';
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER tg_table1_check BEFORE INSERT OR UPDATE ON table1 FOR EACH ROW EXECUTE PROCEDURE fn_table1_check();
非常感謝!我不熟悉plpgsql。我會研究你的代碼。 – geek2000
您正在使用哪個數據庫管理系統? –
我正在使用Postgres。你是這個意思嗎? – geek2000
你是什麼意思的週期?你能否提高效率 –