我有一个Postgresql数据库,我想做一些级联删除。但是,这些表不是用ON DELETE CASCADE规则设置的。有没有办法我可以执行一个删除,并告诉Postgresql级联它只是这一次?等价于
DELETE FROM some_table CASCADE;
这个老问题的答案似乎不存在这样的解决方案,但我想我要明确地问这个问题,只是为了确定。
我有一个Postgresql数据库,我想做一些级联删除。但是,这些表不是用ON DELETE CASCADE规则设置的。有没有办法我可以执行一个删除,并告诉Postgresql级联它只是这一次?等价于
DELETE FROM some_table CASCADE;
这个老问题的答案似乎不存在这样的解决方案,但我想我要明确地问这个问题,只是为了确定。
当前回答
该命令将删除所有具有指定表外键的表中的所有数据,以及对这些表具有外键的所有内容,依此类推。要极其谨慎地进行。
如果你真的想DELETE FROM some_table CASCADE;这意味着“删除表some_table中的所有行”,您可以使用TRUNCATE而不是DELETE,并且始终支持CASCADE。但是,如果想使用带有where子句的选择性删除,TRUNCATE不够好。
小心使用——这将删除在some_table上有外键约束的所有表的所有行,以及在这些表上有约束的所有表,等等。
Postgres支持使用TRUNCATE命令进行级联:
TRUNCATE some_table CASCADE;
这是事务性的(即可以回滚),尽管它没有完全与其他并发事务隔离,并且有其他几个注意事项。详细信息请阅读文档。
其他回答
该命令将删除所有具有指定表外键的表中的所有数据,以及对这些表具有外键的所有内容,依此类推。要极其谨慎地进行。
如果你真的想DELETE FROM some_table CASCADE;这意味着“删除表some_table中的所有行”,您可以使用TRUNCATE而不是DELETE,并且始终支持CASCADE。但是,如果想使用带有where子句的选择性删除,TRUNCATE不够好。
小心使用——这将删除在some_table上有外键约束的所有表的所有行,以及在这些表上有约束的所有表,等等。
Postgres支持使用TRUNCATE命令进行级联:
TRUNCATE some_table CASCADE;
这是事务性的(即可以回滚),尽管它没有完全与其他并发事务隔离,并且有其他几个注意事项。详细信息请阅读文档。
如果我理解正确的话,您应该能够通过删除外键约束、添加一个新的外键约束(它将级联)、做您的事情和重新创建限制外键约束来做您想做的事情。
例如:
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
当然,为了你的心理健康,你应该把这样的东西抽象成一个程序。
当你创建新表时,你可以添加一些约束,如UNIQUE,或NOT NULL,也可以告诉SQL当你试图删除行时,它应该做什么动作,它对另一个表有引用
CREATE TABLE company (
id SERIAL PRIMARY KEY,
name VARCHAR(128),
year DATE);
CREATE TABLE employee (
id SERIAL PRIMARY KEY,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
company_id INT REFERENCES company(id) ON DELETE CASCADE,
salary INT,
UNIQUE (first_name, last_name));
所以在这之后,你可以删除任何你需要的行,例如:
DELETE
FROM company
WHERE id = 2;
带cascade选项的删除只应用于定义了外键的表。如果您执行删除操作,而它告诉您不能删除,因为这会违反外键约束,级联将导致它删除违规行。
如果希望以这种方式删除关联的行,则需要首先定义外键。另外,请记住,除非您显式地指示它开始一个事务,或者更改默认值,否则它将进行自动提交,清理这可能非常耗时。
你可以用ON DELETE CASCADE来定义外键约束。 我引用外键约束的手册:
CASCADE指定当一个被引用的行被删除时, 引用它也应该被自动删除。