这是两个简化的表格,它们说明了我遇到的问题
*构建实际表是为了使我无法真正重构列或轻松地将它们分开
CodeValues
| CodeSet | CodeValue | CodeText |
|---------|-----------|----------|
| States | 1 | Vermont |
| States | 2 | Hawaii |
| YN | 1 | Yes |
| YN | 2 | No |
其中CodeSet
+ CodeValue
是复合主键
Address
| AddressID | Zip | State |
|-----------|-------|-------|
| 1 | 96701 | 2 |
| 2 | 05001 | 1 |
| 3 | 05602 | 1 |
AddressID
是主键
要添加到Address.State
的适当数据库约束是什么?
它应该始终是CodeValues Where CodeSet = 'States'
中存在的值,但是我不相信我可以创建一个Foreign Key that is part of a Composite Primary Key
应该只是这样的check constraint based on a query吗?
CREATE FUNCTION checkCodeValues(
@codeSet VARCHAR(50),
@codeValue SMALLINT
)
RETURNS BIT
AS
BEGIN
IF EXISTS (SELECT * FROM CodeValues WHERE CodeSet = @codeSet
AND CodeValue = @codeValue)
RETURN 1
RETURN 0
END
ALTER TABLE Address
WITH CHECK ADD CONSTRAINT CK_State
CHECK (checkCodeValues('States', State))
我担心的是,db设计工具在真正是FK时,不会真正认识到此约束的全部影响,而只是在表的一部分中。
答案 0 :(得分:3)
一种方法使用了更多的存储空间,但是可以完成您想要的操作:
create table addresses (
. . .,
codeset as (convert(varchar(?), 'states')) persisted,
foreign key (codeset, state) references codevalues (codeset, codevalue)
);
?
代表varchar()
表中codevalues
列的长度。
很高兴,您不需要触发器或用户定义的函数即可完成此操作。
不幸的是,您需要在每一行中保留codeset
,以免占用表中的一小部分空间。