Comment vérifiez-vous si un certain index existe dans une table?

288

Quelque chose comme ça:

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

mais pour les index.

Lieven Cardoen
la source
11
Je souhaite que INFORMATION_SCHEMA ait réellement toutes les informations sur le schéma
Alan Macdonald

Réponses:

480

Vous pouvez le faire en utilisant une sélection simple comme celle-ci:

SELECT * 
FROM sys.indexes 
WHERE name='YourIndexName' AND object_id = OBJECT_ID('Schema.YourTableName')
AdaTheDev
la source
76
Vous pouvez également encapsuler l'instruction dans un fichier IF EXISTS(SELECT * ...) BEGIN ... END.
bounav
26
Il convient de mentionner que YourTableNamele nom doit être complet avec le schéma
Marek
2
@blasto Si vous utilisez un schéma non par défaut, comme dans la plupart de mes cas, la spécification du schéma comme préfixe est obligatoire. Dans les autres cas, vous n'obtiendrez aucun résultat dans cette requête
Marek
3
Pour vérifier par rapport à une table temporaire, vous pouvez utiliser 'tempdb.sys.indexes' et 'tempdb .. # TableName'. (ref Bjorn D. Jensen )
crokusek
7
Juste pour ajouter: "À partir de SQL Server 2016, vous pouvez utiliser la syntaxe DROP INDEX IF EXISTS." Documentation MS
heringer
100

Pour SQL 2008 et versions ultérieures , une méthode plus concise, au niveau du codage, pour détecter l'existence d'index consiste à utiliser la INDEXPROPERTYfonction intégrée:

INDEXPROPERTY ( object_ID , index_or_statistics_name , property )  

L'utilisation la plus simple est avec la IndexIDpropriété:

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

Si l'index existe, ce qui précède renverra son ID; sinon, il reviendra NULL.

Mr McGoo
la source
71

AdaTheDEV, j'ai utilisé votre syntaxe et créé ce qui suit et pourquoi.

Problème: le processus s'exécute une fois par trimestre en prenant une heure en raison de l'index manquant.

Correction: modifier le processus de requête ou la procédure pour vérifier l'index et le créer s'il manque ... Le même code est placé à la fin de la requête et la procédure pour supprimer l'index car il n'est pas nécessaire mais trimestriel. Afficher uniquement la syntaxe de dépôt ici

-- 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
la source
15

Un léger écart par rapport à la question initiale peut toutefois se révéler utile pour les futurs atterrissage ici veulent DROPet CREATEun index, par exemple dans un script de déploiement.

Vous pouvez contourner la vérification existante simplement en ajoutant ce qui suit à votre instruction create:

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

En savoir plus ici: CREATE INDEX (Transact-SQL) - Clause DROP_EXISTING

NB Comme mentionné dans les commentaires, l'index doit déjà exister pour que cette clause fonctionne sans générer d'erreur.

Chris Pickford
la source
8
En fait .. soyez prudent! Cela échouera si l'index n'existe pas déjà! Au moins dans SQL Server 2008.
Andrey Kaipov
1
... et il échoue toujours dans SQL 2016
Magier
2
Un autre effet (peut-être évident) est qu'il va toujours recréer l'index. Ce n'est peut-être pas ce que vous voulez. La suppression et la création d'un index sur une grande table est une opération coûteuse - surtout si l'index existant est déjà celui que vous souhaitez. Cette déclaration est bonne pour le remplacement en une seule étape. Il ne compare pas l'index existant - plutôt une force brute "faites cela, même s'il existe - laissez-le tomber ... faites-le, faites-le!" :-) Il nécessite toujours toutes les vérifications que OP recherchait. Cependant, si l'index doit être remplacé, il combine DROP / CREATE.
ripvlan
10

Si le but caché de votre question est DROPl'index avant de créer INSERTune grande table, alors ceci est utile à une ligne:

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

Cette syntaxe est disponible depuis SQL Server 2016. Documentation pour IF EXISTS:

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

Dans le cas où vous traitez une clé de primery à la place, utilisez ceci:

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

A écrit la fonction ci-dessous qui me permet de vérifier rapidement pour voir si un index existe; fonctionne exactement comme 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: Cela retourne juste le OBJECT_ID de la table, mais il sera NULL si l'index n'existe pas. Je suppose que vous pouvez définir cela pour renvoyer index_id, mais ce n'est pas super utile.

Mark Williams
la source
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
la source
-1

Pour vérifier que l'index clusterisé existe sur une table particulière ou non:

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
la source
5
Cela renvoie des clés primaires et des contraintes uniques, mais aucune d'entre elles n'est nécessairement un index clusterisé.
Mark Sowul
index_id = 1 est une clause where incorrecte. Un indice différent peut être attribué à l'index
Fuzzybear