如何找到将被 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;