级联删除一次

时间:2020-03-06 14:41:01  来源:igfitidea点击:

我有一个Postgresql数据库,我想在该数据库上进行一些级联删除。但是,这些表未使用ON DELETE CASCADE规则进行设置。有什么办法可以执行一次删除并告诉Postgresql一次将其级联吗?相当于

DELETE FROM some_table CASCADE;

这个较旧问题的答案似乎似乎不存在这样的解决方案,但我想我想明确地问这个问题只是为了确定。

解决方案

只需一次,我们只需为要级联的表编写delete语句即可。

DELETE FROM some_child_table WHERE some_fk_field IN (SELECT some_id FROM some_Table);
DELETE FROM some_table;

带级联选项的删除仅适用于已定义外键的表。如果我们执行删除操作,但说不能,因为它会违反外键约束,则级联将导致它删除有问题的行。

如果要以这种方式删除关联的行,则需要首先定义外键。另外,请记住,除非我们明确指示它开始事务,或者更改默认值,否则它将执行自动提交,这可能会非常耗时。

如果我理解正确,那么我们应该能够通过删除外键约束,添加新的(它将层叠),完成工作并重新创建限制性外键约束来做我们想要的事情。

例如:

testing=# create table a (id integer primary key);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "a_pkey" for table "a"
CREATE TABLE
testing=# create table b (id integer references a);
CREATE TABLE

-- put some data in the table
testing=# insert into a values(1);
INSERT 0 1
testing=# insert into a values(2);
INSERT 0 1
testing=# insert into b values(2);
INSERT 0 1
testing=# insert into b values(1);
INSERT 0 1

-- restricting works
testing=# delete from a where id=1;
ERROR:  update or delete on table "a" violates foreign key constraint "b_id_fkey" on table "b"
DETAIL:  Key (id)=(1) is still referenced from table "b".

-- find the name of the constraint
testing=# \d b;
       Table "public.b"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id)

-- drop the constraint
testing=# alter table b drop constraint b_a_id_fkey;
ALTER TABLE

-- create a cascading one
testing=# alter table b add FOREIGN KEY (id) references a(id) on delete cascade; 
ALTER TABLE

testing=# delete from a where id=1;
DELETE 1
testing=# select * from a;
 id 
----
  2
(1 row)

testing=# select * from b;
 id 
----
  2
(1 row)

-- it works, do your stuff.
-- [stuff]

-- recreate the previous state
testing=# \d b;
       Table "public.b"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) ON DELETE CASCADE

testing=# alter table b drop constraint b_id_fkey;
ALTER TABLE
testing=# alter table b add FOREIGN KEY (id) references a(id) on delete restrict; 
ALTER TABLE

当然,为了心理健康,我们应该将类​​似的内容抽象到一个过程中。

与注释一起使用:如注释中所指出:"这将删除对some_table具有外键约束的所有表的所有行,以及对这些表具有约束的所有表,等等"

在Postgres上,假设我们不想指定WHERE子句,则可以使用TRUNCATE命令:

TRUNCATE some_table CASCADE;

方便地,这是事务性的(即可以回滚),尽管它与其他并发事务没有完全隔离,并且还有其他一些警告。阅读文档以获取详细信息。