我想限制可以在列中输入的可用值,但我想要使用的值在另一个表中,该表不是该表的主键;该表的主键未包含在我的表中。
作为一个例子,假设我创建了一个用于报告客户的表(列:Id,名称,标题),它引用了现有的客户标题表(列:Id,标签)两个表都有Id的主键。我希望customers表以单词显示客户的标题,而不是title.Id与客户相关联。我知道客户标题列应该只包含titles表中的值。我无法改变titles表的结构。
以下是我考虑过的三个选项,但我并不喜欢这些选项:
1.我不能用外键引用title.label列,因为它不是主键。
2.我可以创建一个检查约束并创建一个动态脚本,在使用标题标签更新customers表之前使用titles表中的值更新它,但这感觉非常简单。
DECLARE @TableName VARCHAR(50) = 'Customers'
DECLARE @FieldName VARCHAR(50) = 'Title'
DECLARE @SQL VARCHAR(MAX) = ''
SELECT @SQL = @SQL + '
OR ' + @FieldName + ' = ''' + Label + ''''
FROM dbo.Titles
ORDER BY Label
SELECT @SQL = 'ALTER TABLE dbo.' + @TableName + ' DROP CONSTRAINT chk_Customer' + @FieldName + '
ALTER TABLE dbo.' + @TableName + ' ADD CONSTRAINT chk_Customer_' + @FieldName + ' CHECK
(' + SUBSTRING(@SQL,6,LEN(@SQL)) + ')'
PRINT @SQL
3.我可以放弃它而忘记对列进行约束,但我宁愿在可能的情况下添加约束,以尽可能地减少所有内容,并提高查询性能。
所以,问题是:是否有一种内置方法可以通过引用另一个表来引用一列(限制或枚举值),而不必以某种方式编写值;曾经创建的东西将始终保持最新,就像外键关系一样,但没有必要引用主键。
答案 0 :(得分:1)
首先,与GordonLinoff评论一样,更好的方法是在TitleID
表中包含Customer
。如果您无法更改Customer
表的布局,则可以选择以下选项。 foreign key
肯定比使用动态T-SQL更新check
约束更好。
我无法按原样引用title.label列 不是主键。
外键可以引用任何候选键。它不必引用主键。
要告知数据库候选键,您可以创建一个唯一索引:
create table title (
id int primary key,
label varchar(50));
create table customer (
id int primary key,
title varchar(50));
create unique index ux_title_label on title(label);
alter table customer add constraint fk_customer_title
foreign key (title) references title(label);
告诉数据库有关候选键的另一种方法是一个唯一约束:
alter table title add constraint uc_title_label unique (label);