如何找到将被 CASCADE 丢弃的所有对象?
How to find all object which will be dropped by CASCADE?
当我掉东西时:
ALTER TABLE "order_bt" DROP COLUMN "billed_to"
文档说我可以看到依赖于 billed_to
列的内容:
DETAIL: view "order" depends on column billed_to of table order_bt
但是在 order
视图中还有依赖于 order
的触发器,这些触发器将随着 CASCADE
一起被删除
是否有一个选项允许查看 CASCADE
将删除的内容的完整列表?
我创建了一个示例结构来检查依赖关系。你可以在你的数据库上试试,当然objects ID会不一样。
CREATE TABLE parents (
id_parent integer NOT NULL,
name_parent varchar(100),
CONSTRAINT pk_parents_id PRIMARY KEY (id_parent)
);
CREATE TABLE childs (
id_child integer NOT NULL,
name_child varchar(100),
parent_id integer,
CONSTRAINT pk_childs_id PRIMARY KEY (id_child),
CONSTRAINT fk_childs_parent_id__parents FOREIGN KEY (parent_id)
REFERENCES parents (id_parent) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE OR REPLACE VIEW public.parents_view AS
SELECT parents.id_parent,
parents.name_parent
FROM parents;
CREATE FUNCTION test_trigger() RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' then
raise notice 'INSERT trigger, NEW = [%]', NEW;
ELSIF TG_OP = 'UPDATE' then
raise notice 'UPDATE trigger, OLD = [%], NEW = [%]', OLD, NEW;
ELSE
raise notice 'DELETE trigger, OLD = [%]', OLD;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER parents_view_trigger INSTEAD OF INSERT OR UPDATE OR DELETE ON parents_view FOR EACH ROW EXECUTE PROCEDURE test_trigger();
Objects 依赖于 table "parents":
SELECT
refclassid, refobjid, refobjsubid,
pg_describe_object(refclassid, refobjid, refobjsubid),
--pg_identify_object (refclassid, refobjid, refobjsubid) ,
classid, objid, objsubid,
pg_describe_object(classid, objid, objsubid),
--pg_identify_object (classid, objid, objsubid) ,
pg_get_constraintdef(objid),
deptype
FROM pg_depend
WHERE refobjid IN ('parents'::regclass) -- and deptype IN ('n', 'a')
ORDER BY classid, refobjid;
输出:
refclassid
refobjid
refobjsubid
pg_describe_object refobject
classid
objid
objsubid
pg_describe_object object
pg_get_constraintdef
deptype
1259
2305241
0
table parents
1247
2305243
0
type parents
i
1259
2305241
1
table parents column id_parent
2606
2305245
0
constraint pk_parents_id on table parents
PRIMARY KEY (id_parent)
a
1259
2305241
1
table parents column id_parent
2606
2305251
0
constraint fk_childs_parent_id__parents on table childs
FOREIGN KEY (parent_id) REFERENCES parents(id_parent) ON UPDATE CASCADE ON DELETE CASCADE
n
1259
2305241
1
table parents column id_parent
2618
2305259
0
rule _RETURN on view parents_view
n
1259
2305241
2
table parents column name_parent
2618
2305259
0
rule _RETURN on view parents_view
n
Objects 取决于视图 "parents_view":
SELECT
refclassid, refobjid, refobjsubid,
pg_describe_object(refclassid, refobjid, refobjsubid),
--pg_identify_object (refclassid, refobjid, refobjsubid),
classid, objid, objsubid,
pg_describe_object(classid, objid, objsubid),
--pg_identify_object (classid, objid, objsubid) ,
pg_get_constraintdef(objid),
deptype
FROM pg_depend
WHERE refobjid IN ('parents_view'::regclass) -- and deptype IN ('n', 'a')
ORDER BY classid, refobjid;
输出:
refclassid
refobjid
refobjsubid
pg_describe_object refobj
classid
objid
objsubid
pg_describe_object obj
pg_get_constraintdef
deptype
1259
2305256
0
view parents_view
1247
2305258
0
type parents_view
i
1259
2305256
0
view parents_view
2618
2305259
0
rule _RETURN on view parents_view
i
1259
2305256
0
view parents_view
2618
2305259
0
rule _RETURN on view parents_view
n
1259
2305256
0
view parents_view
2620
2305260
0
trigger parents_view_trigger on view parents_view
a
您可以检查视图“parents_view”(object ID:2305256)不依赖于 table parents 但规则“在视图 [=39 上规则 _RETURN =]" (object ID: 2305259) 可以,而"trigger parents_view_trigger on view parents_view"依赖于parents_view,这就是为什么递归查询不return查看依赖信息。
触发器是 DEPENDENCY_AUTO 类型 (a):依赖 object 可以与引用 object 分开删除,并且应该自动删除(无论是 RESTRICT 还是 CASCADE 模式)如果引用的 object 被删除。示例:table 上的命名约束是 table 上的 auto-dependent,因此如果 table 被删除,它将消失。
您可以尝试这样的查询,但您应该尝试改进它:
您可以通过 deptype 限制结果过滤。
WITH RECURSIVE pg_depend_recursive AS (
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
where refobjid = 'parents'::regclass
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive dr ON d.refobjid = dr.objid),
pg_depend_recursive2 AS (SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend_recursive d
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive2 dr ON d.objid = dr.objid AND pg_describe_object(dr.classid, dr.objid, dr.objsubid) ilike 'rule%'),
pg_depend_recursive3 AS (SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend_recursive2 d
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive3 dr ON d.refobjid = dr.refobjid)
SELECT refclassid, refobjid, refobjsubid, pg_describe_object(refclassid, refobjid, refobjsubid),
classid, objid, objsubid, pg_describe_object(classid, objid, objsubid),
deptype
FROM pg_depend_recursive3;
当我掉东西时:
ALTER TABLE "order_bt" DROP COLUMN "billed_to"
文档说我可以看到依赖于 billed_to
列的内容:
DETAIL: view "order" depends on column billed_to of table order_bt
但是在 order
视图中还有依赖于 order
的触发器,这些触发器将随着 CASCADE
是否有一个选项允许查看 CASCADE
将删除的内容的完整列表?
我创建了一个示例结构来检查依赖关系。你可以在你的数据库上试试,当然objects ID会不一样。
CREATE TABLE parents (
id_parent integer NOT NULL,
name_parent varchar(100),
CONSTRAINT pk_parents_id PRIMARY KEY (id_parent)
);
CREATE TABLE childs (
id_child integer NOT NULL,
name_child varchar(100),
parent_id integer,
CONSTRAINT pk_childs_id PRIMARY KEY (id_child),
CONSTRAINT fk_childs_parent_id__parents FOREIGN KEY (parent_id)
REFERENCES parents (id_parent) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE OR REPLACE VIEW public.parents_view AS
SELECT parents.id_parent,
parents.name_parent
FROM parents;
CREATE FUNCTION test_trigger() RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' then
raise notice 'INSERT trigger, NEW = [%]', NEW;
ELSIF TG_OP = 'UPDATE' then
raise notice 'UPDATE trigger, OLD = [%], NEW = [%]', OLD, NEW;
ELSE
raise notice 'DELETE trigger, OLD = [%]', OLD;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER parents_view_trigger INSTEAD OF INSERT OR UPDATE OR DELETE ON parents_view FOR EACH ROW EXECUTE PROCEDURE test_trigger();
Objects 依赖于 table "parents":
SELECT
refclassid, refobjid, refobjsubid,
pg_describe_object(refclassid, refobjid, refobjsubid),
--pg_identify_object (refclassid, refobjid, refobjsubid) ,
classid, objid, objsubid,
pg_describe_object(classid, objid, objsubid),
--pg_identify_object (classid, objid, objsubid) ,
pg_get_constraintdef(objid),
deptype
FROM pg_depend
WHERE refobjid IN ('parents'::regclass) -- and deptype IN ('n', 'a')
ORDER BY classid, refobjid;
输出:
refclassid | refobjid | refobjsubid | pg_describe_object refobject | classid | objid | objsubid | pg_describe_object object | pg_get_constraintdef | deptype |
---|---|---|---|---|---|---|---|---|---|
1259 | 2305241 | 0 | table parents | 1247 | 2305243 | 0 | type parents | i | |
1259 | 2305241 | 1 | table parents column id_parent | 2606 | 2305245 | 0 | constraint pk_parents_id on table parents | PRIMARY KEY (id_parent) | a |
1259 | 2305241 | 1 | table parents column id_parent | 2606 | 2305251 | 0 | constraint fk_childs_parent_id__parents on table childs | FOREIGN KEY (parent_id) REFERENCES parents(id_parent) ON UPDATE CASCADE ON DELETE CASCADE | n |
1259 | 2305241 | 1 | table parents column id_parent | 2618 | 2305259 | 0 | rule _RETURN on view parents_view | n | |
1259 | 2305241 | 2 | table parents column name_parent | 2618 | 2305259 | 0 | rule _RETURN on view parents_view | n |
Objects 取决于视图 "parents_view":
SELECT
refclassid, refobjid, refobjsubid,
pg_describe_object(refclassid, refobjid, refobjsubid),
--pg_identify_object (refclassid, refobjid, refobjsubid),
classid, objid, objsubid,
pg_describe_object(classid, objid, objsubid),
--pg_identify_object (classid, objid, objsubid) ,
pg_get_constraintdef(objid),
deptype
FROM pg_depend
WHERE refobjid IN ('parents_view'::regclass) -- and deptype IN ('n', 'a')
ORDER BY classid, refobjid;
输出:
refclassid | refobjid | refobjsubid | pg_describe_object refobj | classid | objid | objsubid | pg_describe_object obj | pg_get_constraintdef | deptype |
---|---|---|---|---|---|---|---|---|---|
1259 | 2305256 | 0 | view parents_view | 1247 | 2305258 | 0 | type parents_view | i | |
1259 | 2305256 | 0 | view parents_view | 2618 | 2305259 | 0 | rule _RETURN on view parents_view | i | |
1259 | 2305256 | 0 | view parents_view | 2618 | 2305259 | 0 | rule _RETURN on view parents_view | n | |
1259 | 2305256 | 0 | view parents_view | 2620 | 2305260 | 0 | trigger parents_view_trigger on view parents_view | a |
您可以检查视图“parents_view”(object ID:2305256)不依赖于 table parents 但规则“在视图 [=39 上规则 _RETURN =]" (object ID: 2305259) 可以,而"trigger parents_view_trigger on view parents_view"依赖于parents_view,这就是为什么递归查询不return查看依赖信息。
触发器是 DEPENDENCY_AUTO 类型 (a):依赖 object 可以与引用 object 分开删除,并且应该自动删除(无论是 RESTRICT 还是 CASCADE 模式)如果引用的 object 被删除。示例:table 上的命名约束是 table 上的 auto-dependent,因此如果 table 被删除,它将消失。
您可以尝试这样的查询,但您应该尝试改进它:
您可以通过 deptype 限制结果过滤。
WITH RECURSIVE pg_depend_recursive AS (
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
where refobjid = 'parents'::regclass
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive dr ON d.refobjid = dr.objid),
pg_depend_recursive2 AS (SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend_recursive d
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive2 dr ON d.objid = dr.objid AND pg_describe_object(dr.classid, dr.objid, dr.objsubid) ilike 'rule%'),
pg_depend_recursive3 AS (SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend_recursive2 d
UNION
SELECT d.refclassid, d.refobjid, d.refobjsubid, d.classid, d.objid, d.objsubid, d.deptype
FROM pg_depend d
INNER JOIN pg_depend_recursive3 dr ON d.refobjid = dr.refobjid)
SELECT refclassid, refobjid, refobjsubid, pg_describe_object(refclassid, refobjid, refobjsubid),
classid, objid, objsubid, pg_describe_object(classid, objid, objsubid),
deptype
FROM pg_depend_recursive3;