Указание существующего некластеризованного уникального индекса при определении ограничения первичного ключа

У меня есть таблица кучи - кластерный индекс не определен - (назовите ее table A) с уникальным некластеризованным индексом в столбце, не допускающем значения NULL (вызовите column ID и index IX).

Я хотел бы использовать index IX при определении ограничения первичного ключа на column ID для table A.

В документации где-то говорится:

Компонент Database Engine автоматически создает уникальный индекс, чтобы обеспечить выполнение требования уникальности ограничения PRIMARY KEY. Если кластеризованный индекс еще не существует в таблице или некластеризованный индекс не указан явно, создается уникальный кластеризованный индекс для обеспечения соблюдения ограничения PRIMARY KEY.

Я прочитал всю ALTER TABLE документацию, но, похоже, нет синтаксиса для "некластеризованный индекс ... явно указан".

Попробовали определить некластеризованный index IX и указать первичный ключ, а также пробовали различные комбинации оператора alter table ... add constraint ... primary key, но безрезультатно.

Имеет смысл, что мой индекс IX эквивалентен некластеризованному индексу, который SQL Server создает, когда я просто указываю столбец идентификатора в таблице изменений .... добавляю ограничение .... оператор первичного ключа (ID), но я бы предпочел не имея этот избыточный индекс, который SQL Server создает для меня, и скорее заставляю его использовать index IX, который также состоит из включаемого списка столбцов.

Если я отброшу индекс, созданный SQL Server, ограничение первичного ключа также исчезнет.

Если бы можно было изменить индекс, создаваемый SQL Server, моя проблема была бы решена, но изменение, которое я хотел бы сделать с ним, требует удаления и воссоздания.


person Kerneels Roos    schedule 18.06.2014    source источник
comment
Почему бы просто не оставить стол как есть? Столбец с ограничениями NOT NULL и UNIQUE эквивалентен столбцу с ограничением PRIMARY KEY. Зачем вообще это менять?   -  person ypercubeᵀᴹ    schedule 18.06.2014
comment
Документация непонятна. Я думаю, это означает, что создается кластерный или некластеризованный индекс, в зависимости от утверждения. Не то чтобы вы могли указать ранее существовавший индекс. Таким образом, вы не можете избежать создания нового индекса при определении ограничения PRIMARY KEY.   -  person ypercubeᵀᴹ    schedule 18.06.2014
comment
Я предполагаю, что они имеют в виду необязательную часть [ CLUSTERED | NONCLUSTERED ], которая следует за PRIMARY KEY в объявлении первичного ключа (о чем, вероятно, и говорит @ypercube). Синтаксические диаграммы не показывают способа указать существующий индекс для использования с ограничением первичного ключа, вы можете только указать, будет ли [новый] индекс первичного ключа кластеризованным или некластеризованным.   -  person Andriy M    schedule 18.06.2014
comment
Невозможно оставить таблицу как есть - требуется первичный ключ, чтобы иметь ограничения внешнего ключа для других таблиц, ссылающихся на рассматриваемую таблицу. Также нельзя просто позволить sql серверу сделать это и создать индекс, поскольку автоматически созданный индекс не совсем то, что требуется - хотелось бы, например, иметь несколько включаемых столбцов в индексе. На данный момент я согласен просто создать избыточный индекс. Это не идеально, так как это еще один индекс, который нужно поддерживать во время операторов DML, и еще один индекс, чтобы запутать оптимизатор запросов :-), и немного больше памяти.   -  person Kerneels Roos    schedule 19.06.2014
comment
да, Andriy M, я согласен, они, вероятно, действительно имеют в виду возможность указывать НЕКЛАССНЫЙ ИНДЕКС или нет - как подходящее для указания фактического существующего индекса :-) но имо, им следует перефразировать. Спасибо хоть.   -  person Kerneels Roos    schedule 19.06.2014


Ответы (1)


Невозможно создать ограничение и связать его с существующим индексом, который уже гарантирует ограничение.

Эта функция существует в других СУБД. Это было бы особенно полезно для шаблона супертипа / подтипа, поскольку это требует создания уникальных индексов как для Id, так и для (Id, Type), даже если последний (необходимый для FK) логически обеспечивается первым.

Можно заменить уникальный индекс ограничением уникальности, поскольку метаданные изменяются только с помощью ALTER TABLE ... SWITCH, но попытка сделать то же самое с некластеризованным ограничением PK завершается неудачно с

Оператор ALTER TABLE SWITCH завершился неудачно. В исходной таблице «A» нет идентичного индекса для индекса «IX» в целевой таблице «B».

Код, который выполняет это для уникального ограничения:

Исходное положение

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; 
person Martin Smith    schedule 28.12.2014