【发布时间】:2016-11-06 02:10:28
【问题描述】:
我有一个关于明确定义某事物的独特性的问题。这与复合外键的创建有关。我在下面创建了一个示例,以尝试使我的问题尽可能清晰(为了便于测试,我添加了一些数据插入)。
[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')
[Table2] 中的每个 [Value] 对于每个 [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')
[Table3] 中 [Table1ID] 和 [Table2ID] 的每个组合必须在 [Table2] 中具有匹配的组合(我假设 [Table1ID] 和 [Table2ID] 的两个 FOREIGN KEYs 是多余的,如果复合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)
[Table3] 中的复合 FOREIGN KEY 约束是问题所在。如果[Table2] 中注释掉的UNIQUE 约束未注释,则可以成功创建[Table3]。如果不是,[Table3] 的创建将失败,并显示“引用的表中没有与外键中的引用列列表匹配的主键或候选键”。
我了解键的唯一性需要,但是由于[Table2] 的[ID] 列是PRIMARY KEY 并且始终是唯一的,为什么[Table1ID] 列在[Table2] 中不是唯一的防止[Table2] 中[ID] 和[Table1ID] 的任意组合是唯一的?
基本上,UNIQUE([ID], [Table1ID]) 部分对我来说似乎是多余的,但似乎必须明确定义 [Table2] 中 [Table1ID] 的唯一性,以便 SQL Server 允许在 @ 中创建复合外键987654354@.
真的是这样吗?为了允许上述情况,需要这种约束,无论它看起来多么多余?还是我错过了什么?
【问题讨论】:
-
是的,因为您发现必须声明唯一性。我会质疑任何需要做你所要求的数据设计。
-
再一次,我把上面的东西放在一起作为例子来演示一下。您能否扩展您的数据设计评论?
-
让我直说。 Table2 已经与 Table1 有关系。在表 3 中,希望直接在 1 和 2 之间创建关系,同时尊重 2 与 1 的现有关系。您是否能够针对这种关系扩展任何合理的业务需求?
-
@Paparazzi [
Table1]是key的列表,比如列表的名字,[Table2]是每个key的可选值的列表,即列表中的值,[Table3]是从此类列表中选择的值。不同的用户可以选择不同的值(因此第三个表存储他们的选择),但每个人都可以从相同的值列表中进行选择 ([Table2])。 [Table1] 引用最初可能看起来是多余的,但实际上它提供了一些数据完整性。 -
如果有人决定更改
[Table2]记录以使其引用不同的[Table1]记录(即将可选值移动到不同的列表),但[Table3]中的记录已经在引用因为一个或多个用户已经在原始键下选择了该列表值,所以将阻止更改。如果没有额外的[Table1]引用,用户最初选择的值将隐式移动到不同的列表。
标签: sql-server tsql foreign-keys unique-constraint