有表1:
CREATE TABLE table1
(
id serial NOT NULL,
CONSTRAINT pk_table1_id PRIMARY KEY (id),
)
有表2:
CREATE TABLE table2
(
id serial NOT NULL,
fk_1 integer,
CONSTRAINT fk_to_table1 FOREIGN KEY (fk_1)
REFERENCES table1 (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
NOT VALID
)
当我尝试从table1删除一些行时,我得到了异常:
UPDATE or DELETE in the table "table1" violates the foreign key constraint "fk_to_table1" of the table "table2"
如果删除了来自table1的外键的行,是否有某种方法可以在table2中保留(保存)具有相同值的行(fk_1(来自table1的id)?
示例:表1:
id
1
2
3
Teble2:
id fk_1
1 | 1
2 | 1
3 | 3
4 | 2
从table1删除第一行后我想看到的内容:
表格1:
id
2
3
Teble2:
id fk_1
1 | 1
2 | 1
3 | 3
4 | 2
你可以使用ON DELETE SET NULL
做到这一点:
CREATE TABLE table2
(
id int NOT NULL,
fk_1 integer,
CONSTRAINT fk_to_table1 FOREIGN KEY (fk_1)
REFERENCES table1 (id)
ON UPDATE CASCADE
ON DELETE SET NULL
);
insert into table1 values (1), (2);
insert into table2 values (1,1), (2,1), (3,2), (4,2);
然后,如果你运行:
delete from table1
where id = 1;
表2将如下所示:
id | fk_1
---+-----
1 |
2 |
3 | 2
4 | 2
简短的回答是:你做不到。
外键的目的是验证只要该属性具有值,该值就在引用的表中(除非值为NULL ---表中不需要NULL)。
两个建议:
解决方案1.将元组保留在表2中,不要删除它。相反,添加一个布尔属性,确定是否已删除元组。
专门针对您的问题。添加删除到表的属性。将if设置为false。当删除元组时,创建一个触发器,将此属性设置为true。这很麻烦且容易出错。
解决方案2(这是我的首选解决方案)。您可以使用通过触发器管理的第三个表。每次添加table2中的元组时,都会添加一个表3的元组。表3只有一个属性(您希望引用外键的属性)。 Table3将是属于Table2的属性的所有值的集合。添加到Table3的触发器应该使用upsert,以防之前已经看到添加的属性。然后,Table1将具有指向Table3的外键约束。