【问题标题】:Specifying existing non clustered unique index when defining a primary key constraint在定义主键约束时指定现有的非聚集唯一索引
【发布时间】:2014-08-08 21:52:18
【问题描述】:

我有一个堆表 - 没有定义聚集索引 - (称为 table A),在不可为空的列上有一个唯一的非聚集索引(称为 column IDindex IX)。

在为table A 定义column ID 的主键约束时,我想使用index IX

某处的文档是这样说的:

数据库引擎自动创建唯一索引以强制执行 PRIMARY KEY 约束的唯一性要求。如果聚集索引确实 表上尚不存在或未显式指定非聚集索引,则创建唯一的聚集索引以强制执行 PRIMARY KEY 约束。

我已经阅读了整个 ALTER TABLE 文档,但似乎没有“非聚集索引是……明确指定的”的语法。

已尝试定义非聚集index IX并指定主键,也尝试了alter table的各种组合...添加约束...主键语句无济于事。

当我在 alter table 中指定 ID 列时,我的索引 IX 等同于 SQL Server 创建的非聚集索引 .... 添加约束 .... 主键 (ID) 语句,这是有道理的,但我宁愿没有 SQL Server 为我创建的冗余索引,而是让它使用index IX,它也包含列的包含列表。

如果我删除 SQL Server 创建的索引,那么主键约束也会消失。

如果可以更改 SQL Server 创建的索引,我的问题将得到解决,但我想对其进行的更改需要删除并重新创建。

【问题讨论】:

  • 为什么不保持原样?具有NOT NULLUNIQUE 约束的列等效于具有PRIMARY KEY 约束的列。为什么还要改呢?
  • 文档不清楚。我认为这意味着根据语句创建聚集索引或非聚集索引。并不是说您可以指定以前存在的索引。因此,在定义 PRIMARY KEY 约束时,您无法避免创建新索引。
  • 我猜他们指的是主键声明中PRIMARY KEY 后面的可选[ CLUSTERED | NONCLUSTERED ] 部分(这可能也是@ypercube 所说的)。语法图显示无法指定现有索引与主键约束一起使用,您只能指定 [新] 主键索引是集群还是非集群。
  • 不能让表保持原样 - 需要一个主键才能在其他表上具有外键约束,引用有问题的表。也可以不只是让 sql server 做这件事并创建索引,因为自动创建的索引并不完全是需要的 - 例如,希望在索引上有一些包含列。现在,我只满足于创建冗余索引。这并不理想,因为在 DML 语句期间要多维护一个索引,还要再多一个索引来混淆查询优化器 :-),并浪费更多内存。
  • 是的 Andriy M ,我同意,他们可能确实提到了指定非集群索引的能力 - 与指定实际的现有索引一样:-) 但 imo,他们应该改写。不过还是谢谢。

标签: sql-server-2012 primary-key non-clustered-index


【解决方案1】:

无法创建约束并将其与已经保证约束的现有索引相关联。

此功能在其他 RDBMS 中确实存在。这对于超类型/子类型模式特别有用,因为这需要在 Id(Id, Type) 上创建唯一索引,即使后者(FK 所需)在逻辑上由第一个确保。

可以将唯一索引替换为唯一约束,因为元数据仅使用 ALTER TABLE ... SWITCH 更改,但尝试对非集群 PK 约束执行相同操作会失败

ALTER TABLE SWITCH 语句失败。没有相同的索引 目标表“B”中索引“IX”的源表“A”。

为唯一约束执行此操作的代码是

初始位置

CREATE TABLE dbo.A(ID INT NOT NULL, OtherCols VARCHAR(200));

CREATE UNIQUE NONCLUSTERED INDEX IX ON dbo.A(ID);

INSERT INTO dbo.A VALUES (1,'A'),(2,'B');

用唯一约束替换唯一索引

SET XACT_ABORT ON;

BEGIN TRAN;

CREATE TABLE dbo.B
  (
     ID        INT NOT NULL CONSTRAINT IX UNIQUE NONCLUSTERED,
     OtherCols VARCHAR(200)
  );

ALTER TABLE dbo.A 
      SWITCH TO dbo.B;

DROP TABLE dbo.A;

EXECUTE sp_rename
  N'dbo.B',
  N'A',
  'OBJECT';

COMMIT; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-16
    • 2021-06-17
    • 2014-07-30
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    相关资源
    最近更新 更多