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

Lie*_*oen 269 sql-server

像这样的东西:

SELECT
* 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
WHERE CONSTRAINT_NAME ='FK_TreeNodesBinaryAssets_BinaryAssets'
and TABLE_NAME = 'TreeNodesBinaryAssets'
Run Code Online (Sandbox Code Playgroud)

但对于索引.

Ada*_*Dev 450

你可以使用这样的直接选择来做到这一点:

SELECT * 
FROM sys.indexes 
WHERE name='YourIndexName' AND object_id = OBJECT_ID('Schema.YourTableName')
Run Code Online (Sandbox Code Playgroud)

  • 您还可以将语句包装到`IF EXISTS(SELECT*...)BEGIN ... END`中. (71认同)
  • 值得一提的是,`YourTableName`应该是带有模式的全名 (25认同)
  • 只需添加:"从SQL Server 2016开始,您可以使用DROP INDEX IF EXISTS语法." [MS文档](https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-index-transact-sql) (4认同)
  • 要检查临时表,可以使用'tempdb.sys.indexes'和'tempdb ..#TableName'.(参见[Bjorn D. Jensen](https://social.msdn.microsoft.com/Forums/sqlserver/en-US/dbee7c2d-b2be-41d9-bd59-f2025c898483/existence-of-index-for-temp-table )) (3认同)
  • @blasto如果使用非默认模式,就像在我的大多数情况下一样,将模式指定为前缀是必需的.在其他情况下,您不会在此查询中获得任何结果 (2认同)

Mr *_*Goo 87

编码方式,检测索引存在的更简洁的方法如下;

If IndexProperty(Object_Id('MyTable'), 'MyIndex', 'IndexId') Is Null
Run Code Online (Sandbox Code Playgroud)

如果索引存在,IndexProperty将返回一个Id,如果不存在,则不会.

  • 这个答案更优越,因为它更容易集成到维护脚本中.需要注意的是,最后一个选项`IndexID`是一个命令,而不是一个必需的对象相关的答案.[IndexProperty - Microsoft Docs](https://docs.microsoft.com/en-us/sql/t-sql/functions/indexproperty-transact-sql) (11认同)
  • 仅适用于[SQL Server 2008及更高版本](https://msdn.microsoft.com/en-us/library/ms187729.aspx?f=255&MSPPError=-2147217396). (3认同)

小智 70

AdaTheDEV,我使用了你的语法并创建了以下内容和原因.

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

更正:更改查询过程或过程以检查索引并在缺少时创建它...在查询和过程结束时放置相同的代码以删除索引,因为它不是必需的,而是每季度.此处仅显示删除语法

-- 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
Run Code Online (Sandbox Code Playgroud)


Chr*_*ord 14

然而,与原始问题的轻微偏差可能对将来登陆此处的DROP人和CREATE索引(即在部署脚本中)有用.

只需将以下内容添加到create语句中即可绕过exists检查:

CREATE INDEX IX_IndexName
ON dbo.TableName
WITH (DROP_EXISTING = ON);
Run Code Online (Sandbox Code Playgroud)

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

NB正如注释中所提到的,索引必须已经存在才能使该子句工作而不会抛出错误.

  • 其实..小心!如果索引尚不存在,这将失败!至少在SQL Server 2008中. (6认同)
  • ...并且在 SQL 2016 中仍然失败 (2认同)
  • 我应该在进行部署之前阅读这些评论 (2认同)
  • 另一个(可能很明显)的效果是它总是会重新创建索引。这可能不是您想要的。在大表上删除和创建索引是一项昂贵的操作 - 特别是如果现有索引已经是您想要的索引。此语句适用于一步替换。它不比较现有的索引 - 而是一种蛮力“这样做,即使存在 - 放弃它......就这样做,就完成了!” :-) 它仍然需要 OP 正在寻找的所有检查。但是,如果索引需要替换,它会结合 DROP/CREATE。 (2认同)

Mar*_*ams 6

写下面的函数,让我快速检查索引是否存在; 就像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
Run Code Online (Sandbox Code Playgroud)

编辑:这只返回表的OBJECT_ID,但如果索引不存在则为NULL.我想你可以设置它来返回index_id,但这不是非常有用.


Prz*_*min 5

如果您的问题的隐藏目的是DROP在创建INSERT大型表之前先建立索引,则这很有用:

DROP INDEX IF EXISTS [IndexName] ON [dbo].[TableName]
Run Code Online (Sandbox Code Playgroud)

这句法是因为SQL服务器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] 
Run Code Online (Sandbox Code Playgroud)