Sql 在远程相关表之间强制执行引用完整性

Sql 在远程相关表之间强制执行引用完整性,sql,sql-server,tsql,database-normalization,referential-integrity,Sql,Sql Server,Tsql,Database Normalization,Referential Integrity,我有四张桌子,看起来有点像这样: 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

我有四张桌子,看起来有点像这样:

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 )
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]) )
但是我想在
TableD
上强制引用完整性,这样有效值只能是
table a
中与父
table c
记录关联的
table b
中的一个值。例如:

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!
现在,我尝试将
A_ID
列添加到
表格中,如下所示:

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 )
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]) )
但我得到了以下错误:

味精1776,第16级,状态0,第2行
引用的表“
TableC
”中没有与外键“
FK\u TableD\u TableC
”中的引用列列表匹配的主键或候选键

Msg 1750,第16级,第0状态,第2行
无法创建约束。请参阅前面的错误

无论如何,我并不真的喜欢这个解决方案,因为我有
表c
TableA
关系存储在两个不同的位置,但我想不出任何其他方法来强制引用完整性(触发器除外,我希望避免)


有没有办法做到这一点?

是的,有办法。您可以将
unique
约束添加到表
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]) )
然后,您将能够在表
TableD
中引用指定的
table c

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

那不是外键的用途。他们只是在那里检查父记录是否存在。不强制执行特定的祖先计数。你想要一个
检查
约束。@MarcB你能提供一个例子吗?@MarcB我看到了,但我不知道如何在我的案例中应用它。它不能仅仅是一个简单的函数调用,它必须类似于
CHECK([Value]IN(从[TableB]中选择[Value])
这些函数可以是存储过程。唯一的限制是您使用(或创建)的函数返回true/false。感谢您的回复,我会尽快尝试这个(以及Marc B的建议)。这很有效。奇怪的是,我必须添加一个唯一的约束。由于
ID
是主键,因此包括
ID
在内的任何一对列都保证是唯一的,但我认为这是SQL。我也设法让马克B的建议也奏效了,但我不确定我更喜欢哪一个。这似乎更可靠,因为由于
table
上的FK,将自动拒绝
table B
中的中断更改,但检查条件似乎保持正常化。也许这是另一天的问题。