我需要设置约束,以便仅当该表中的另一列具有特定值时该表才接受来自其他表的外键。
数据库相当复杂,但让我举个例子:
餐桌福:
Foo_id | Foo_value | Another values...
1 | "GOOD" |
2 | "BAD" |
3 | "GOOD" |
桌栏:
Bar_id | Foo_id(FK) | Another values...
1 | 1 |
2 | 1 |
3 | 3 |
如您所见,Bar 应该只接受来自 Foo 的接受 id,其中 Foo_Value 为“GOOD”。
我尝试添加检查约束,但它不接受 WHERE 语句,因此我无法访问 Foo_Value。我尝试搜索,但我找不到任何东西,或者我对此的解释是错误的。
可能唯一的方法是使用
trigger
(用于插入/更新):
create trigger chk_bar before insert on bar /* before update */
for each row
begin
if not exists (SELECT 1 FROM foo
WHERE Foo_value = 'GOOD' AND foo_id = new.foo_id) then
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid FK';
end if;
end;
请记住在更新
foo
-> GOOD
时在 BAD
上添加另一个触发器,或删除该触发器,以检查引用完整性。
MySQL 直到 8.0.16 版本才实现 CHECK 约束。
仅当外键包含您的 Foo_value 列时,您才可以使用外键强制执行您的规则。这意味着您的父表中需要一个额外的 KEY。
ALTER TABLE Foo ADD UNIQUE KEY (Foo_id, Foo_value);
ALTER TABLE Bar ADD COLUMN Foo_value VARCHAR(4) DEFAULT 'GOOD',
ADD FOREIGN KEY (Foo_id, Foo_value) REFERENCES Foo (Foo_id, Foo_value);
由于无法使用 CHECK 约束,因此必须使用触发器来确保 Bar.Foo_value 为“GOOD”:
CREATE TRIGGER BarInsertFooValueGood BEFORE INSERT ON Bar FOR EACH ROW
SET Foo_value = 'GOOD';
CREATE TRIGGER BarUpdateFooValueGood BEFORE UPDATE ON Bar FOR EACH ROW
SET Foo_value = 'GOOD';