将FK /约束添加到表的小节

时间:2019-04-30 21:08:43

标签: sql sql-server foreign-keys check-constraints

设置

这是两个简化的表格,它们说明了我遇到的问题
*构建实际表是为了使我无法真正重构列或轻松地将它们分开

表格: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时,不会真正认识到此约束的全部影响,而只是在表的一部分中。

1 个答案:

答案 0 :(得分:3)

一种方法使用了更多的存储空间,但是可以完成您想要的操作:

create table addresses (
    . . .,
    codeset as (convert(varchar(?), 'states')) persisted,
    foreign key (codeset, state) references codevalues (codeset, codevalue)
);

?代表varchar()表中codevalues列的长度。

很高兴,您不需要触发器或用户定义的函数即可完成此操作。

不幸的是,您需要在每一行中保留codeset,以免占用表中的一小部分空间。