我想删除包含外键的行,但是当我尝试这样的操作时:
DELETE FROM osoby WHERE id_osoby='1'
我得到以下声明:
错误:对表“ osoby”的更新或删除违反了表“ kontakty”上的外键约束“ kontakty_ibfk_1”详细信息:密钥(id_osoby)=(1)仍从表“ kontakty”中引用。
如何删除这些行?
我想删除包含外键的行,但是当我尝试这样的操作时:
DELETE FROM osoby WHERE id_osoby='1'
我得到以下声明:
错误:对表“ osoby”的更新或删除违反了表“ kontakty”上的外键约束“ kontakty_ibfk_1”详细信息:密钥(id_osoby)=(1)仍从表“ kontakty”中引用。
如何删除这些行?
Answers:
要自动执行此操作,可以使用定义外键约束ON DELETE CASCADE
。
我引用外键约束手册:
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
锁定表osoby
。
如果不能 ALTER
表格,则BEFORE DELETE
剩下的选项是手动(一次)或触发器(每次)删除。
DELETE CASCADE
。我无法更改表的结构。有没有一种方法可以自动删除外键?或者我们要遵循@juergen d建议的方式
ALTER
在表中添加带有的FK ON DELETE CASCADE
,则BEFORE DELETE
剩下的选项是手动(一次)或触发器(每次)删除。
ON DELETE CASCADE
在create语句中使用外键将其添加到列中。
\d kontakty
不应该将其推荐为一种通用解决方案,但是要一次性删除不在生产环境中或正在使用中的数据库中的行,则可以暂时禁用有关表的触发器。
就我而言,我处于开发模式,并且有几个表通过外键相互引用。因此,删除它们的内容并不像从一个表中删除所有行先于另一表那样简单。因此,对我来说,按如下所示删除它们的内容效果很好:
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/中有一些很好的相关讨论
提出这个问题已经有一段时间了,希望能有所帮助。因为您不能更改或更改db结构,所以可以执行此操作。根据PostgreSQL文档。
TRUNCATE-清空一个表或一组表。
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
描述
TRUNCATE快速从一组表中删除所有行。它与在每个表上进行不限定DELETE的效果相同,但是由于它实际上并不扫描表,因此速度更快。此外,它可以立即回收磁盘空间,而不需要随后的VACUUM操作。这在大型表上最有用。
截断其他表,并通过外键约束级联到引用其他表的任何表:
TRUNCATE othertable CASCADE;
相同,并重置所有关联的序列生成器:
TRUNCATE bigtable, fattable RESTART IDENTITY;
截断并重置任何关联的序列生成器:
TRUNCATE revinfo RESTART IDENTITY CASCADE ;
creating foreign keys
我们add parent then child
。因此,当删除我们时delete child and then parent
;)