检查另一个表上的约束引用唯一列

时间:2015-02-20 11:38:59

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

我想限制可以在列中输入的可用值,但我想要使用的值在另一个表中,该表不是该表的主键;该表的主键未包含在我的表中。

作为一个例子,假设我创建了一个用于报告客户的表(列: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.我可以放弃它而忘记对列进行约束,但我宁愿在可能的情况下添加约束,以尽可能地减少所有内容,并提高查询性能。

所以,问题是:是否有一种内置方法可以通过引用另一个表来引用一列(限制或枚举值),而不必以某种方式编写值;曾经创建的东西将始终保持最新,就像外键关系一样,但没有必要引用主键。

1 个答案:

答案 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);