Tabloda belirli bir dizinin mevcut olup olmadığını nasıl kontrol edersiniz?


288

Bunun gibi bir şey:

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

ancak dizinler için.


11
Keşke BİLGİ_SCHEMA tüm şema bilgilerine sahip olsaydı
Alan Macdonald

Yanıtlar:


480

Bunu, aşağıdaki gibi düz bir seçim kullanarak yapabilirsiniz:

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

76
Ayrıca ifadeyi bir IF EXISTS(SELECT * ...) BEGIN ... END.
bounav

26
YourTableNameŞema ile tam adı olması gerektiğini belirtmek gerekir
Marek

2
@blasto Çoğu durumda olduğu gibi varsayılan olmayan bir şema kullanıyorsanız, şemayı önek olarak belirtmek zorunludur. Diğer durumda, bu sorguda herhangi bir sonuç
Marek

3
Bir geçici tabloya karşı denetlemek için, 'tempdb.sys.indexes' ve 'tempdb .. # TableName' kullanabilirsiniz. (ref Bjorn D. Jensen )
crokusek

7
Sadece eklemek için: "SQL Server 2016 ile başlayarak, DROP INDEX IF EXISTS sözdizimini kullanabilirsiniz." MS belgeleri
heringer

100

İçin SQL 2008 ve daha yeni , daha özlü yöntemi endeks varlığını tespit etmek için, akıllıca kodlama kullanmaktır INDEXPROPERTYyerleşik fonksiyonu:

INDEXPROPERTY ( object_ID , index_or_statistics_name , property )  

En basit kullanım IndexIDözelliği ile:

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

Dizin varsa, yukarıdakiler kimliğini döndürür; değilse, geri dönecektir NULL.


71

AdaTheDEV, sözdizimini kullandım ve aşağıdakileri ve nedenini oluşturdum.

Sorun: İşlem, eksik dizin nedeniyle saatte bir çeyrek kez çalışıyor.

Düzeltme: Sorgu işlemini veya Dizini denetleme ve eksikse oluşturma yordamını değiştirin ... Aynı kod, sorgunun sonuna ve gerekmediği için üç ayda bir dizin kaldırma yordamının sonuna yerleştirilir. Buraya sadece bırak sözdizimi gösteriliyor

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

Bununla birlikte, orijinal sorudan hafif bir sapma buraya gelmek isteyen gelecekteki insanlar DROPve CREATEbir indeks, yani bir dağıtım betiği için yararlı olabilir .

Create deyiminize aşağıdakileri ekleyerek mevcut denetimi atlayabilirsiniz:

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

Daha fazla bilgiyi buradan edinebilirsiniz: CREATE INDEX (Transact-SQL) - DROP_EXISTING Yan tümcesi

Not Yorumlarda belirtildiği gibi, bu fıkranın bir hata atmadan çalışması için dizin zaten mevcut olmalıdır.


8
Aslında .. dikkatli ol! Dizin zaten yoksa bu başarısız olur! En azından SQL Server 2008'de.
Andrey Kaipov

1
... ve SQL 2016'da hala başarısız
Magier

2
Başka bir (belki de açık) etki, her zaman dizini yeniden oluşturacağıdır. İstediğiniz bu olmayabilir. Büyük bir tabloda bir dizin bırakmak ve oluşturmak pahalı bir işlemdir - esp varolan dizin zaten istediğiniz dizinse. Bu ifade tek adımlı değiştirme için iyidir. Mevcut endeksi karşılaştırmaz - daha ziyade kaba bir güç "bunu yap, hatta mevcut - bırak ... sadece yap, tamam!" :-) Hala OP aradığı tüm kontrol gerektirir. Ancak, dizinin değiştirilmesi gerekiyorsa DROP / CREATE öğesini birleştirir.
ripvlan

10

Sorunuzun gizli amacı büyük bir tabloya DROPgeçmeden önce dizine INSERTyönelikse, bu tek satırlık yararlıdır:

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

Bu sözdizimi için SQL Server 2016 Dokümantasyon beri mevcuttur IF EXISTS:

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

Bunun yerine bir primery anahtarıyla uğraşırsanız, bunu kullanın:

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

7

Bir dizinin var olup olmadığını hızlıca kontrol etmemi sağlayan aşağıdaki işlevi yazdı; tıpkı OBJECT_ID gibi çalışır.

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: Bu sadece tablonun OBJECT_ID döndürür, ancak dizin yoksa NULL olur. Sanırım bu index_id dönmek için ayarlayabilirsiniz, ama bu süper yararlı değil.


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

Kümelenmiş Dizin'in belirli bir tabloda var olup olmadığını kontrol etmek için:

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
Bu, birincil anahtarları ve benzersiz kısıtlamaları döndürür, ancak bunların hiçbiri mutlaka kümelenmiş bir dizin değildir.
Mark Sowul

index_id = 1, yan tümce nerede yanlış.
Dizine
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.