Вопрос помечен SQL Server 2000, но в интересах людей, разрабатывающих последнюю версию, я сначала расскажу об этом.
SQL Server 2014
В дополнение к описанным ниже методам добавления индексов на основе ограничений SQL Server 2014 также позволяет указывать неуникальные индексы напрямую с помощью встроенного синтаксиса в объявлениях табличных переменных.
Пример синтаксиса для этого ниже.
/*SQL Server 2014+ compatible inline index syntax*/
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);
Отфильтрованные индексы и индексы с включенными столбцами в настоящее время не могут быть объявлены с этим синтаксисом, однако SQL Server 2016 смягчает это немного дальше. Из CTP 3.1 теперь можно объявлять отфильтрованные индексы для табличных переменных. В RTM может быть так, что включенные столбцы также разрешены, но текущая позиция такова, что они "скорее всего не попадут в SQL16 из-за ограничений ресурсов"
/*SQL Server 2016 allows filtered indexes*/
DECLARE @T TABLE
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/
)
SQL Server 2000 - 2012
Могу ли я создать индекс по имени?
Краткий ответ: да.
DECLARE @TEMPTABLE TABLE (
[ID] [INT] NOT NULL PRIMARY KEY,
[Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL,
UNIQUE NONCLUSTERED ([Name], [ID])
)
Более подробный ответ ниже.
Традиционные таблицы в SQL Server могут иметь кластеризованный индекс или иметь структуру кучи .
Кластерные индексы могут быть объявлены как уникальные, чтобы запретить повторяющиеся значения ключа, или по умолчанию не уникальные. Если не уникален, то SQL Server автоматически добавляет уникализатор к любым дублирующимся ключам, чтобы сделать их уникальными.
Некластеризованные индексы также могут быть явно объявлены как уникальные. В противном случае для неуникального случая SQL Server добавляет указатель строки (ключ кластеризованного индекса или RID для кучи) ко всем ключам индекса (а не только к дубликатам), что снова гарантирует их уникальность.
В SQL Server 2000 - 2012 индексы для табличных переменных можно неявно создавать только путем создания ограничения UNIQUE
или PRIMARY KEY
. Разница между этими типами ограничений заключается в том, что первичный ключ должен находиться в столбцах, которые не могут содержать значения NULL. Столбцы, участвующие в уникальном ограничении, могут иметь значение NULL. (хотя реализация SQL Server уникальных ограничений при наличии NULL
s не соответствует той, которая указана в стандарте SQL). Также таблица может иметь только один первичный ключ, но несколько уникальных ограничений.
Оба эти логических ограничения физически реализованы с уникальным индексом. Если явно не указано иное PRIMARY KEY
, кластерный индекс станет уникальным, а уникальные ограничения не будут кластеризованы, но это поведение можно переопределить, указав CLUSTERED
или NONCLUSTERED
явно указав объявление ограничения (пример синтаксиса)
DECLARE @T TABLE
(
A INT NULL UNIQUE CLUSTERED,
B INT NOT NULL PRIMARY KEY NONCLUSTERED
)
В результате вышеизложенного могут быть неявно созданы следующие индексы для табличных переменных в SQL Server 2000 - 2012.
+-------------------------------------+-------------------------------------+
| Index Type | Can be created on a table variable? |
+-------------------------------------+-------------------------------------+
| Unique Clustered Index | Yes |
| Nonunique Clustered Index | |
| Unique NCI on a heap | Yes |
| Non Unique NCI on a heap | |
| Unique NCI on a clustered index | Yes |
| Non Unique NCI on a clustered index | Yes |
+-------------------------------------+-------------------------------------+
Последний требует небольшого объяснения. В определении табличной переменной в начале этого ответа неуникальный некластеризованный индекс on Name
моделируется уникальным индексом on Name,Id
(напомним, что SQL Server в любом случае автоматически добавит ключ кластеризованного индекса в неуникальный ключ NCI).
IDENTITY
Неуникальный кластеризованный индекс также может быть достигнут путем добавления столбца вручную в качестве уникализатора.
DECLARE @T TABLE
(
A INT NULL,
B INT NULL,
C INT NULL,
Uniqueifier INT NOT NULL IDENTITY(1,1),
UNIQUE CLUSTERED (A,Uniqueifier)
)
Но это не точное моделирование того, как неуникальный кластерный индекс обычно будет реализован в SQL Server, так как это добавляет «уникализатор» ко всем строкам. Не только те, которые этого требуют.