2

我有一个表 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]..应该在一个新的 CTAable 中而不是作为 ATable 中的一个子集,但我不能真正指出任何设计范式来支持这一点。

4

4 回答 4

2

这将在 PostgreSQL 9.1 中成为可能,但我认为没有定义级联约束的任何方法都可以做到这一点。

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

于 2011-04-15T12:20:10.347 回答
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)
        )

PS 以防万一你不知道标准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或 a PRIMARY KEY,这对于大规模更新来说效率低于基于集合的解决方案。

于 2011-04-15T12:30:36.643 回答
1

您应该能够做到这一点:这是我在本页底部找到的一个示例

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)
);
于 2011-04-15T12:29:54.697 回答
-1

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

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

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

于 2011-04-15T12:48:28.157 回答