我有三个表,表 A 有一个自动递增的唯一主键,另外两个(表 B 和 C)的主键有一个外键约束,将它们与第一个表的主键联系起来。
我想制定一个约束,以保持第二个和第三个表中的所有行不能包含任何重复项,并且对于表 A 中的所有记录,B 或 C 中都有匹配的记录。
所以基本上 A 类型的记录可以是 B 或 C 类型,并且必须是 B 或 C 之一。
是否可以在没有触发器的情况下在 MySQL 中进行此约束?还是需要触发器?
谢谢你的帮助。
我有三个表,表 A 有一个自动递增的唯一主键,另外两个(表 B 和 C)的主键有一个外键约束,将它们与第一个表的主键联系起来。
我想制定一个约束,以保持第二个和第三个表中的所有行不能包含任何重复项,并且对于表 A 中的所有记录,B 或 C 中都有匹配的记录。
所以基本上 A 类型的记录可以是 B 或 C 类型,并且必须是 B 或 C 之一。
是否可以在没有触发器的情况下在 MySQL 中进行此约束?还是需要触发器?
谢谢你的帮助。
您可以使用“类型”表:
CREATE TABLE Type
( type_code CHAR(1) NOT NULL
, PRIMARY KEY (type_code)
) ;
正好有 2 行(与您需要的不同子类型表一样多:
INSERT INTO Type (type_code)
VALUES ('B'), ('C') ;
超类型表(包括引用“类型”的列):
CREATE TABLE A
( a_id INT NOT NULL AUTO_INCREMENT
, type_code CHAR(1) NOT NULL
, PRIMARY KEY (a_id)
, UNIQUE KEY (type_code, a_id)
, FOREIGN KEY (type_code)
REFERENCES Type (type_code)
) ;
子类型表(现在引用 A 的主键和 type_code 的组合:
CREATE TABLE B
( a_id INT NOT NULL
, type_code CHAR(1) NOT NULL DEFAULT 'B'
, PRIMARY KEY (type_code, a_id)
, FOREIGN KEY (type_code, a_id)
REFERENCES A (type_code, a_id)
, CHECK (type_code = 'B')
) ;
CREATE TABLE C
( a_id INT NOT NULL
, type_code CHAR(1) NOT NULL DEFAULT 'C'
, PRIMARY KEY (type_code, a_id)
, FOREIGN KEY (type_code, a_id)
REFERENCES A (type_code, a_id)
, CHECK (type_code = 'C')
) ;
CHECK
如果只有 MySQL 实现了约束,上述内容将可以正常工作。但事实并非如此。因此,要绝对确保您的所有规范都得到执行,而不是'B'
在表中插入类型数据C
,您必须再添加 2 个“类型”表(并删除 MySQLCHECK
约束中无用的表):
CREATE TABLE TypeB
( type_code CHAR(1) NOT NULL
, PRIMARY KEY (type_code)
) ;
CREATE TABLE TypeC
( type_code CHAR(1) NOT NULL
, PRIMARY KEY (type_code)
) ;
每行恰好有 1 行:
INSERT INTO TypeB (type_code)
VALUES ('B') ;
INSERT INTO TypeC (type_code)
VALUES ('C') ;
和额外的 FK:
ALTER TABLE B
ADD FOREIGN KEY (type_code)
REFERENCES TypeB (type_code) ;
ALTER TABLE C
ADD FOREIGN KEY (type_code)
REFERENCES TypeC (type_code) ;
有了这些约束,表 A 的每一行都将属于 B 或 C 类型,并且将在相应的表(B 或 C)中,并且永远不会在两者中。
如果您还想确保它们恰好在一个表中(并且从不在 B 或 C 中),则在插入 A 时应注意这一点(所有插入都应通过强制执行该要求的事务完成)。