我有一个关于明确定义某事物唯一性的问题。这涉及复合外键的创建。我已经在下面创建了一个示例,尽可能地使我的问题变得清晰(我已经包含了一些数据插入以便于测试)。
[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]
中的复合外键。
实际情况如此吗?这种约束,无论多么多余,都是必要的,以便允许上述内容?或者我错过了什么?
答案 0 :(得分:1)
实际上,这与关系数据库的理论方面有关。
其父表中的哪些外键引用不是一组任意列,但它们可能是唯一的;它引用了一个键 - 主键或备用键。并且必须明确声明此密钥。
答案 1 :(得分:0)
唯一列集的任何超集都是唯一的。 DBMS可以编程来理解这一点。但SQL要求您在引用的表中声明组合唯一。
PS在关系模型中,外键必须引用候选键,必须同时声明候选键。但是在SQL中,UNIQUE声明了一个超级键,而FOREIGN KEY声明了一个外键超级键。 (当超级密钥不包含较小的超级密钥时,它是候选密钥。)人们可能更喜欢符合人体工程学的冗余,即外部超级密钥声明的目标具有显式匹配的唯一声明。但是没有理论或实施理由。