Sql server 2012 定义主键约束时指定现有的非聚集唯一索引

Sql server 2012 定义主键约束时指定现有的非聚集唯一索引,sql-server-2012,primary-key,non-clustered-index,Sql Server 2012,Primary Key,Non Clustered Index,我有一个堆表-未定义聚集索引-(称之为表a),在不可为空的列上有一个唯一的非聚集索引(称之为列ID和索引IX) 在为表A定义列ID上的主键约束时,我想使用索引IX 某个地方的文档说明了这一点: 数据库引擎自动创建唯一索引,以强制执行主键约束的唯一性要求。如果聚集索引 表上不存在或未显式指定非聚集索引,将创建唯一的聚集索引以强制主键约束 我已经阅读了整个altertable文档,但似乎没有“非聚集索引是……明确指定的”的语法 已经尝试定义非聚集的索引IX并指定主键,还尝试了alter table的

我有一个堆表-未定义聚集索引-(称之为
表a
),在不可为空的列上有一个唯一的非聚集索引(称之为
列ID
索引IX

在为
表A
定义
列ID
上的主键约束时,我想使用
索引IX

某个地方的文档说明了这一点:

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

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

已经尝试定义非聚集的
索引IX
并指定主键,还尝试了alter table的各种组合。。。添加约束。。。主键语句无效

当我在alter表中简单地指定ID列时,我的索引IX相当于SQL Server创建的非聚集索引,这是有意义的。。。。添加约束。。。。主键(ID)语句,但我不希望使用SQL Server为我创建的这个冗余索引,而是让它使用
索引IX
,它还包括列的include列表

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


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

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

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

可以使用
altertable将唯一索引替换为唯一约束,作为仅元数据的更改。。。切换
,但尝试对非聚集PK约束执行相同操作失败

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

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

初始位置 用唯一约束替换唯一索引
为什么不让桌子保持原样呢?具有
非空
唯一
约束的列相当于具有
主键
约束的列。为什么要更改它呢?文档不清楚。我认为这意味着根据语句创建聚集索引或非聚集索引。并不是说您可以指定以前存在的索引。因此,在定义
主键
约束时,您无法避免创建一个新索引。我猜他们指的是主键声明中
主键
后面的可选
[CLUSTERED | NONCLUSTERED]
部分(这可能也是@ypercube所说的)。语法图无法指定要与主键约束一起使用的现有索引,您只能指定[新]主键索引是群集索引还是非群集索引。不能保持表的原样-需要主键才能在其他表上具有外键约束,参考相关表格。还可以不让sql server做它自己的事情并创建索引,因为自动创建的索引并不完全是必需的-例如,希望在索引上有一些include列。现在,我只需要创建冗余索引就可以了。这并不理想,因为在DML语句中需要维护多个索引,多个索引会让查询优化程序感到困惑:-),并且会浪费更多的内存。是的,Andrey M,我同意,他们可能指的是指定非聚集索引或不指定非聚集索引的能力(与指定实际的现有索引不同:-)但是,他们应该重新措辞。谢谢你。
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;