Wie überprüfen Sie, ob ein bestimmter Index in einer Tabelle vorhanden ist?


288

Etwas wie das:

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

aber für Indizes.


11
Ich wünschte, INFORMATION_SCHEMA hätte tatsächlich alle Schemainformationen
Alan Macdonald

Antworten:


480

Sie können dies mit einer einfachen Auswahl wie folgt tun:

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

76
Sie können die Anweisung auch in a einschließen IF EXISTS(SELECT * ...) BEGIN ... END.
Bounav

26
Es ist erwähnenswert, dass YourTableNameder vollständige Name mit Schema sein sollte
Marek

2
@blasto Wenn Sie wie in den meisten meiner Fälle ein nicht standardmäßiges Schema verwenden, müssen Sie das Schema als Präfix angeben. In einem anderen Fall erhalten Sie keine Ergebnisse in dieser Abfrage
Marek

3
Verwenden Sie zum Überprüfen einer temporären Tabelle 'tempdb.sys.indexes' und 'tempdb .. # TableName'. (Ref. Björn D. Jensen )
Crokusek

7
Nur um hinzuzufügen: "Ab SQL Server 2016 können Sie die DROP INDEX IF EXISTS-Syntax verwenden." MS Dokumentation
Heringer

100

Für SQL 2008 und höher ist die Verwendung der INDEXPROPERTYintegrierten Funktion eine präzisere Methode zum Erkennen der Indexexistenz in Bezug auf die Codierung :

INDEXPROPERTY ( object_ID , index_or_statistics_name , property )  

Die einfachste Verwendung ist mit der IndexIDEigenschaft:

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

Wenn der Index vorhanden ist, gibt der oben genannte seine ID zurück. Wenn dies nicht der Fall ist, wird es zurückkehren NULL.


71

AdaTheDEV, ich habe Ihre Syntax verwendet und Folgendes erstellt und warum.

Problem: Der Prozess wird vierteljährlich ausgeführt und dauert aufgrund des fehlenden Index eine Stunde.

Korrektur: Ändern Sie den Abfrageprozess oder die Prozedur, um nach dem Index zu suchen und ihn zu erstellen, falls er fehlt. Der gleiche Code wird am Ende der Abfrage und der Prozedur zum Entfernen des Index platziert, da er nicht benötigt wird, sondern vierteljährlich. Hier wird nur die Drop-Syntax angezeigt

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

15

Eine leichte Abweichung von der ursprünglichen Frage kann sich jedoch als nützlich für zukünftige Menschen erweisen, die hier landen und wollen DROPundCREATE einen Index, dh in einem Bereitstellungsskript.

Sie können die vorhandene Prüfung umgehen, indem Sie Ihrer create-Anweisung Folgendes hinzufügen:

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

Lesen Sie hier mehr: CREATE INDEX (Transact-SQL) - DROP_EXISTING-Klausel

Hinweis Wie in den Kommentaren erwähnt, muss der Index bereits vorhanden sein, damit diese Klausel ohne Fehler funktioniert.


8
Eigentlich .. sei vorsichtig! Dies schlägt fehl, wenn der Index noch nicht vorhanden ist! Zumindest in SQL Server 2008.
Andrey Kaipov

1
... und es schlägt immer noch in SQL 2016 fehl
Magier

2
Ein weiterer (möglicherweise offensichtlicher) Effekt besteht darin, dass der Index immer neu erstellt wird. Dies ist möglicherweise nicht das, was Sie wollen. Das Löschen und Erstellen eines Index für eine große Tabelle ist eine teure Operation - insbesondere, wenn der vorhandene Index bereits der gewünschte ist. Diese Aussage eignet sich für den Austausch in einem Schritt. Es vergleicht nicht den vorhandenen Index - eher eine brutale Kraft "Mach das, auch wenn es existiert - lass es fallen ... mach es einfach, mach es fertig!" :-) Es erfordert immer noch alle Überprüfungen, nach denen OP gesucht hat. Wenn der Index jedoch ersetzt werden muss, kombiniert er DROP / CREATE.
Ripvlan

10

Wenn der versteckte Zweck Ihrer Frage darin besteht, DROPden Index vor dem Erstellen INSERTeiner großen Tabelle zu erstellen, ist dies ein nützlicher Einzeiler:

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

Diese Syntax ist seit SQL Server 2016 verfügbar. Dokumentation für IF EXISTS:

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

Wenn Sie stattdessen einen Primery-Schlüssel verwenden, verwenden Sie diesen:

ALTER TABLE [TableName] DROP CONSTRAINT IF EXISTS [PK_name] 

7

Schrieb die folgende Funktion, mit der ich schnell überprüfen kann, ob ein Index vorhanden ist. funktioniert genauso wie 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

BEARBEITEN: Dies gibt nur die OBJECT_ID der Tabelle zurück, ist jedoch NULL, wenn der Index nicht vorhanden ist. Ich nehme an, Sie könnten dies so einstellen, dass index_id zurückgegeben wird, aber das ist nicht besonders nützlich.


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

-1

So überprüfen Sie, ob der Clustered Index für eine bestimmte Tabelle vorhanden ist oder nicht:

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

5
Dies gibt Primärschlüssel und eindeutige Einschränkungen zurück, aber keiner davon ist notwendigerweise ein Clustered-Index.
Mark Sowul

index_id = 1 ist eine falsche where-Klausel. Dem Index kann eine andere ID zugewiesen werden
Fuzzybear
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.