Можете ли вы создать индекс для табличной переменной в SQL Server 2000?
т.е.
DECLARE @TEMPTABLE TABLE (
[ID] [int] NOT NULL PRIMARY KEY
,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL
)
Могу ли я создать индекс на Name
?
sql
sql-server
tsql
indexing
table-variable
GordyII
источник
источник
CREATE TABLE #T1(X INT); CREATE TABLE #T2(X INT); CREATE INDEX IX ON #T1(X); CREATE INDEX IX ON #T2(X);
Ответы:
Вопрос помечен SQL Server 2000, но в интересах людей, разрабатывающих последнюю версию, я сначала расскажу об этом.
SQL Server 2014
В дополнение к описанным ниже методам добавления индексов на основе ограничений SQL Server 2014 также позволяет указывать неуникальные индексы напрямую с помощью встроенного синтаксиса в объявлениях табличных переменных.
Пример синтаксиса для этого ниже.
Отфильтрованные индексы и индексы с включенными столбцами в настоящее время не могут быть объявлены с этим синтаксисом, однако SQL Server 2016 смягчает это немного дальше. Из CTP 3.1 теперь можно объявлять отфильтрованные индексы для табличных переменных. В RTM может быть так, что включенные столбцы также разрешены, но текущая позиция такова, что они "скорее всего не попадут в SQL16 из-за ограничений ресурсов"
SQL Server 2000 - 2012
Краткий ответ: да.
Более подробный ответ ниже.
Традиционные таблицы в 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
явно указав объявление ограничения (пример синтаксиса)В результате вышеизложенного могут быть неявно созданы следующие индексы для табличных переменных в SQL Server 2000 - 2012.
Последний требует небольшого объяснения. В определении табличной переменной в начале этого ответа неуникальный некластеризованный индекс on
Name
моделируется уникальным индексом onName,Id
(напомним, что SQL Server в любом случае автоматически добавит ключ кластеризованного индекса в неуникальный ключ NCI).IDENTITY
Неуникальный кластеризованный индекс также может быть достигнут путем добавления столбца вручную в качестве уникализатора.Но это не точное моделирование того, как неуникальный кластерный индекс обычно будет реализован в SQL Server, так как это добавляет «уникализатор» ко всем строкам. Не только те, которые этого требуют.
источник
Следует понимать, что с точки зрения производительности нет различий между таблицами @temp и таблицами #temp, которые предпочитают переменные. Они находятся в одном месте (tempdb) и реализованы одинаково. Все отличия появляются в дополнительных функциях. Посмотрите эту удивительно полную рецензию: /dba/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386
Хотя в некоторых случаях временная таблица не может использоваться, например, в табличных или скалярных функциях, в большинстве других случаев до v2016 (когда к табличной переменной можно добавить даже отфильтрованные индексы) вы можете просто использовать таблицу #temp.
Недостатком использования именованных индексов (или ограничений) в базе данных tempdb является то, что имена могут затем конфликтовать. Не только теоретически с другими процедурами, но часто довольно легко с другими экземплярами самой процедуры, которая будет пытаться поместить тот же индекс в свою копию таблицы #temp.
Чтобы избежать конфликтов имен, обычно работает что-то вроде этого:
Это гарантирует, что имя всегда уникально даже при одновременном выполнении одной и той же процедуры.
источник
Если переменная Table содержит большие данные, то вместо табличной переменной (@table) создать временную таблицу (#table) .table переменная не позволяет создавать индекс после вставки.
Создать таблицу с уникальным кластерным индексом
Вставить данные в таблицу Temp "#Table"
Создать некластеризованные индексы.
источник