SQL“删除级联”

发布于 2024-11-02 05:29:16 字数 527 浏览 6 评论 0原文

我有一个表 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 中的子集,但我无法真正指出任何设计支持这一点的范式。

I have a table B that has a foreign key to table A, and now I want to do a sorta "DELETE CASCADE" thingie on A, but PostgreSQL won't accept the following:

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

Seems that only SELECT can be inside the IN () clause. I suppose there is some easy (and standard SQL, not PostgreSQL-specific?) way of doing this?

Edit: is it safe to say that something is badly structured when you bump into this kind of problem? In our case I have a gut feeling that the hits in ..[expr].. should be in a new CTAble instead of as a subset in ATable, but I can't really point to any design paradigm to support that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

英雄似剑 2024-11-09 05:29:16

这在 PostgreSQL 9.1 中是可能的,但我认为在不定义级联约束的情况下没有任何方法可以做到这一点。

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

This will be possible with PostgreSQL 9.1, but I don't think there is any way doing that without defining cascading constraints.

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

∞琼窗梦回ˉ 2024-11-09 05:29:16

您可以等待 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 应该是 UNIQUEPRIMARY KEY,与基于集合的更新相比,这对于批量更新来说效率较低解决方案。

You can wait for 9.1 or create a set-returning function meanwhile:

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. Just in case if you're not aware about standard SQL way of doing it.

If you create the tables like this:

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

then a delete from btable will trigger a delete from atable as well.

For this to work, btable.aid should be UNIQUE or a PRIMARY KEY, and this is less efficient for mass updates than a set-based solution.

始终不够 2024-11-09 05:29:16

您应该能够做到这一点:这是我在

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

You should be able to do that: here is an example that I found on the bottom of this page.

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)
);
滿滿的愛 2024-11-09 05:29:16

数据库函数超出了我的舒适区(我知道,我知道),我什至不想对相关列进行临时更改,所以我只是做了 a

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

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

DB functions are outside my comfort zone (I know, I know) and I didn't want to make even temporary changes to the columns in question so I simply did a

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

and used that to sequentially delete data in B and A.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文