SQL Server ile CREATE TABLE deyimi içinde kümelenmemiş benzersiz olmayan bir dizin oluşturun


95

Bir SQL Server CREATE TABLE deyiminde birincil anahtar veya benzersiz dizin oluşturmak mümkündür. CREATE TABLE ifadesi içinde benzersiz olmayan bir dizin oluşturmak mümkün müdür ?

CREATE TABLE MyTable(
    a int NOT NULL
    ,b smallint NOT NULL
    ,c smallint NOT NULL
    ,d smallint NOT NULL
    ,e smallint NOT NULL

    -- This creates a primary key
    ,CONSTRAINT PK_MyTable PRIMARY KEY CLUSTERED (a)

    -- This creates a unique nonclustered index on columns b and c
    ,CONSTRAINT IX_MyTable1 UNIQUE (b, c)

    -- Is it possible to create a non-unique index on columns d and e here?
    -- Note: these variations would not work if attempted:
    -- ,CONSTRAINT IX_MyTable2 INDEX (d, e)
    -- ,CONSTRAINT IX_MyTable3 NONCLUSTERED INDEX (d, e)
);
GO

-- The proposed non-unique index should behave identically to
-- an index created after the CREATE TABLE statement. Example:
CREATE NONCLUSTERED INDEX IX_MyTable4 ON MY_TABLE (d, e);
GO

Yine amaç, benzersiz olmayan dizini CREATE TABLE deyiminden sonra değil içinde oluşturmaktır.

Değeri ne olursa olsun, [CREATE TABLE için SQL Server Books Online girişini] yararlı bulmadım .

Ayrıca, [Bu Soru] neredeyse aynıdır, ancak kabul edilen cevap geçerli değildir.

Yanıtlar:


126

Yapamazsın. CREATE / ALTER TABLE yalnızca eklenecek olan CONSTRAINT'leri kabul eder, indeksleri kabul etmez. Birincil anahtar ve benzersiz kısıtlamaların bir endeks açısından uygulanması bir yan etkidir. İndeksleri yönetmek için, çok iyi bildiğiniz gibi CREATE / ALTER / DROP INDEX'e sahipsiniz.

Neden CREATE TABLE deyimine benzersiz olmayan kümelenmemiş dizinler eklemek gibi bir gereksiniminiz var?

SQL Server 2014'ün satır içi dizin oluşturma seçeneğini sunduğunu unutmayın :

CREATE TABLE MyTable(
    a int NOT NULL
    ,b smallint NOT NULL
    ,c smallint NOT NULL
    ,d smallint NOT NULL
    ,e smallint NOT NULL

    -- This creates a primary key
    ,CONSTRAINT PK_MyTable PRIMARY KEY CLUSTERED (a)

    -- This creates a unique nonclustered index on columns b and c
    ,CONSTRAINT IX_MyTable1 UNIQUE (b, c)

    -- This creates a non-clustered index on (d, e)
    ,INDEX IX_MyTable4 NONCLUSTERED (d, e)
);
GO

17
Harika açıklama için teşekkürler! Neden? Tamamen estetik nedenlerle. Tüm kısıtlamalar / dizinler aynı ifade içinde yer alıyorsa, betiği okuyan herkes için uygun olacağını düşündüm. Şahsen, bir yabancı anahtara ait sütunların da bir indeksi olup olmadığını bilmek isterim ve bu, bu bilgiyi aynı ifadede mantıksal olarak gruplamak için güzel bir yöntem olabilirdi.
Mike

Bende Error: (1146) Table 'tablename' doesn't exist, hahahah, ironik
Aminah Nuraini

13

Başı olarak T-SQL tablo oluşturmak 2014 yılında, dizin tanımlayan sütun tanımı destekleri belgeler:

<column_definition> ::=  
column_name <data_type>  
    ...
    [ <column_index> ]  

ve dilbilgisi şu şekilde tanımlanır:

<column_index> ::=   
 INDEX index_name [ CLUSTERED | NONCLUSTERED ]  
    [ WITH ( <index_option> [ ,... n ] ) ]  
    [ ON { partition_scheme_name (column_name )   
         | filegroup_name  
         | default   
         }  
    ]   
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]  

Yani ayrı bir ifade olarak yapabileceğiniz şeylerin çoğu satır içi olarak yapılabilir. includeBu dilbilgisinde bir seçenek olmadığını fark ettim , bu yüzden bazı şeyler mümkün değil.

CREATE TABLE MyTable(
    a int NOT NULL
    ,b smallint NOT NULL index IX_MyTable_b nonclustered
    ,c smallint NOT NULL
    ,d smallint NOT NULL
    ,e smallint NOT NULL
)

Ayrıca, sütunlardan sonra başka bir satır olarak, ancak tablo oluşturma deyimi içinde tanımlanmış satır içi dizinlere sahip olabilirsiniz ve bu, dizinde birden çok sütuna izin verir, ancak yine de hiçbir includemadde yoktur :

< table_index > ::=   
{  
    {  
      INDEX index_name [ CLUSTERED | NONCLUSTERED ]   
         (column_name [ ASC | DESC ] [ ,... n ] )   
    | INDEX index_name CLUSTERED COLUMNSTORE  
    | INDEX index_name [ NONCLUSTERED ] COLUMNSTORE (column_name [ ,... n ] )  
    }  
    [ WITH ( <index_option> [ ,... n ] ) ]   
    [ ON { partition_scheme_name (column_name )   
         | filegroup_name  
         | default   
         }  
    ]   
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]  

}   

Örneğin burada hem c hem de d sütunlarına bir dizin ekliyoruz:

CREATE TABLE MyTable(
    a int NOT NULL
    ,b smallint NOT NULL index IX_MyTable_b nonclustered
    ,c smallint NOT NULL
    ,d smallint NOT NULL
    ,e smallint NOT NULL

    ,index IX_MyTable_c_d nonclustered (c,d)
)

1
Bu harika çalışıyor ve BOL'a göre en azından 2008'e kadar gidiyor. OP gibi, çoğunlukla gördüğüm kodun (genellikle SSMS tarafından oluşturulur) gözlerimi incittiğini görüyorum ve tablo tanımlarımın rasyonel bir insan için anlamlı olmasını seviyorum. Teşekkürler.
Wade Hatler

8

Ayrı bir ifade.

Ayrıca bir tabloya girip içinden seçim yapıp aynı ifadede bir dizin oluşturmak da mümkün değildir.

BOL girişi ihtiyacınız olan bilgileri içerir:

KÜMELENMİŞ | NONCLUSTERED
PRIMARY KEY veya UNIQUE kısıtlaması için kümelenmiş veya kümelenmemiş bir dizinin oluşturulduğunu gösterir. BİRİNCİL ANAHTAR kısıtlamaları varsayılan olarak KÜMELENMİŞ olarak ve EŞSİZ sınırlamalar varsayılan olarak NONCLUSTERED olarak ayarlanır.

CREATE TABLE deyiminde, CLUSTERED yalnızca bir kısıtlama için belirtilebilir. UNIQUE kısıtlaması için CLUSTERED belirtilirse ve PRIMARY KEY kısıtlaması da belirtilirse, PRIMARY KEY varsayılan olarak NONCLUSTERED olur.

Bir PK alanında bir dizin oluşturabilirsiniz, ancak pk olmayan, benzersiz olmayan kısıtlı bir alanda kümelenmemiş bir dizin oluşturabilirsiniz.

Bir NCL indeksi tablonun yapısıyla ilgili değildir ve tablonun içindeki veriler üzerinde bir kısıtlama değildir. Bu, tabloyu destekleyen, ancak işlevselliği veya tasarımının ayrılmaz bir parçası olmayan ayrı bir varlıktır.

Bu yüzden ayrı bir ifade. NCL indeksi, tasarım açısından tabloyla ilgisizdir (sorgu optimizasyonuna rağmen).


7

Satır içi bir Dizin oluşturma konusunda kabul edilen yanıt, bir Tablo oluşturma komut dosyası benim için işe yaramadı. Bu yaptı:

CREATE TABLE [dbo].[TableToBeCreated]
(
    [Id] BIGINT IDENTITY(1, 1) NOT NULL PRIMARY KEY
    ,[ForeignKeyId] BIGINT NOT NULL
    ,CONSTRAINT [FK_TableToBeCreated_ForeignKeyId_OtherTable_Id] FOREIGN KEY ([ForeignKeyId]) REFERENCES [dbo].[OtherTable]([Id])
    ,INDEX [IX_TableToBeCreated_ForeignKeyId] NONCLUSTERED ([ForeignKeyId])
)

Unutmayın, Yabancı Anahtarlar Dizin oluşturmaz, bu nedenle büyük olasılıkla onlara katılacağınız için onları dizinlemek iyi bir uygulamadır.


Bu son ifadeyi takip etmiyorum. Tablonuzu yabancı anahtarla sorgulamak olağan bir uygulama ise bu ifadeye katılıyorum; ancak sadece ona katılmakla kalmaz, bu nedenle dizine eklenmelidir. Örnek: Tüm çalışanları ve şirket kimliği X olan şirket adını bulun - sonra FK'deki bir dizinin yardımcı olduğundan emin olun. A ile başlayan soyadıyla birlikte tüm çalışanları ve şirket adlarını bulun; FK'deki dizin yardımcı olmuyor. Başka bir deyişle, "ona katıldığınız için dizine eklemelisiniz" in iyi bir uygulama olduğundan emin değilim. Bir şey mi kaçırıyorum?
Paul,

2
Dizinler birleştirme sorgularını daha hızlı hale getirir.
ScubaSteve
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.