2010-04-22 8 views

risposta

347

È possibile farlo utilizzando un dritto in avanti selezionare in questo modo:

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

Puoi anche inserire l'istruzione in un 'IF EXISTS (SELECT * ...) INIZIA ... FINE'. – bounav

+21

Vale la pena ricordare che 'YourTableName' dovrebbe essere il nome completo con lo schema – Marek

+0

Ho usato la tua query senza la clausola name = 'YourIndexName' e ho notato il nome di un vincolo univoco sulla mia tabella dalla colonna del nome restituita dalla query. È come UNIQ _..... Ottengo un errore - non è un vincolo. Impossibile eliminare il vincolo. Vedi errori precedenti. Come posso risolvere questo? – Steam

-1

Per controllare Clustered Index esiste in particolare tabella 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') 
+5

Restituisce chiavi primarie e vincoli univoci, ma nessuno di questi è necessariamente un indice cluster. –

+0

index_id = 1 non è corretto dove clausola. All'indice può essere assegnato un ID diverso – Fuzzybear

3

ha scritto la seguente funzione che mi permette di fretta controlla se esiste un indice; funziona proprio come 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: Questo solo restituisce l'OBJECT_ID del tavolo, ma sarà NULL se l'indice non esiste. Suppongo che tu possa impostare questo per restituire index_id, ma questo non è super utile.

50

AdaTheDEV, ho usato la sintassi e creato quanto segue e perché.

Problema: il processo viene eseguito una volta al mese, a causa di un indice mancante.

Correzione: Alter processo di interrogazione o la procedura per verificare la presenza di indice e creare se manca ... Stesso codice è posto alla fine della query e procedura per rimuovere indice dato che non è necessario, ma trimestrale. Mostra solo la sintassi di eliminazione qui

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

Un metodo più conciso, per quanto riguarda la codifica, per rilevare l'esistenza dell'indice è il seguente;

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

Se esiste l'indice, INDEXPROPERTY restituirà un Id, se non lo fa, non lo farà.

+1

Disponibile solo da [SQL Server 2008 e versioni successive] (https://msdn.microsoft.com/en-us/library/ms187729.aspx?f=255&MSPPError=-2147217396). – Adi

+3

Questa risposta è superiore in quanto è più facile l'integrazione in uno script di manutenzione. Una nota è che l'ultima opzione 'IndexID' è un comando, non una risposta dipendente dall'oggetto richiesta. [IndexProperty - Microsoft Docs] (https://docs.microsoft.com/en-us/sql/t-sql/functions/indexproperty-transact-sql) –

9

Una leggera deviazione rispetto alla domanda originale potrebbe tuttavia rivelarsi utile per le future persone che atterrano qui desiderando DROP e CREATE un indice, vale a dire in uno script di distribuzione.

È possibile bypassare il controllo esiste semplicemente aggiungendo quanto segue al comando create:

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

Read more here: CREATE INDEX (Transact-SQL) - DROP_EXISTING Clause

N.B. Come menzionato nei commenti, l'indice deve già esistere affinché questa clausola funzioni senza generare un errore.

+5

In realtà .. fai attenzione! Questo fallirà se l'indice non esiste già! Almeno in SQL Server 2008. –

+0

... e non riesce ancora in SQL 2016 – Magier

+1

Avrei dovuto leggere i commenti prima di andare per l'implementazione – Rabin

0

È possibile utilizzare un UDF come:

IF (SELECT [dbo].[Index_Exists] (N'SchemaName', N'TableName', N'IndexName')) = 0 
BEGIN 
    -- Your script 
END 

Questa funzione assicura che l'indice si fa riferimento è quella giusta in quanto potrebbero utilizzare lo stesso indice e/o il nome della tabella per i diversi schemi:

CREATE FUNCTION [dbo].[Index_Exists] (@Schema_Name sysname, @Table_Name sysname, @Index_Name sysname) 
RETURNS bit 
WITH EXECUTE AS CALLER 
AS 
BEGIN 
DECLARE @Output bit 

SET @Schema_Name = ISNULL(@Schema_Name, N'dbo'); 

IF EXISTS (SELECT * 
      FROM sys.indexes ind 
      JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id 
      JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id 
      JOIN sys.tables t ON ind.object_id = t.object_id 
      WHERE @Table_Name = t.[name] 
      AND  @Schema_Name = OBJECT_SCHEMA_NAME(t.[object_id]) 
      AND  @Index_Name = ind.[name] 
     ) SET @Output = CAST(1 as bit) 

RETURN ISNULL(@Output,CAST(0 as bit)) 
END 
Problemi correlati