PostgreSQL:删除从另一个表引用的行

lau*_*urt 5 sql postgresql referential-integrity foreign-keys

我有两个表,object和object_data,对象通过外键引用object_data(关系是1:1).对于一组对象,我需要将其object_data引用置空并删除相应的object_data行,如下所示:

DELETE FROM object_data WHERE id IN
( SELECT object_data_id FROM object WHERE ... );

UPDATE object SET object_data_id = NULL WHERE ...;
Run Code Online (Sandbox Code Playgroud)

问题是,外键约束不允许删除仍然从对象引用的object_data行.

我当前的解决方案是将结果读SELECT入列表,然后将外键置零,然后使用IN运算符以合理大小的批量删除object_data行.有更好的解决方案吗?添加从object_data引用回对象的列不是一个选项.

Erw*_*ter 6

Sonds就像ON UPDATE SET NULL你的FK约束的修饰符一样完美.每个文件:

SET NULL

将引用列设置为null.

ALTER TABLE object DROP CONSTRAINT <fk_name_here>;

ALTER TABLE object ADD CONSTRAINT <fk_name_here>
FOREIGN KEY ON (object_data_id) REFERENCES object_data (object_data_id)
ON DELETE SET NULL;
Run Code Online (Sandbox Code Playgroud)

猜猜PK的名字object_data_id也是.那你需要的只是:

DELETE FROM object_data WHERE id ...
Run Code Online (Sandbox Code Playgroud)

Reverences object自动设置为NULL.

除此之外,这听起来很奇怪:

我有两个表,object和object_data,对象通过外键引用object_data(关系是1:1)

通常情况下,我希望引用是从倒过来object_data ,以 object这样的场景,但是这只是从表名猜测.


Eel*_*lke 5

是,使用CTE(公用表表达式)

WITH tmp AS (SELECT object_data_id FROM object WHERE ...),
    upd AS (UPDATE object SET object_data_id = NULL WHERE ...)
DELETE FROM object_data 
  WHERE id IN (SELECT object_data_id FROM tmp);
Run Code Online (Sandbox Code Playgroud)

首先执行名为tmp的第一个CTE,并在以后记住您需要的数据。第二个称为upd的CTE会将字段设置为NULL。最后,DELETE使用tmp中的数据执行DELETE