简体   繁体   中英

Check Constraint Referencing Unique Column on another Table

I would like to limit the available values that can be entered in a column, but the values I would like to use are in another table, which is not the primary key of that table; the primary key of that table is not included in my table.

As an example, say I make a table for reporting of customers (Columns: Id, Name, Title) which references an existing table of customer titles (Columns: Id, Label) Both tables have primary keys on Id. I want the customers table to show the customer's title in words, not the title.Id associated with the customer. I know that the customer title column should only include values from the titles table. I cannot change the structure of the titles table.

Here are three options I have considered, but which I don't really like:

1.I cannot reference the title.label column with a foreign key as it is not a primary key.

2.I could create a check constraint and make a dynamic script to update it with the values in the titles table before updating the customers table with title labels, but this feels very hand cranked.

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 could just leave it be and forget about constraining the column at all, but I would rather add constraints where possible to keep everything battened down as much as possible and improve querying performance.

So, the question is this: is there a built-in way to reference one column (to limit or enumerate the values) by reference to another table, without having to script out the values in some way; something that once created will always be kept up to date, much as a foreign key relationship is but without the necessity to reference a primary key.

First, like GordonLinoff comments, the better approach is to include TitleID in the Customer table. Below is an option if you can't change the layout of the Customer table. A foreign key is definitely better than using dynamic T-SQL to keep a check constraint up to date.

I cannot reference the title.label column with a foreign key as it is not a primary key.

A foreign key can reference any candidate key. It doesn't have to reference the primary key.

To tell the database about candidate keys, you can create a unique index:

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

Another way to tell the database about a candidate key is a unique constraint:

alter table title add constraint uc_title_label unique (label);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM