Как вы проверяете, существует ли какой-либо индекс в таблице?

Что-то вроде этого:

SELECT
* 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
WHERE CONSTRAINT_NAME ='FK_TreeNodesBinaryAssets_BinaryAssets'
and TABLE_NAME = 'TreeNodesBinaryAssets'

но для индексов.

Ответ 1

Вы можете сделать это, используя прямой выбор:

SELECT * 
FROM sys.indexes 
WHERE name='YourIndexName' AND object_id = OBJECT_ID('Schema.YourTableName')

Ответ 2

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

If IndexProperty(Object_Id('MyTable'), 'MyIndex', 'IndexId') Is Null

Если индекс существует, IndexProperty вернет идентификатор, если он этого не сделает, он не будет.

Ответ 3

AdaTheDEV, я использовал ваш синтаксис и создал следующее и почему.

Проблема: процесс выполняется один раз в квартал с часами из-за отсутствия индекса.

Исправление: измените процесс запроса или процедуру, чтобы проверить индекс и создать его, если он отсутствует... Тот же код помещается в конце запроса и процедуры для удаления индекса, поскольку он не нужен, а ежеквартально. Показывать только синтаксис drop здесь

-- drop the index 
begin

  IF EXISTS (SELECT *  FROM sys.indexes  WHERE name='Index_Name' 
    AND object_id = OBJECT_ID('[SchmaName].[TableName]'))
  begin
    DROP INDEX [Index_Name] ON [SchmaName].[TableName];
  end

end

Ответ 4

Небольшое отклонение от первоначального вопроса, однако, может оказаться полезным для будущих людей посадки здесь желающих DROP и CREATE индекс, то есть в сценарии развертывания.

Вы можете обойти проверку существующих, просто добавив следующее в оператор создания:

CREATE INDEX IX_IndexName
ON dbo.TableName
WITH (DROP_EXISTING = ON);

Подробнее читайте здесь: CREATE INDEX (Transact-SQL) - предложение DROP_EXISTING

NB. Как уже упоминалось в комментариях, индекс должен уже существовать, чтобы это предложение работало без выдачи ошибки.

Ответ 5

Написал следующую функцию, которая позволяет мне быстро проверить, существует ли индекс; работает точно так же, как OBJECT_ID.

CREATE FUNCTION INDEX_OBJECT_ID (
    @tableName VARCHAR(128),
    @indexName VARCHAR(128)
    )
RETURNS INT
AS
BEGIN
    DECLARE @objectId INT

    SELECT @objectId = i.object_id
    FROM sys.indexes i
    WHERE i.object_id = OBJECT_ID(@tableName)
    AND i.name = @indexName

    RETURN @objectId
END
GO

EDIT: это просто возвращает OBJECT_ID таблицы, но он будет NULL, если индекс не существует. Я полагаю, вы могли бы установить это для возврата index_id, но это не очень полезно.

Ответ 6

Если скрытая цель вашего вопроса - DROP индекс перед выполнением INSERT для большой таблицы, то это полезный однострочный:

DROP INDEX IF EXISTS [IndexName] ON [dbo].[TableName]

Этот синтаксис доступен с SQL Server 2016. Документация для IF EXISTS:

https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/

Если вместо этого вы имеете дело с первичным ключом, используйте это:

ALTER TABLE [TableName] DROP CONSTRAINT IF EXISTS [PK_name] 

Ответ 7

Вы можете использовать UDF как:

IF (SELECT [dbo].[Index_Exists] (N'SchemaName', N'TableName', N'IndexName')) = 0 
BEGIN
    -- Your script
END

Эта функция гарантирует, что указатель, на который вы ссылаетесь, является правильным, поскольку они могут использовать один и тот же индекс и/или имя таблицы для разных схем:

CREATE FUNCTION [dbo].[Index_Exists] (@Schema_Name sysname, @Table_Name sysname, @Index_Name sysname)
RETURNS bit
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE @Output bit

SET @Schema_Name = ISNULL(@Schema_Name, N'dbo');

IF EXISTS ( SELECT *
            FROM sys.indexes ind 
            JOIN sys.index_columns ic ON  ind.object_id = ic.object_id and ind.index_id = ic.index_id 
            JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id 
            JOIN sys.tables t ON ind.object_id = t.object_id
            WHERE   @Table_Name = t.[name]
            AND     @Schema_Name = OBJECT_SCHEMA_NAME(t.[object_id])
            AND     @Index_Name = ind.[name]
        ) SET @Output  = CAST(1 as bit)

RETURN ISNULL(@Output,CAST(0 as bit))
END

Ответ 8

-- Delete index if exists
IF EXISTS(SELECT TOP 1 1 FROM sys.indexes indexes INNER JOIN sys.objects 
objects ON indexes.object_id = objects.object_id WHERE indexes.name 
='Your_Index_Name' AND objects.name = 'Your_Table_Name')
BEGIN
    PRINT 'DROP INDEX [Your_Index_Name] ON [dbo].[Your_Table_Name]'
    DROP INDEX [our_Index_Name] ON [dbo].[Your_Table_Name]
END
GO

Ответ 9

Чтобы проверить кластеризованный индекс, существует конкретная таблица или нет:

SELECT * FROM SYS.indexes 
WHERE index_id = 1 AND name IN (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'Table_Name')