SQL Server 用IF NOT EXISTS建索引仍报索引/统计已存在错误
SQL Server「索引不存在则创建」逻辑异常解决方案
问题背景
需要编写可靠SQL实现索引不存在则创建的效果,初始实现逻辑为查询sys.indexes系统视图,若表internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit上不存在名为IX_GraphedTripleValueBit_PropertyDefinitionId的索引,则执行索引创建,初始代码如下:
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_GraphedTripleValueBit_PropertyDefinitionId' AND object_id = OBJECT_ID('internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit')) BEGIN CREATE INDEX IX_GraphedTripleValueBit_PropertyDefinitionId ON internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit(PropertyDefinitionId) INCLUDE (GraphedEntityRootUid) END;
执行上述代码时抛出如下报错:
The operation failed because an index or statistics with name 'IX_GraphedTripleValueBit_PropertyDefinitionId' already exists on table 'GraphedTripleValueBit'
已知约束
- SQL由C#代码生成(非Entity Framework实现),部署目标为客户端SQL Azure数据库
- 客户方DBA开放权限前,无法直接登录实例查看系统表实际状态
- 逻辑覆盖大量表,非必要不希望增加额外检查开销
- 初步猜测问题为未同步检查
sys.stats视图,需要确认正确实现方式
结论与解决方案
必须同时检查sys.indexes和sys.stats两个系统视图。
报错的核心原因是SQL Server中同一张表下的索引和统计信息共享命名空间,二者不允许重名:sys.indexes仅记录实际存在的索引对象,不会覆盖独立存在的统计信息,这类统计信息可能是查询优化器自动生成的,也可能是历史脚本、DBA手动创建的,虽然不会出现在sys.indexes中,但会占用索引名称,导致CREATE INDEX语句抛出重名错误。
针对元数据系统视图的检查开销极低,查询走系统内置元数据查找逻辑,哪怕批量覆盖上千张表也不会产生可感知的性能损耗,完全满足低开销要求。修正后的可靠实现代码如下:
IF NOT EXISTS ( SELECT 1 FROM sys.indexes WHERE name = 'IX_GraphedTripleValueBit_PropertyDefinitionId' AND object_id = OBJECT_ID('internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit') ) AND NOT EXISTS ( SELECT 1 FROM sys.stats WHERE name = 'IX_GraphedTripleValueBit_PropertyDefinitionId' AND object_id = OBJECT_ID('internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit') ) BEGIN CREATE INDEX IX_GraphedTripleValueBit_PropertyDefinitionId ON internal_dot_dotalign_dot_com_teams_1.GraphedTripleValueBit(PropertyDefinitionId) INCLUDE (GraphedEntityRootUid) END;
额外注意事项
- 代码中
OBJECT_ID()传入的表名必须和CREATE INDEX后接的表名完全一致,避免因默认schema不匹配导致object_id解析错误,出现漏判。 - 若检测到同名统计信息存在但对应索引不存在,不要直接删除统计信息后创建索引:自动生成的统计信息可能正被现有执行计划引用,贸然删除可能引发短期查询性能波动,这类场景可以先跳过该表的索引创建,待有权限核查统计信息来源后再做处理。
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

