将外键/约束添加到 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
设置
这里有两个简化的* 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.