基于SQL Server中引用表中的值创建约束

时间:2018-06-20 10:13:18

标签: sql-server

我有两个表:

铅笔:

ID(PK): 0,1,2,3

Pencil: Type1, Type2, Type3, Type4

Color_ID(FK, references Colors(ID)): 0,0,0,0

颜色:

ID(PK):0,1,2

Color:Red, Blue, Green

Availability:Yes, No, No

我想在Pencil表中创建约束,以便用户无法输入其可用性为No的颜色的Color_ID值。这样做的最佳方法是什么?谢谢。

1 个答案:

答案 0 :(得分:1)

您可以在包含可用性信息的颜色表中添加superkey,然后将外键与计算列一起使用以确保其受约束:

create table Colors (
    ID int not null,
    Name varchar(30) not null,
    Available bit not null,
    constraint PK_Colors PRIMARY KEY (ID),
    constraint UQ_Color_Names UNIQUE (Name),
    constraint UQ_Color_AvailabilityXRef UNIQUE (ID,Available)
)
go
create table Pencils (
    ID int not null,
    Pencil varchar(20) not null,
    ColorID int not null,
    _Available as CAST(1 as bit) persisted,
    constraint PK_Pencils PRIMARY KEY (ID),
    constraint FK_Pencil_Colors FOREIGN KEY (ColorID) references Colors (ID),
    constraint FK_PenciL_Color_AvailabilityXRef FOREIGN KEY (ColorID,_Available) 
                                                      references Colors (ID,Available)
)

您会注意到,严格来说,FK_Pencil_Colors现在是多余的。我更喜欢保留它,因为它是“真实”的FK,但其他人可能会选择放弃它。

还请注意,这可以防止在仍然有铅笔引用该颜色的情况下使该颜色不可用,这是在此处增加的限制条件。 1

最后,根据我的惯例,当名称不打算由“其他人”使用时,我会在名称前加上_。他们在那里是为了帮助我构建DRI。


1 Jeroen所述,这实际上可能不是您想要的行为。请记住,约束通常会陈述“永恒的真理”。如果这是一个约束,那么应该可以删除并重新插入数据而不会违反约束。如果您有一个 temporal 要求,例如“在插入行的时间点X和Y应该为true ”,那么通常最好处理这个问题使用触发器。