T-SQL集群外键

时间:2012-12-01 20:42:35

标签: sql-server performance tsql foreign-keys

"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将有助于页面查找的性能。换句话说,“给我父母身份证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 FOREIGN KEY。

但这次调查让我更接近我的答案。显然clustered indexes MUST be unique,如此处所述。引用:

  

如果聚簇索引不是唯一索引,则SQL Server通过添加内部生成的称为唯一性的值来使任何重复键唯一

特别是,我认为this answer涵盖了它。

4 个答案:

答案 0 :(得分:4)

正如其他人所解释的那样,聚集索引不必是主键,但它必须是唯一的,或者SQL-Server向其添加(未显示)UNIQUIFIER列。

为避免这种情况,您可以通过将主键列显式添加到聚簇索引来使聚簇索引唯一,如下所示。然后,索引将被外键约束(以及查询,如加入两个表)使用。

请注意,正如@Martin Smith所解释的那样,CONSTRAINTINDEX的概念是不同的。各种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)
) ;

答案 1 :(得分:4)

  

这有什么理由吗?

您也可以问为什么不能创建CLUSTERED检查约束或CLUSTERED默认约束。

外键只是定义了一个逻辑约束,并且在SQL Server中没有为它自动创建索引(这只适用于UNIQUEPRIMARY KEY约束)。在SQL Server中总是如此,如果您希望索引FK列,则需要自己在相关列上运行CREATE INDEX

因此CLUSTERED FOREIGN KEY的概念没有任何意义。当然,您可以在构成FK的列上创建CLUSTERED INDEX,但正如您在问题中指出的那样。

答案 2 :(得分:2)

您只能在表上拥有一个聚簇索引。默认情况下,这将是主键列。

There are ways to change this - 您需要使用PRIMARY KEY NONCLUSTEREDUNIQUE CLUSTERED FOREIGN KEY

答案 3 :(得分:0)

似乎你将聚集索引的想法与密钥(主要或外来)混为一谈。为什么不制作表格,然后再指定其聚集索引? (从第一个示例中复制的代码并尽可能少地更改)

CREATE TABLE [Content](
    [ID] [int] NOT NULL CONSTRAINT PK_Content_ID PRIMARY KEY NONCLUSTERED,
    ContentDefID int NOT NULL CONSTRAINT FK_Plugin_ContentDef FOREIGN KEY REFERENCES ContentDef(ID)
    )
GO

CREATE CLUSTERED INDEX IX_Content_Clustered on Content(ContentDefID)

您无需使聚集索引唯一