我想删除包含外键的行,但是当我尝试这样的事情时:
DELETE FROM osoby WHERE id_osoby='1'
我得到这样的声明:
错误:表“osoby”上的更新或删除违反表“kontakty”上的外键约束“kontakty_ibfk_1” 详细信息:Key(id_osoby)=(1)仍然从表“kontakty”中引用。
如何删除这些行?
答案 0 :(得分:59)
要自动执行此操作,您可以使用ON DELETE CASCADE
定义外键约束
我引用the manual of foreign key constraints:
CASCADE
指定删除引用的行时,行 引用它也应该被自动删除。
查找当前的FK定义:
SELECT pg_get_constraintdef(oid) AS constraint_def
FROM pg_constraint
WHERE conrelid = 'public.kontakty'::regclass -- assuming pubic schema
AND conname = 'kontakty_ibfk_1';
然后在以下语句中将ON DELETE ...
部分添加或修改为ON DELETE CASCADE
(保留其他所有内容):
ALTER TABLE kontakty
DROP CONSTRAINT kontakty_ibfk_1
, ADD CONSTRAINT kontakty_ibfk_1
FOREIGN KEY (id_osoby) REFERENCES osoby (id_osoby) ON DELETE CASCADE;
由于没有ALTER CONSTRAINT
语法,请在单个ALTER TABLE
语句中删除并重新创建约束。这可以避免可能的并发写访问的竞争条件。
显然,您需要这样做的权限。该操作会对表ACCESS EXCLUSIVE
上的kontakty
锁定以及对表SHARE ROW EXCLUSIVE
的{{1}}锁定。
如果您不能osoby
表格,则手动删除(一次)或触发ALTER
(每次)都是其余选项。
答案 1 :(得分:30)
如果仍然引用另一个表,则无法删除外键。 首先删除参考
delete from kontakty
where id_osoby = 1;
DELETE FROM osoby
WHERE id_osoby = 1;
答案 2 :(得分:16)
不应该建议将其作为一般解决方案,但是对于未生产或正在使用的数据库中的一次性删除行,您可以暂时禁用相关表上的触发器。
在我的情况下,我处于开发模式并且有几个表通过外键相互引用。因此,删除它们的内容并不像从一个表中删除所有行之前那样简单。所以,对我来说,删除它们的内容工作正常如下:
ALTER TABLE table1 DISABLE TRIGGER ALL;
ALTER TABLE table2 DISABLE TRIGGER ALL;
DELETE FROM table1;
DELETE FROM table2;
ALTER TABLE table1 ENABLE TRIGGER ALL;
ALTER TABLE table2 ENABLE TRIGGER ALL;
您应该能够根据需要添加WHERE子句,当然要小心避免破坏数据库的完整性。
在http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/
进行了一些很好的相关讨论答案 3 :(得分:10)
自问这个问题以来已经有一段时间了,希望可以提供帮助。 因为您无法更改或更改数据库结构,所以可以执行此操作。根据postgresql docs。
TRUNCATE - 清空一个表或一组表。
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
<强>描述强>
TRUNCATE会快速删除一组表中的所有行。它与每个表上的非限定DELETE具有相同的效果,但由于它实际上不扫描表,因此速度更快。此外,它立即回收磁盘空间,而不是需要后续的VACUUM操作。这对大型表格最有用。
截断表othertable,并级联到任何通过外键约束引用其他表的表:
TRUNCATE othertable CASCADE;
同样,并重置任何相关的序列生成器:
TRUNCATE bigtable, fattable RESTART IDENTITY;
截断并重置任何相关的序列生成器:
TRUNCATE revinfo RESTART IDENTITY CASCADE ;
答案 4 :(得分:6)
这意味着在表kontakty
中,您有一行引用您要删除的osoby
中的行。您必须先删除该行,或者在表之间的关系上设置级联删除。
Powodzenia!