将外键/约束添加到 table 的小节

Add FK / Constraint to subsection of table

设置

这里有两个简化的* table可以说明我遇到的问题
*实际 table 的构建使得我无法真正重构列或轻松拆分它们

Table: CodeValues

| <b>Code<i>Set</i></b> | <b>Code<i>Value</i></b> | <b>Code<i>Text</i></b> |
|---------|-----------|----------|
| States  | 1         | Vermont  |
| States  | 2         | Hawaii   |
| YN      | 1         | Yes      |
| YN      | 2         | No       |
</pre>

其中CodeSet+CodeValue是复合主键

Table: Address

| <b>AddressID</b> | <b>Zip</b>   | <b>State</b> |
|-----------|-------|-------|
| 1         | 96701 | 2     |
| 2         | 05001 | 1     |
| 3         | 05602 | 1     |</pre>

其中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))

我担心的是,当它确实是一个 FK 时,数据库设计工具不会真正识别出此约束的全部影响,而只是针对 table.

的一个小节

一种方法使用的存储空间稍微多一点,但它可以满足您的需求:

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

?codevalues table 中 varchar() 列的长度。

幸运的是,您不需要触发器或用户定义的函数来完成此操作。

不幸的是,您需要在每一行中保留 codeset,这样会在 table.

中占用一点点 space