对于复合外键,是/为什么是带有主键的列组合所需的引用表中的复合UNIQUE约束?

时间:2016-07-04 11:00:57

标签: sql-server tsql foreign-keys unique-constraint

我有一个关于明确定义某事物唯一性的问题。这涉及复合外键的创建。我已经在下面创建了一个示例,尽可能地使我的问题变得清晰(我已经包含了一些数据插入以便于测试)。

[Table1]的每个条目都必须有唯一的[Name]

CREATE TABLE [Table1]
(
    [ID]    INT IDENTITY            NOT NULL PRIMARY KEY,
    [Name]  NVARCHAR(255) UNIQUE    NOT NULL CHECK(LTRIM(RTRIM([Name])) <> '')
);

INSERT INTO [Table1]([Name])
VALUES
('Name 1'),
('Name 2'),
('Name 3'),
('Name 4'),
('Name 5'),
('Name 6'),
('Name 7')

[Value]中的每个[Table2]对于每个[Table1ID]必须是唯一的。

CREATE TABLE [Table2]
(
    [ID]        INT IDENTITY    NOT NULL    PRIMARY KEY,
    [Table1ID]  INT             NOT NULL    FOREIGN KEY REFERENCES [Table1]([ID]),
    [Value]     NVARCHAR(255)   NOT NULL    CHECK(LTRIM(RTRIM([Value])) <> ''),

    --UNIQUE([ID], [Table1ID]),
    UNIQUE([Table1ID], [Value])
);

INSERT INTO [Table2]([Table1ID], [Value])
VALUES
(1, 'Entry 1'),
(1, 'Entry 2'),
(1, 'Entry 3'),
(1, 'Entry 4'),
(3, 'Entry 5'),
(3, 'Entry 6'),
(3, 'Entry 7')

[Table1ID][Table2ID][Table3]的每个组合必须在[Table2]中具有匹配组合(我假设这两个FOREIGN KEY为如果复合[Table1ID]到位,那么[Table2ID]FOREIGN KEY会是多余的。)

CREATE TABLE [Table3]
(
    [ID]        INT IDENTITY    NOT NULL,
    [Table1ID]  INT             NOT NULL    FOREIGN KEY REFERENCES [Table1]([ID]),
    [Table2ID]  INT             NOT NULL    FOREIGN KEY REFERENCES [Table2]([ID]),

    FOREIGN KEY ([Table2ID], [Table1ID]) REFERENCES [Table2](ID, [Table1ID])
);

INSERT INTO [Table3]([Table2ID], [Table1ID])
VALUES
(5, 3)

FOREIGN KEY中的复合[Table3]约束是个问题。如果UNIQUE中注释掉的[Table2]约束已取消注释,则可以成功创建[Table3]。如果不是,则[Table3]的创建将失败并且#34;引用的表中没有与外键中的引用列列表匹配的主键或候选键&#34;。

我理解密钥的唯一性需求,但由于[ID]的{​​{1}}列是[Table2]并且始终是唯一的,为什么PRIMARY KEY [Table1ID]中的列不是唯一的,可以防止[Table2][ID][Table1ID]的任何组合独特?

基本上,[Table2]部分对我来说似乎是多余的,但似乎必须明确定义UNIQUE([ID], [Table1ID])[Table1ID]的唯一性,以便SQL Server允许创建[Table2]中的复合外键。

实际情况如此吗?这种约束,无论多么多余,都是必要的,以便允许上述内容?或者我错过了什么?

2 个答案:

答案 0 :(得分:1)

实际上,这与关系数据库的理论方面有关。

其父表中的哪些外键引用不是一组任意列,但它们可能是唯一的;它引用了一个键 - 主键或备用键。并且必须明确声明此密钥。

答案 1 :(得分:0)

唯一列集的任何超集都是唯一的。 DBMS可以编程来理解这一点。但SQL要求您在引用的表中声明组合唯一。

PS在关系模型中,外键必须引用候选键,必须同时声明候选键。但是在SQL中,UNIQUE声明了一个超级键,而FOREIGN KEY声明了一个外键超级键。 (当超级密钥不包含较小的超级密钥时,它是候选密钥。)人们可能更喜欢符合人体工程学的冗余,即外部超级密钥声明的目标具有显式匹配的唯一声明。但是没有理论或实施理由。