"Create Table" grammar显然不允许我指定聚集外键约束。换句话说,这是非法的:
--keyword CLUSTERED must be removed before this will execute...
CREATE TABLE [Content](
[ID] [int] NOT NULL CONSTRAINT PK_Content_ID PRIMARY KEY,
ContentDefID int NOT NULL CONSTRAINT FK_Plugin_ContentDef FOREIGN KEY CLUSTERED REFERENCES ContentDef(ID)
)
GO
但我不明白为什么这是非法的。 ISTM 认为聚集外键将有助于分页查找的性能。换句话说,“给我父 ID 20 的子项目 80 到 140”。
这样做有什么道理吗?
更新
根据 Oded 和 Tvanfosson 的反馈,我发现以下方法有效:
CREATE TABLE [Content](
[ID] [int] NOT NULL CONSTRAINT PK_Content_ID PRIMARY KEY,
ContentDefID int NOT NULL UNIQUE CLUSTERED CONSTRAINT FK_ContentDefContent FOREIGN KEY REFERENCES ContentDef(ID)
)
GO
但是上述引起的问题比它解决的问题还要多。首先,“唯一”外键迫使我的关系成为一对一,这是我不想要的。其次,这之所以有效,是因为它代表了两个单独约束的创建,而不是单个聚集外键。
但是这项调查让我更接近我的答案。显然clustered indexes MUST be unique ,如此处所述。引用:
If the clustered index is not a unique index, SQL Server makes any duplicate keys unique by adding an internally generated value called a uniqueifier
我特别认为this answer覆盖它。
最佳答案
正如其他人所解释的,聚集索引不必是主键,但它必须是唯一的,或者 SQL-Server 添加一个(未显示)UNIQUIFIER
列。
为了避免这种情况,您可以通过将主键列显式添加到聚集索引来使聚集索引唯一,如下所示。然后,该索引将可供外键约束使用(以及查询,例如连接两个表)。
请注意,正如 @Martin Smith 所解释的,CONSTRAINT
和 INDEX
的概念是不同的。不同的 DBMS 以不同的方式实现这些。 SQL-Server 会自动为某些约束创建索引,但不会为外键约束创建索引。但建议有一个约束可以使用的索引(在引用的表中删除或更新时):
CREATE TABLE Content(
ID int NOT NULL,
ContentDefID int NOT NULL,
CONSTRAINT PK_Content_ID
PRIMARY KEY NONCLUSTERED (ID),
CONSTRAINT CI_Content
UNIQUE CLUSTERED (ContentDefID, ID),
CONSTRAINT FK_Plugin_ContentDef
FOREIGN KEY (ContentDefID) REFERENCES ContentDef(ID)
) ;
关于sql-server - T-SQL 聚集外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13663569/