我有三张桌子:
BallId Color
ball_1 red
ball_2 red
ball_3 blue
ball_4 green
ball_5 green
.......
BoxId Color
box_1 green
box_2 green
box_3 red
.......
BoxId BallId
box_1 ball4
box_1 ball5
box_3 ball2
我想在BoxId,BallId表上强制颜色关系,是否可能是示意图?
答案 0 :(得分:3)
我不太确定你的最终目标是什么。
如果您只是想确保底部表中的BoxId
和BallId
必须存在于前两个表中,那么您可以使用FOREIGN KEYs(又名“参照完整性”)。 / p>
---编辑---
基于其他评论/回复,我发现您确实希望确保通过第三个表连接的2行始终具有相同的颜色,但断开连接的行仍然可以拥有自己的颜色。
如果是这样,那么你可以“滥用”这样的键:
Ball:
BallId PK, AK1
Color AK1
Box:
BoxId PK, AK1
Color AK1
BallInBox
BallId PK
BoxId PK
Color
FK (BallId, Color) references Ball
FK (BoxId, Color) references Box
这是实际的DDL SQL:
delimiter $$
CREATE TABLE Ball (
BallId varchar(45) NOT NULL,
Color varchar(45),
PRIMARY KEY (BallId),
UNIQUE KEY Ball_AK1 (BallId, Color)
)$$
CREATE TABLE Box (
BoxId varchar(45) NOT NULL,
Color varchar(45),
PRIMARY KEY (BoxId),
UNIQUE KEY Box_AK1 (BoxId, Color)
)$$
CREATE TABLE BallInBox (
BallId varchar(45) NOT NULL,
BoxId varchar(45) NOT NULL,
Color varchar(45),
PRIMARY KEY (BallId, BoxId),
CONSTRAINT BallInBox_FK1 FOREIGN KEY (BallId, Color) REFERENCES Ball (BallId, Color),
CONSTRAINT BallInBox_FK2 FOREIGN KEY (BoxId, Color) REFERENCES Box (BoxId, Color)
)$$
BTW,这允许“基础”表和“连接”表中的NULL颜色。如果不是你想要的话,很容易添加NOT NULL约束。
答案 1 :(得分:2)
一种方法(虽然它不是严格的“原理图”)是在第三个表上有一个插入触发器,用于检查输入的球/盒的颜色,如果它们不相同则抛出异常< / p>
答案 2 :(得分:1)
我认为,就关系理论而言,这个问题的答案如下:你在这里真正说的是你有一套盒子和一组球,每个球都放在一个盒子里。盒子和球每个都有一种颜色,球只能在一个匹配颜色的盒子里。但是将球的颜色存储在球桌中是一个设计错误。相反,你应该只存储每个球所在的盒子,然后你知道球是什么颜色,因为你可以检查它所存储的盒子的颜色(使用连接)。
所以,不,没有你可以指定的约束来强制执行你想要的关系,但那是因为你以错误的方式解决这个问题。你不应该在球表中有Color
列。
编辑:以上假设每个球必须在一个盒子里。 OP澄清说不是每个球都需要在一个盒子里。这似乎是一个更难的问题,因为在这种情况下你不能依靠盒子表来跟踪球的颜色。我可以看到一些不同的解决方案,但都不是完美的。
答案 3 :(得分:1)
可以使用复合外键通过数据库执行此操作:
create table ball
(id int unsigned not null primary key auto_increment,
color varchar(10)) engine=InnoDB;
create table box
(id int unsigned not null primary key auto_increment,
color varchar(10)) engine=InnoDB;
create table boxBallRule
(ballId int unsigned not null,
boxId int unsigned not null,
PRIMARY KEY (ballId,boxId),
CONSTRAINT `boxBallRule_box_fk1` FOREIGN KEY (boxId) references `box` (id),
CONSTRAINT `boxBallRule_ball_fk1` FOREIGN KEY (ballId) references `ball` (id)
) engine=InnoDB;
create table boxBall
(id int unsigned primary key auto_increment not null,
ballId int unsigned not null,
boxId int unsigned not null,
CONSTRAINT `boxBallColorRule_fk1` FOREIGN KEY (ballId,boxId) references boxBallRule(ballId,boxId)
) engine=InnoDB;
然后,您可以在boxBallRule
表中的哪个框中存储允许的球。任何不符合“允许”框与球关系的boxBall
表中的插入都将失败。因此:
insert into ball (color) values ('red');
insert into ball (color) values ('blue');
insert into ball (color) values ('green');
insert into box (color) values ('red');
insert into box (color) values ('blue');
insert into box (color) values ('green');
insert into boxBallRule (ballId,boxId) values ((select id from ball where color = 'red'),(select id from box where color = 'red'));
insert into boxBallRule (ballId,boxId) values ((select id from ball where color = 'blue'),(select id from box where color = 'blue'));
insert into boxBallRule (ballId,boxId) values ((select id from ball where color = 'green'),(select id from box where color = 'green'));
-- Let's try and put a red ball in a green box.
-- The DB should not allow us to do this!
insert into boxBall (ballId,boxId) values
((select id from ball where color = 'red'),
(select id from box where color = 'green'));
最后一个语句应该失败,因为它违反了boxBallRule
表上的复合外键。