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
中的中断更改,但检查条件似乎保持正常化。也许这是另一天的问题。