如何检查表中是否存在某个索引?

就像这样:

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

但是对于索引。

413678 次浏览

你可以像这样直接选择:

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

查询指定表上是否存在聚集索引。

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

写了下面的函数,允许我快速检查,看看是否存在索引;就像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,但这并不是非常有用。

AdaTheDEV,我使用了您的语法并创建了以下内容及其原因。

问题:由于缺少索引,进程每季度运行一次,耗时1小时。

纠正:改变查询过程或过程,以检查索引和创建它,如果缺少…同样的代码被放置在查询和过程的末尾,以删除索引,因为它不是需要的,而是每季度需要一次。此处只显示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

对于SQL 2008及更新版本,一个更简洁的方法,在编码方面,检测索引是否存在是通过使用INDEXPROPERTY内置函数:

INDEXPROPERTY ( object_ID , index_or_statistics_name , property )

最简单的用法是IndexID属性:

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

如果索引存在,则返回索引ID;如果没有,它将返回NULL

与最初的问题稍有偏差,但是,对于将来想要在部署脚本中DROPCREATE作为索引的人来说,这可能是有用的。

你可以通过在你的create语句中添加以下内容来绕过exists检查:

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

在这里阅读更多:CREATE INDEX (Transact-SQL) - DROP_EXISTING子句

注意:正如注释中提到的,索引必须已经存在,此子句才能正常工作而不抛出错误。

-- 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

如果你的问题的隐藏目的是在将INSERT变成一个大表之前DROP索引,那么这是有用的一行代码:

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]
EXEC sp_helpindex '[[[SCHEMA-NAME.TABLE-NAME]]]'
GO