【问题标题】:postgresql on delete cascadepostgresql 删除级联
【发布时间】:2012-07-16 12:50:51
【问题描述】:

我有两张桌子:

TableY:
    id, name, description

TableX:
    id, name, y_id

我在TableX (y_id REFERENCING tableY id ON DELETE CASCADE) 中添加了一个外键。 当我从 TableX 删除时,TableY id 仍然存在(虽然理论上应该删除)。 我想我误解了ON DELETE CASCADE 选项的工作原理。谁能告诉我做错了什么?

我也看到了这个ON DELETE CASCADE,但对我来说没有多大意义。

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    简答

    ON DELETE CASCADE 指定约束选项。在您的情况下(假设您有依赖于 table_x 的 table_x 和 table_y),当您删除 table_x 中的行并且从 table_y 引用该行时,table_x 中的行将被删除,并且在 table_y 中引用该行的所有行也将被删除。

    当您想要删除表并在此表上依赖一个或多个其他表时,请使用 DROP TABLE 和 CASCADE 关键字。

    更多关于 DROP、DELETE 和 ON DELETE CASCADE 约束选项

    删除与删除

    当您想从数据库中删除表时,请使用 drop。当您使用删除一词时,表示您要从表中删除/删除内容(但希望表保持=继续存在于数据库中)。

    删除从其他表引用的行

    当您在表中有行(例如 table_x 和 id 为 1 的行)并且该行被其他表引用(在其他表中有与该条目链接的外键)时,您不能删除该行,如下所示。你会得到一个错误。

    DELETE FROM table_x WHERE id = 1;
    
    ERROR:  update or delete on table "table_x" violates foreign key constraint "constraint_name" on table "table_y"
    DETAIL:  Key (id)=(1) is still referenced from table "table_y".
    

    原因在错误的详细部分描述。其他表/表中的条目/条目引用此条目。例如,您可以想象表 account 和表 account_activity。当您从表帐户中删除条目(删除一个帐户)时,您应该从表 account_activity 中删除所有引用表帐户中此特定条目的条目。否则,您最终会得到不涉及任何帐户的帐户活动。

    根据您想要实现的目标,有两种可能性:

    1. 您要删除整个表 (table_x) 的内容和 引用(外键)此表的所有表。
    2. 您想从一个表中删除 WHERE 子句中指定的一个或多个条目(行),同时删除所有引用此表的行 条目/条目(如 account 和 account_activity 的示例 上面提到的)。

    1) 使用带有 CASCADE 关键字的 TRUNCATE

    TRUNCATE table_x CASCADE;
    

    2) 更改您在 table_y 中对列的约束,使其具有 ON DELETE CASCADE 选项。

    ALTER TABLE table_y   
        DROP CONSTRAINT constraint_name,   
        ADD CONSTRAINT constraint_name FOREIGN KEY (column_in_table_y)
              REFERENCES table_x (referenced_column_in_table_x) ON DELETE CASCADE;
    

    删除其他表所依赖的表

    当您有表(例如 table_x)并且其他表/表依赖于它时,您不能删除此表。依赖意味着其他表引用(具有外键)此表(table_x)。当您尝试删除此类表时,您会收到错误。

    DROP TABLE table_x;
    
    ERROR:  cannot drop table table_x because other objects depend on it
    DETAIL:  constraint id_x_fk on table table_y depends on table table_x
    HINT:  Use DROP ... CASCADE to drop the dependent objects too.
    

    错误提示。当您想要删除这样的表时,您必须使用带有级联关键字的 drop。该表将被删除,并且所有引用该表的约束也将被删除。

    DROP TABLE table_x CASCADE;
    

    示例

    创建 table_x 和 table_y。

    CREATE TABLE table_x
    (
      id integer NOT NULL,
      text character varying(255) NOT NULL,
      CONSTRAINT table_x_pk PRIMARY KEY (id)
    );
    
    CREATE TABLE table_y
    (
      id integer NOT NULL,
      text character varying(255) NOT NULL,
      id_x integer NOT NULL,
      CONSTRAINT table_y_pk PRIMARY KEY (id)
    );
    

    在 table_y 的 id_x 列上创建名为 id_x_fk 的约束。

    ALTER TABLE table_y
      ADD CONSTRAINT id_x_fk FOREIGN KEY (id_x)
          REFERENCES table_x (id);
    

    将测试数据插入 table_x 和 table_y。

    INSERT INTO table_x VALUES
        (1, 'super x'),
        (2, 'great x');
    
    INSERT INTO table_y VALUES
        (1, 'y one', 2),
        (2, 'y two', 1),
        (3, 'y three', 1);
    

    从 table_x 中删除(错误)。

    DELETE FROM table_x WHERE id = 1;
    

    删除和添加同名约束。

    ALTER TABLE table_y
      DROP CONSTRAINT id_x_fk,
      ADD CONSTRAINT id_x_fk FOREIGN KEY (id_x)
          REFERENCES table_x (id) ON DELETE CASCADE;
    

    从 table_x 和 table_y 中删除(正确)。

    DELETE FROM table_x WHERE id = 1;
    

    正在删除 table_x 和 table_y 中的所有内容。

    TRUNCATE table_x CASCADE;
    

    删除(删除)table_x 并删除 table_y 中的 id_x_fk 约束。

    DROP TABLE table_x CASCADE;
    

    通知

    如果您在 table_x 中有行(例如,id = 3)并且此条目(此 id)未从 table_y 引用,您可以删除该行,即使约束没有 ON DELETE CASCADE 选项(因为没有约束违规)。

    代码在“PostgreSQL 9.2.4, Visual C++ build 1600, 64-bit 编译”上测试。

    来源:

    http://www.postgresql.org/docs/current/static/sql-droptable.html

    http://www.postgresql.org/docs/current/static/sql-delete.html

    http://www.postgresql.org/docs/current/static/ddl-constraints.html

    http://www.postgresql.org/docs/current/static/sql-altertable.html

    PostgreSQL delete all content

    【讨论】:

      【解决方案2】:

      我猜你误会了。尝试从TableY 中删除行,TableX 中的相应行将被级联删除。当您有辅助相关表并希望通过从主表中删除父行来清理它们而不违反约束或留下垃圾时,此选项是必不可少的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-07
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 2018-08-31
        • 2015-04-24
        • 1970-01-01
        • 2011-06-29
        相关资源
        最近更新 更多