检查另一个 Table 上引用唯一列的约束
Check Constraint Referencing Unique Column on another Table
我想限制可以在列中输入的可用值,但我想使用的值在另一个 table 中,它不是那个 [=32= 的主键]; table 的主键不包含在我的 table.
中
举个例子,假设我创建了一个 table 用于报告客户(列:Id、姓名、职务),它引用了现有的 table 客户职务(列:Id、标签)两个 tables 在 Id 上都有主键。我希望客户 table 用文字显示客户的头衔,而不是与客户关联的 title.Id。我知道客户标题列应该只包含来自标题 table 的值。我无法更改标题的结构 table.
以下是我考虑过但不太喜欢的三个选项:
1.I 无法使用外键引用 title.label 列,因为它不是主键。
2.I 可以创建一个检查约束并制作一个动态脚本以在使用标题标签更新客户 table 之前使用标题 table 中的值更新它,但这感觉非常手摇。
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.I 可以让它保持原状,完全忘记约束列,但我宁愿在可能的情况下添加约束,以尽可能地减少所有内容并提高查询性能。
所以,问题是:是否有一种 built-in 方法可以通过引用另一列 table 来引用一列(以限制或枚举值),而不必编写值的脚本某种程度上来说;一旦创建的东西将始终保持最新,就像外键关系一样,但不需要引用主键。
首先,就像 GordonLinoff 的评论一样,更好的方法是在 Customer
table 中包含 TitleID
。如果您无法更改 Customer
table 的布局,下面是一个选项。 foreign key
绝对比使用动态 T-SQL 来保持 check
约束更新更好。
I cannot reference the title.label column with a foreign key as it is
not a primary key.
外键可以引用任何候选键。它不必引用主键。
要告诉数据库有关候选键的信息,您可以创建一个唯一索引:
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);
我想限制可以在列中输入的可用值,但我想使用的值在另一个 table 中,它不是那个 [=32= 的主键]; table 的主键不包含在我的 table.
中举个例子,假设我创建了一个 table 用于报告客户(列:Id、姓名、职务),它引用了现有的 table 客户职务(列:Id、标签)两个 tables 在 Id 上都有主键。我希望客户 table 用文字显示客户的头衔,而不是与客户关联的 title.Id。我知道客户标题列应该只包含来自标题 table 的值。我无法更改标题的结构 table.
以下是我考虑过但不太喜欢的三个选项:
1.I 无法使用外键引用 title.label 列,因为它不是主键。
2.I 可以创建一个检查约束并制作一个动态脚本以在使用标题标签更新客户 table 之前使用标题 table 中的值更新它,但这感觉非常手摇。
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.I 可以让它保持原状,完全忘记约束列,但我宁愿在可能的情况下添加约束,以尽可能地减少所有内容并提高查询性能。
所以,问题是:是否有一种 built-in 方法可以通过引用另一列 table 来引用一列(以限制或枚举值),而不必编写值的脚本某种程度上来说;一旦创建的东西将始终保持最新,就像外键关系一样,但不需要引用主键。
首先,就像 GordonLinoff 的评论一样,更好的方法是在 Customer
table 中包含 TitleID
。如果您无法更改 Customer
table 的布局,下面是一个选项。 foreign key
绝对比使用动态 T-SQL 来保持 check
约束更新更好。
I cannot reference the title.label column with a foreign key as it is not a primary key.
外键可以引用任何候选键。它不必引用主键。
要告诉数据库有关候选键的信息,您可以创建一个唯一索引:
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);