SQL'DELETE CASCADE'

时间:2011-04-15 12:17:57

标签: sql postgresql sql-delete cascading-deletes

我有一个表B,它有一个表A的外键,现在我想在A上做一个“DELETE CASCADE”的东西,但是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的子集,但我不能指出任何设计范例来支持它。

4 个答案:

答案 0 :(得分:2)

使用PostgreSQL 9.1可以实现这一点,但我认为如果不定义级联约束,就没有办法做到这一点。

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

答案 1 :(得分:2)

您可以等待9.1或同时创建一个设置返回功能:

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)
        )

P.S。如果您不了解标准的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应该是UNIQUEPRIMARY KEY,这对于批量更新而言比基于集合的解决方案效率低。

答案 2 :(得分:1)

你应该可以这样做:这是我在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)
);

答案 3 :(得分:-1)

数据库功能在我的舒适区之外(我知道,我知道)而且我不想对有问题的列进行临时更改,所以我只是做了一个

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

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