¿Cómo verifica si existe cierto índice en una tabla?

288

Algo como esto:

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

pero para índices.

Lieven Cardoen
fuente
11
Me gustaría INFORMATION_SCHEMA en realidad tenía toda la información del esquema
Alan Macdonald

Respuestas:

480

Puede hacerlo usando una selección sencilla como esta:

SELECT * 
FROM sys.indexes 
WHERE name='YourIndexName' AND object_id = OBJECT_ID('Schema.YourTableName')
AdaTheDev
fuente
76
También puede ajustar la declaración en a IF EXISTS(SELECT * ...) BEGIN ... END.
bounav
26
Vale la pena mencionar que YourTableNamedebería ser el nombre completo con esquema
Marek
2
@blasto Si utiliza un esquema no predeterminado, como en la mayoría de mis casos, es obligatorio especificar el esquema como prefijo. En otro caso, no obtendrá ningún resultado en esta consulta
Marek
3
Para verificar una tabla temporal, puede usar 'tempdb.sys.indexes' y 'tempdb .. # TableName'. (ref Bjorn D. Jensen )
crokusek
77
Solo para agregar: "A partir de SQL Server 2016, puede usar la sintaxis DROP INDEX IF EXISTS". Documentación de MS
heringer
100

Para SQL 2008 y versiones posteriores , un método más conciso, codificado, para detectar la existencia del índice es mediante el uso de la INDEXPROPERTYfunción integrada:

INDEXPROPERTY ( object_ID , index_or_statistics_name , property )  

El uso más simple es con la IndexIDpropiedad:

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

Si el índice existe, lo anterior devolverá su ID; si no lo hace, volverá NULL.

Sr. McGoo
fuente
71

AdaTheDEV, usé tu sintaxis y creé lo siguiente y por qué.

Problema: el proceso se ejecuta una vez al trimestre y tarda una hora debido a la falta de índice.

Corrección: Alterar el proceso de consulta o el Procedimiento para verificar el índice y crearlo si falta ... El mismo código se coloca al final de la consulta y el procedimiento para eliminar el índice, ya que no es necesario sino trimestralmente. Mostrando solo la sintaxis de soltar aquí

-- 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
Hank Freeman
fuente
15

Una ligera desviación de la pregunta original, aunque puede resultar útil para futuras personas que aterrizan aquí que quieren DROPy CREATEun índice, es decir, en un script de implementación.

Puede omitir la verificación existente simplemente agregando lo siguiente a su declaración de creación:

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

Lea más aquí: CREATE INDEX (Transact-SQL) - Cláusula DROP_EXISTING

Nota: Como se mencionó en los comentarios, el índice ya debe existir para que esta cláusula funcione sin generar un error.

Chris Pickford
fuente
8
En realidad ... ten cuidado! ¡Esto fallará si el índice aún no existe! Al menos en SQL Server 2008.
Andrey Kaipov
1
... y todavía falla en SQL 2016
Magier
2
Otro efecto (quizás obvio) es que siempre volverá a crear el índice. Esto puede no ser lo que quieres. Dejar y crear un índice en una tabla grande es una operación costosa, especialmente si el índice existente ya es el que desea. Esta declaración es buena para el reemplazo en un solo paso. No compara el índice existente, sino más bien una fuerza bruta "haga esto, incluso si existe, suéltelo ... simplemente hágalo, ¡listo!" :-) Todavía requiere toda la verificación que OP estaba buscando. Sin embargo, si el índice necesita ser reemplazado, combina DROP / CREATE.
ripvlan
10

Si el propósito oculto de su pregunta es DROPel índice antes de hacer INSERTuna tabla grande, entonces esto es útil:

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

Esta sintaxis está disponible desde SQL Server 2016. Documentación para IF EXISTS:

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

En caso de que trabaje con una clave primaria, use esto:

ALTER TABLE [TableName] DROP CONSTRAINT IF EXISTS [PK_name] 
Przemyslaw Remin
fuente
7

Escribió la siguiente función que me permite verificar rápidamente para ver si existe un índice; funciona igual que 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

EDITAR: Esto solo devuelve el OBJECT_ID de la tabla, pero será NULL si el índice no existe. Supongo que podría configurar esto para devolver index_id, pero eso no es súper útil.

Mark Williams
fuente
1
-- 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
Paolo Argentieri
fuente
-1

Para comprobar que el índice agrupado existe en una tabla en particular o no:

SELECT * FROM SYS.indexes 
WHERE index_id = 1 AND name IN (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'Table_Name')
Rajiv Singh
fuente
55
Esto devuelve claves primarias y restricciones únicas, pero ninguna de ellas es necesariamente un índice agrupado.
Mark Sowul el
index_id = 1 es incorrecto donde la cláusula Al índice se le puede asignar una identificación diferente
Fuzzybear