我想删除包含外键的行,但是当我尝试像这样做时:
DELETE FROM osoby WHERE id_osoby='1'
我收到了以下声明:
错误: 更新或删除“osoby”表上的行违反了“kontakty_ibfk_1”表对“kontakty”上的外键约束 细节: 由于表“kontakty”中仍引用了键(id_osoby)=(1),因此需要注意。
我如何删除这些行?
我想删除包含外键的行,但是当我尝试像这样做时:
DELETE FROM osoby WHERE id_osoby='1'
我收到了以下声明:
错误: 更新或删除“osoby”表上的行违反了“kontakty_ibfk_1”表对“kontakty”上的外键约束 细节: 由于表“kontakty”中仍引用了键(id_osoby)=(1),因此需要注意。
我如何删除这些行?
ON DELETE CASCADE
定义外键约束。
CASCADE
表示当参考行被删除时,引用它的行也应该被自动删除。
像这样查找当前的 FK 定义:
SELECT pg_get_constraintdef(oid) AS constraint_def
FROM pg_constraint
WHERE conrelid = 'public.kontakty'::regclass -- assuming public 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
语句中删除并重新创建约束。
显然您需要相应的权限。该操作将在表kontakty
上获取一个ACCESS EXCLUSIVE
锁和在表osoby
上获取一个SHARE ROW EXCLUSIVE
锁。
如果您无法对表进行ALTER
,那么手动删除(一次)或使用BEFORE DELETE
触发器(每次)是剩下的选项。
DELETE CASCADE
的表。我不能更改表结构。是否有一种方式可以自动删除外键?或者我们必须按照@juergen d建议的方法进行操作? - वरुणON DELETE CASCADE
添加FK来更改表,则手动删除(一次)或使用BEFORE DELETE
触发器(每次)是剩下的选项。 - Erwin BrandstetterON DELETE CASCADE
。 - 425nesp\d kontakty
。 - marquicus不建议将此作为通用解决方案,但如果需要删除未在生产环境或活跃使用中的数据库中的某些行,您可以尝试临时禁用涉及表格的触发器。
在我的情况下,我处于开发模式,并且有几个通过外键相互引用的表格。因此,在删除其中一个表格的所有行之前,删除它们的内容并不是很简单。所以,对我来说,按照以下方式删除它们的内容可以正常工作:
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/上有一些相关的好讨论。
如果外键仍然引用另一个表,则无法删除该外键。 首先删除引用。
delete from kontakty
where id_osoby = 1;
DELETE FROM osoby
WHERE id_osoby = 1;
这个问题已经有一段时间了,希望可以帮到您。由于您不能更改或修改数据库结构,可以按照PostgreSQL 文档进行操作。
TRUNCATE -- 清空一个表或一组表。
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
描述
TRUNCATE快速地从一组表中删除所有行。它与每个表上未有限定符的DELETE具有相同的效果,但由于它实际上不扫描表格,因此更快。此外,它会立即回收磁盘空间,而不需要随后的VACUUM操作。这在大型表格上最为有用。
截断othertable表,并级联到通过外键约束引用othertable的任何表格:
TRUNCATE othertable CASCADE;
重置相关的序列生成器:
TRUNCATE bigtable, fattable RESTART IDENTITY;
截断并重置任何相关的序列生成器:
TRUNCATE revinfo RESTART IDENTITY CASCADE ;
这意味着在表kontakty
中,您有一行引用了要删除的osoby
表中的行。您需要先删除该行或在表之间设置级联删除关系。
祝好运!
可以通过发布额外的SQL脚本来删除与FK
相关的记录,从而实现此目的。
为此,在DELETE
命令的WHERE
子句中使用子查询即可轻松完成所需操作。
类似于以下内容:
DELETE FROM kontakty
WHERE fk_column_from_kontakty_matching_id_osoby IN (
SELECT id_osoby FROM osoby WHERE id_osoby = '1'
);
DELETE FROM osoby WHERE id_osoby = '1';
kontakty
表中的FK
列与osoby.id_osoby
匹配的名称为fk_column_from_kontakty_matching_id_osoby
,因为无法从提供的错误消息中推断出来。id
,并且无法轻松地先获取id
然后再进行操作。
创建外键
时我们会先添加父级再添加子级
,所以在删除时我们需要先删除子级,再删除父级
;) - bonCodigo