Что-то вроде этого:
SELECT
*
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_NAME ='FK_TreeNodesBinaryAssets_BinaryAssets'
and TABLE_NAME = 'TreeNodesBinaryAssets'
но для индексов.
Что-то вроде этого:
SELECT
*
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_NAME ='FK_TreeNodesBinaryAssets_BinaryAssets'
and TABLE_NAME = 'TreeNodesBinaryAssets'
но для индексов.
Вы можете сделать это, используя прямой выбор:
SELECT *
FROM sys.indexes
WHERE name='YourIndexName' AND object_id = OBJECT_ID('Schema.YourTableName')
Более сжатый метод, кодирующий, чтобы обнаружить существование индекса, выглядит следующим образом:
If IndexProperty(Object_Id('MyTable'), 'MyIndex', 'IndexId') Is Null
Если индекс существует, IndexProperty вернет идентификатор, если он этого не сделает, он не будет.
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
Небольшое отклонение от первоначального вопроса, однако, может оказаться полезным для будущих людей посадки здесь желающих DROP
и CREATE
индекс, то есть в сценарии развертывания.
Вы можете обойти проверку существующих, просто добавив следующее в оператор создания:
CREATE INDEX IX_IndexName
ON dbo.TableName
WITH (DROP_EXISTING = ON);
Подробнее читайте здесь: CREATE INDEX (Transact-SQL) - предложение DROP_EXISTING
NB. Как уже упоминалось в комментариях, индекс должен уже существовать, чтобы это предложение работало без выдачи ошибки.
Написал следующую функцию, которая позволяет мне быстро проверить, существует ли индекс; работает точно так же, как 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, но это не очень полезно.
Если скрытая цель вашего вопроса - DROP
индекс перед выполнением INSERT
для большой таблицы, то это полезный однострочный:
DROP INDEX IF EXISTS [IndexName] ON [dbo].[TableName]
Этот синтаксис доступен с SQL Server 2016. Документация для IF EXISTS
:
Если вместо этого вы имеете дело с первичным ключом, используйте это:
ALTER TABLE [TableName] DROP CONSTRAINT IF EXISTS [PK_name]
Вы можете использовать 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
-- 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
Чтобы проверить кластеризованный индекс, существует конкретная таблица или нет:
SELECT * FROM SYS.indexes
WHERE index_id = 1 AND name IN (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'Table_Name')