我有一个Postgresql数据库,我想对它执行一些级联删除。但是,表没有设置ON DELETE CASCADE规则。有什么方法可以执行删除并告诉Postgresql只级联它一次吗?类似于
DELETE FROM some_table CASCADE;
this older question的答案似乎不存在这样的解决方案,但我想我应该明确地问这个问题,以确保万无一失。
我有一个Postgresql数据库,我想对它执行一些级联删除。但是,表没有设置ON DELETE CASCADE规则。有什么方法可以执行删除并告诉Postgresql只级联它一次吗?类似于
DELETE FROM some_table CASCADE;
this older question的答案似乎不存在这样的解决方案,但我想我应该明确地问这个问题,以确保万无一失。
9条答案
按热度按时间monwx1rj1#
不需要。如果只执行一次,只需为要级联的表编写delete语句。
ibrsph3r2#
* 此命令将删除具有指向指定表的外键的所有表中的所有数据,以及指向这些表的外键的所有内容,依此类推。请格外小心。*
如果您真的需要
DELETE FROM some_table CASCADE;
(表示“* 从表some_table
中删除所有行 *"),您可以使用TRUNCATE
代替DELETE
,并且CASCADE
始终受支持。但是,如果您想使用带有where
子句的选择性删除,TRUNCATE
就不够好了。USE WITH CARE-这将删除在
some_table
上具有外键约束的所有表的所有行,以及在这些表上具有约束的所有表,等等。Postgres支持
CASCADE
和TRUNCATE command:这是事务性的(也就是说可以回滚),尽管它没有完全与其他并发事务隔离,并且有一些其他的警告。
gorkyyrv3#
我写了一个(递归)函数来删除基于主键的任何行。我编写这个函数是因为我不想创建“on delete cascade”约束。我希望能够删除复杂的数据集(作为一个DBA),但不允许我的程序员能够级联删除而不考虑所有的影响。我仍然在测试这个函数,因此可能会有一些bug--但是如果数据库有多列主数据,请不要尝试(因此也是外部)键。另外,所有键都必须能够以字符串形式表示,但它可以用一种没有这种限制的方式来编写。无论如何,我非常稀疏地使用这个函数,我对数据的评价太高,以至于不能对所有内容启用级联约束。(字符串形式),它将从查找该表上的任何外键开始,并确保数据不存在--如果数据存在,它递归地调用它自己找到的数据。它使用一个数组的数据已经标记为删除,以防止无限循环。请测试一下,让我知道它如何为你工作。注意:有点慢。我是这么叫的:
select delete_cascade('public','my_table','1');
a2mppw5e4#
如果我理解正确的话,您应该能够通过删除外键约束、添加一个新的外键约束(将级联)、做您自己的事情以及重新创建限制外键约束来完成您想要做的事情。
例如:
当然,为了你的心理健康,你应该把这样的事情抽象成一个程序。
o4tp2gmn5#
是的,正如其他人所说,没有方便的'DELETE FROM my_table... CASCADE'(或等效的)。要删除非级联外键保护的子记录及其引用的祖先,您的选项包括:
我想,这是有意使绕过外键约束变得不方便;但我确实理解在特定情况下您为什么要这样做,如果您经常要这样做,并且如果您愿意无视各地DBA的智慧,那么您可能希望通过一个过程来自动化它。
几个月前,我来到这里寻找“级联删除一次”问题的答案(最初是在十多年前问的!)我从乔·洛夫的聪明解决方案中得到了一些好处(以及托马斯. G. deVilhena的变体),但最终我的用例有特殊的需求(例如,处理表内循环引用),这迫使我采取了一种不同的方法,这种方法最终变成了recursively_delete(PG 10.10)。
我在生产中使用recursively_delete已经有一段时间了,现在我终于(谨慎地)有足够的信心将它提供给其他可能在这里寻找想法的人。与Joe Love的解决方案一样,它允许您删除整个数据图,就好像数据库中的所有外键约束都被暂时设置为CASCADE一样,但它提供了一些额外的特性:
ikfrs5lh6#
我无法评论Palehorse的答案,所以我补充了自己的答案。Palehorse的逻辑是可以的,但在大数据集的情况下效率可能会很差。
如果列上有索引,并且数据集比几条记录大,则速度会更快。
6psbrbz97#
我接受了Joe Love的答案,并使用带有子选择的
IN
操作符而不是=
重写了它,以使函数更快(根据Hubbitus的建议):uinbv5nw8#
您可以使用来自动执行此操作,您可以使用
ON DELETE CASCADE
定义外键约束。我引用外键约束手册:
CASCADE
指定删除引用行时,引用该行的行也应自动删除。6ojccjat9#
带有级联选项的删除仅适用于定义了外键的表。如果执行删除操作,但由于会违反外键约束条件而显示不能执行,则级联将导致删除违规的行。
如果要以这种方式删除关联行,则需要首先定义外键。另外,请记住,除非显式指示它开始事务处理,或者更改默认值,否则它将执行自动提交,而这可能非常耗时。