I have a four tables, which look a bit like this:

CREATE TABLE [TableA]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY )
CREATE TABLE [TableB]
    ( [A_ID]  INT     NOT NULL FOREIGN KEY REFERENCES [TableA] ([ID]) 
    , [Value] TINYINT NOT NULL 
    , PRIMARY KEY ( [A_ID], [Value] ) )
CREATE TABLE [TableC]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY
    , [A_ID]  INT     NOT NULL FOREIGN KEY REFERENCES [TableA] ([ID]) )
CREATE TABLE [TableD]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY
    , [C_ID]  INT     NOT NULL FOREIGN KEY REFERENCES [TableC] ([ID])
    , [Value] TINYINT NOT NULL )

But I'd like to enforce referential integrity on TableD such that a valid value may only be one of the values from TableB of the TableA associated with the parent TableC record. For example:

TableA: ID 
         1
TableB: A_ID | VALUE
           1 |     1
           1 |     2
TableC: ID | A_ID
         7 |    1
TableD: ID | C_ID | VALUE
         1 |    7 |     1 -- Fine, Inserted
         1 |    7 |     2 -- Fine, Inserted
         1 |    7 |     3 -- Invalid, Rejected!

Now, I tried adding an A_ID column to TableD like this:

CREATE TABLE [TableD]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY
    , [C_ID]  INT     NOT NULL 
    , [A_ID]  INT     NOT NULL 
    , [Value] TINYINT NOT NULL
    , FOREIGN KEY ([C_ID], [A_ID]) REFERENCES [TableC] ([ID], [A_ID])
    , FOREIGN KEY ([A_ID], [Value]) REFERENCES [TableB] ([A_ID], [Value]) )

But I get the following error:

Msg 1776, Level 16, State 0, Line 2
There are no primary or candidate keys in the referenced table 'TableC' that match the referencing column list in the foreign key 'FK__TableD__TableC'.

Msg 1750, Level 16, State 0, Line 2
Could not create constraint. See previous errors.

I don't really like this solution anyway because it seems denormalized—since I have the TableCTableA relationship stored in two different places—but I can't think of any other way to enforce referential integrity (other than triggers, which I'd like to avoid).

Is there any way to achieve this?

有帮助吗?

解决方案

Yes, there is a way. You can add unique constraint to table TableC:

CREATE TABLE [TableC]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY
    , [A_ID]  INT     NOT NULL FOREIGN KEY REFERENCES [TableA] ([ID]),
     CONSTRAINT UK_TableC UNIQUE ([ID], [A_ID]) )

and then you will be able referencing TableC in table TableD as you specified:

CREATE TABLE [TableD]
    ( [ID]    INT     NOT NULL IDENTITY (1, 1) PRIMARY KEY
    , [C_ID]  INT     NOT NULL 
    , [A_ID]  INT     NOT NULL 
    , [Value] TINYINT NOT NULL
    , FOREIGN KEY ([C_ID], [A_ID]) REFERENCES [TableC] ([ID], [A_ID])
    , FOREIGN KEY ([A_ID], [Value]) REFERENCES [TableB] ([A_ID], [Value]) )
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top