CASCADE删除一次

我有一个Postgresql数据库,我想要做几个级联删除。 但是,这些表不是用ON DELETE CASCADE规则设置的。 有什么办法可以执行删除,并告诉Postgresql级联它只是一次? 相当于的东西

DELETE FROM some_table CASCADE; 

这个老问题的答案似乎没有这样的解决scheme,但我想明确地问这个问题只是为了确定。

不需要。只需要为要级联的表编写删除语句即可。

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

USE WITH CARE – 正如在注释中指出的那样:“ 这将删除在some_table上具有外键约束的所有表的所有行以及对这些表具有约束的所有表等

在Postgres上,你可以使用TRUNCATE命令 ,假设你不想指定一个WHERE子句:

 TRUNCATE some_table CASCADE; 

这是事务性的(即可以回滚),虽然它不是完全与其他并发事务隔离,还有其他一些注意事项。 阅读文档的细节。

如果我理解正确,你应该能够通过删除外键约束,添加一个新的(这将级联),做你的东西,并重新创build限制外键约束能够做你想要的。

例如:

 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=# \db; 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=# \db; 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 

当然,为了你的心理健康,你应该把这样的东西抽象成一个程序。

我写了一个(recursion)函数来删除基于其主键的任何行。 我写这个,因为我不想创build我的约束作为“删除级联”。 我希望能够删除复杂的数据集(作为DBA),但不允许我的程序员能够级联删除而不用考虑所有的影响。 我仍在testing这个函数,所以可能会有一些错误 – 但是如果你的数据库有多列主键(也就是外键),请不要尝试它。 而且,键必须能够以stringforms表示,但是可以以不具有该限制的方式书写。 无论如何,我非常使用这个函数,我非常重视我的数据,以便对所有事物进行级联约束。 基本上,这个函数是通过模式,表名和主值(以stringforms)传递的,它将通过在表上find任何外键开始,并确保数据不存在 – 如果是,则recursion调用自己find的数据。 它使用已标记为删除的数据数组来防止无限循环。 请testing一下,让我知道它是如何工作的。 注意:这有点慢。 我这样称呼它: select delete_cascade('public','my_table','1');

 create or replace function delete_cascade(p_schema varchar, p_table varchar, p_key varchar, p_recursion varchar[] default null) returns integer as $$ declare rx record; rd record; v_sql varchar; v_recursion_key varchar; recnum integer; v_primary_key varchar; v_rows integer; begin recnum := 0; select ccu.column_name into v_primary_key from information_schema.table_constraints tc join information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name and ccu.constraint_schema=tc.constraint_schema and tc.constraint_type='PRIMARY KEY' and tc.table_name=p_table and tc.table_schema=p_schema; for rx in ( select kcu.table_name as foreign_table_name, kcu.column_name as foreign_column_name, kcu.table_schema foreign_table_schema, kcu2.column_name as foreign_table_primary_key from information_schema.constraint_column_usage ccu join information_schema.table_constraints tc on tc.constraint_name=ccu.constraint_name and tc.constraint_catalog=ccu.constraint_catalog and ccu.constraint_schema=ccu.constraint_schema join information_schema.key_column_usage kcu on kcu.constraint_name=ccu.constraint_name and kcu.constraint_catalog=ccu.constraint_catalog and kcu.constraint_schema=ccu.constraint_schema join information_schema.table_constraints tc2 on tc2.table_name=kcu.table_name and tc2.table_schema=kcu.table_schema join information_schema.key_column_usage kcu2 on kcu2.constraint_name=tc2.constraint_name and kcu2.constraint_catalog=tc2.constraint_catalog and kcu2.constraint_schema=tc2.constraint_schema where ccu.table_name=p_table and ccu.table_schema=p_schema and TC.CONSTRAINT_TYPE='FOREIGN KEY' and tc2.constraint_type='PRIMARY KEY' ) loop v_sql := 'select '||rx.foreign_table_primary_key||' as key from '||rx.foreign_table_schema||'.'||rx.foreign_table_name||' where '||rx.foreign_column_name||'='||quote_literal(p_key)||' for update'; --raise notice '%',v_sql; --found a foreign key, now find the primary keys for any data that exists in any of those tables. for rd in execute v_sql loop v_recursion_key=rx.foreign_table_schema||'.'||rx.foreign_table_name||'.'||rx.foreign_column_name||'='||rd.key; if (v_recursion_key = any (p_recursion)) then --raise notice 'Avoiding infinite loop'; else --raise notice 'Recursing to %,%',rx.foreign_table_name, rd.key; recnum:= recnum +delete_cascade(rx.foreign_table_schema::varchar, rx.foreign_table_name::varchar, rd.key::varchar, p_recursion||v_recursion_key); end if; end loop; end loop; begin --actually delete original record. v_sql := 'delete from '||p_schema||'.'||p_table||' where '||v_primary_key||'='||quote_literal(p_key); execute v_sql; get diagnostics v_rows= row_count; --raise notice 'Deleting %.% %=%',p_schema,p_table,v_primary_key,p_key; recnum:= recnum +v_rows; exception when others then recnum=0; end; return recnum; end; $$ language PLPGSQL; 

带级联选项的删除仅适用于定义了外键的表。 如果你做了一个删除,并且说你不能,因为它会违反外键约束,级联会导致它删除有问题的行。

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

您可以使用自动执行此操作,您可以使用ON DELETE CASCADE定义外键约束。
我引用了外键约束的手册 :

CASCADE指定当被引用的行被删除时,引用它的行也应该被自动删除。

我不能评论palehorse答案,所以我加了我自己的答案。 Palehorse logick是可以的,但是对于大数据集,效率可能不好。

 DELETE FROM some_child_table sct WHERE exists (SELECT FROM some_Table st where sct.some_fk_fiel=st.some_id ); DELETE FROM some_table; 

如果您在列上有索引并且数据集大于less量logging,则速度会更快。