有没有办法添加约束以确保一列中的X条目只允许在另一列中输入Y?
假设我有两个表,剥离到最小列,tbl_1有一个pk。 tbl_2有2列 - 一个pk和一个文本字符串。
这些表由第三个关系表连接,因为它们是多对多的,它使用来自tbl1和tbl2的pk。
t1_pk t2_pk | t2_str t1fk | t2fk
x 1 AAA x 1
y 2 BBB x 2
z 3 AAA y 3
4 BBB y 4
z 1
z 2
上面的所有条目都是允许的,但现在我试图找出如何限制关系表,以便附加到t2_pk的字符串只能绑定到t1_pk ONCE。例如。在第3个表中:
t1fk | t2fk
x 3
不允许因为x-1存在且1和3都附加了字符串AAA。我可以想到的另一种方法是不另外制作3个表并绕圈转动,就是将字符串移动到关系表并添加约束,这样如果表中存在t2fk数字,那么它只会再次允许该数字。伴随着相同的字符串。
是否有一个后台进程,我可以声明添加一个唯一约束,还是只需要由存储过程强加?
答案 0 :(得分:1)
要么将t2_str列添加到包含关系的第三个表,要么为此创建新表。这里有一个如何实现新表tab_constr。
的示例drop table if exists tab_constr;
drop table if exists tab_rel;
drop table if exists tab_1;
drop table if exists tab_2;
CREATE TABLE tab_1 (
t1_pk varchar(5),
PRIMARY KEY (t1_pk)
);
CREATE TABLE tab_2 (
t2_pk INT,
t2_str varchar(10) NOT NULL,
PRIMARY KEY (t2_pk),
INDEX(t2_pk, t2_str)
);
CREATE TABLE tab_rel (
t1_pk varchar(5),
t2_pk INT,
PRIMARY KEY (t1_pk,t2_pk),
INDEX (t2_pk),
FOREIGN KEY (t1_pk) REFERENCES tab_1(t1_pk),
FOREIGN KEY (t2_pk) REFERENCES tab_2(t2_pk)
);
CREATE TABLE tab_constr (
t1_pk varchar(5),
t2_str varchar(10),
t2_pk int,
PRIMARY KEY pair_already_exists(t1_pk,t2_str),
INDEX(t1_pk, t2_pk),
INDEX(t2_pk, t2_str),
FOREIGN KEY (t1_pk, t2_pk) REFERENCES tab_rel(t1_pk, t2_pk)
ON DELETE CASCADE,
FOREIGN KEY (t2_pk, t2_str) REFERENCES tab_2(t2_pk, t2_str)
ON UPDATE CASCADE
);
CREATE TRIGGER tr_ins_rel AFTER INSERT ON tab_rel
FOR EACH ROW
BEGIN
INSERT INTO tab_constr ( t1_pk, t2_str, t2_pk)
select new.t1_pk, t2_str, new.t2_pk
from tab_2
where t2_pk=new.t2_pk
;
END;
INSERT INTO tab_1 (t1_pk) VALUES ('x');
INSERT INTO tab_1 (t1_pk) VALUES ('y');
INSERT INTO tab_1 (t1_pk) VALUES ('z');
INSERT INTO tab_2 (t2_pk,t2_str) VALUES (1, 'AAA');
INSERT INTO tab_2 (t2_pk,t2_str) VALUES (2, 'BBB');
INSERT INTO tab_2 (t2_pk,t2_str) VALUES (3, 'AAA');
INSERT INTO tab_2 (t2_pk,t2_str) VALUES (4, 'BBB');
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('x', 1);
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('x', 2);
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('y', 3);
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('y', 4);
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('z', 1);
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('z', 2);
commit;
以下语句将引发错误:
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('x', 3);
这也会引发错误
UPDATE tab_2 set t2_str='BBB' where t2_pk=1;
但这会起作用
DELETE FROM tab_rel where t1_pk='x' and t2_pk=1;
INSERT INTO tab_rel (t1_pk,t2_pk) VALUES ('x', 3);
这将起作用
UPDATE tab_2 set t2_str='XXX' where t2_pk=1;
Here你可以尝试一下。
当然,这个附加表违反了正常形式,并为数据库增加了冗余。但这没有问题,因为这个表tab_constr是一个像索引一样的辅助结构,它将由数据库自动维护。因此,不会发生插入/更新/删除异常。