【问题标题】:SQL 'DELETE CASCADE'SQL '删除级联'
【发布时间】:2011-04-15 12:17:56
【问题描述】:

我有一个表 B,它有一个表 A 的外键,现在我想在 A 上做一个“删除级联”的事情,但 PostgreSQL 不接受以下内容:

DELETE FROM ATable WHERE aid IN
(
    DELETE FROM BTable WHERE aid IN
    (
        ... [expression that depends on the entries in BTAble] ...
    )
    RETURNING aid
);

似乎只有 SELECT 可以在 IN () 子句中。我想有一些简单的(和标准的 SQL,不是特定于 PostgreSQL 的?)的方法吗?

编辑:当您遇到此类问题时,是否可以肯定地说某些内容结构不正确?在我们的例子中,我有一种直觉,..[expr].. 中的点击应该在一个新的 CTAble 中,而不是作为 ATable 中的一个子集,但我真的无法指出任何设计范式来支持这一点。

【问题讨论】:

    标签: sql postgresql sql-delete cascading-deletes


    【解决方案1】:

    这在 PostgreSQL 9.1 中是可能的,但我认为没有定义级联约束就没有办法做到这一点。

    http://developer.postgresql.org/pgdocs/postgres/queries-with.html#QUERIES-WITH-MODIFYING

    【讨论】:

    • 哎哟!您是在谈论外键上的“ON UPDATE CASCADE ON DELETE CASCADE”吗? developer.postgresql.org 目前不适合我...
    • @Jonas:是的,ON DELETE CASCADE 就是我所说的
    【解决方案2】:

    你可以等待9.1或者同时创建一个set-return函数:

    CREATE OR REPLACE FUNCTION fn_delete_btable(params)
    RETURNS SETOF btable.aid%TYPE
    AS
    $$
            DELETE
            FROM    btable
            WHERE   expression_over_params(params)
            RETURNING 
                    aid
    $$
    LANGUAGE 'sql';
    
    DELETE
    FROM    atable
    WHERE   aid IN
            (
            SELECT  aid
            FROM    fn_delete_btable(params)
            )
    

    附:以防万一您不了解标准的 SQL 执行方式。

    如果你创建这样的表:

    CREATE TABLE btable (aid INT NOT NULL UNIQUE, …)
    CREATE TABLE atable (aid INT NOT NULL FOREIGN KEY REFERENCES (aid) ON DELETE CASCADE, …)
    

    然后从btable 删除也会触发从atable 删除。

    为此,btable.aid 应该是 UNIQUE 或 PRIMARY KEY,这对于批量更新的效率低于基于集合的解决方案。

    【讨论】:

    • 关于返回 id 的函数的好主意
    【解决方案3】:

    你应该能够做到这一点:这是我在this 页面底部找到的一个示例。

    CREATE TABLE order_items (
        product_no integer REFERENCES products ON DELETE RESTRICT,
        order_id integer REFERENCES orders ON DELETE CASCADE,
        quantity integer,
        PRIMARY KEY (product_no, order_id)
    );
    

    【讨论】:

      【解决方案4】:

      DB 函数超出了我的舒适区(我知道,我知道),我什至不想对有问题的列进行临时更改,所以我只是做了一个

      CREATE TABLE CTable AS ... [expression that depends on BTAble] ...;
      

      并用它来顺序删除B和A中的数据。

      【讨论】:

      • 一般情况下你可能是对的。对我来说,这是解决我的问题的最简单方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 2011-06-19
      • 2011-06-11
      • 1970-01-01
      相关资源
      最近更新 更多