有table1:
CREATE TABLE table1
(
id serial NOT NULL,
CONSTRAINT pk_table1_id PRIMARY KEY (id),
)
有table2:
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
答案 0 :(得分:0)
您可以使用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
答案 1 :(得分:0)
简短的回答是:你做不到。
外键的目的是验证当该属性具有值时,该值在引用的表中(除非值为NULL时---表中不需要存在NULL)。
两个建议:
解决方案1.将元组保留在表2中,不要删除它。相反,添加一个布尔属性,确定元组是否已被删除。
专门针对您的问题。添加删除到表的属性。 将if设置为false。并且当元组被删除时 创建一个触发器,将此属性设置为true。这很麻烦 并且容易出错。
解决方案2(这是我首选的解决方案)。您可以使用通过触发器管理的第三个表。 每次添加table2中的元组时,table3的元组都是 添加。表3只有一个属性(您想拥有的属性) 引用的外键)。 Table3将是属于Table2的属性的所有值的集合。添加到Table3的触发器应该使用upsert,以防之前已经看到添加的属性。 然后,Table1将使用指向Table3的外键约束。