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 TableC
→TableA
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?