Erstellen Sie mit SQL Server einen nicht gruppierten nicht eindeutigen Index in der Anweisung CREATE TABLE

92

Es ist möglich, einen Primärschlüssel oder einen eindeutigen Index in einer SQL Server-Anweisung CREATE TABLE zu erstellen. Ist es möglich, einen nicht eindeutigen Index innerhalb einer CREATE TABLE-Anweisung zu erstellen ?

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

Wiederum besteht das Ziel darin, den nicht eindeutigen Index innerhalb der Anweisung CREATE TABLE zu erstellen, nicht danach.

Für das, was es wert ist, fand ich den [SQL Server Books Online-Eintrag für CREATE TABLE] nicht hilfreich.

Auch [Diese Frage] ist nahezu identisch, aber die akzeptierte Antwort trifft nicht zu.

Mike
quelle

Antworten:

122

Du kannst nicht. CREATE / ALTER TABLE akzeptiert nur hinzuzufügende CONSTRAINTs, keine Indizes. Die Tatsache, dass Primärschlüssel und eindeutige Einschränkungen in Bezug auf einen Index implementiert werden, ist ein Nebeneffekt. Wie Sie wissen, haben Sie zum Verwalten von Indizes CREATE / ALTER / DROP INDEX.

Warum müssen Sie der Anweisung CREATE TABLE nicht eindeutige, nicht gruppierte Indizes hinzufügen?

Beachten Sie, dass SQL Server 2014 die Option zum Erstellen eines Inline-Index eingeführt hat :

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
Remus Rusanu
quelle
17
Danke für die tolle Erklärung! Warum? Rein aus ästhetischen Gründen. Ich dachte, es könnte für jeden, der das Skript liest, praktisch sein, wenn alle Einschränkungen / Indizes in derselben Anweisung enthalten sind. Persönlich möchte ich wissen, ob Spalten, die zu einem Fremdschlüssel gehören, auch einen Index haben, und dies war möglicherweise eine gute Methode, um diese Informationen logisch in derselben Anweisung zu gruppieren.
Mike
Ich habe Error: (1146) Table 'tablename' doesn't exist, hahahah, ironisch
Aminah Nuraini
13

Wie pro T-SQL CREATE TABLE - Dokumentation, die Spaltendefinition Stützen 2014 definieren einen Index:

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

und Grammatik ist definiert als:

<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" } ]  

So kann vieles, was Sie als separate Anweisung tun können, inline erfolgen. Mir ist aufgefallen, dass includedies in dieser Grammatik keine Option ist, daher sind einige Dinge nicht möglich.

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
)

Sie können Inline-Indizes auch als eine andere Zeile nach Spalten definieren lassen, jedoch innerhalb der Anweisung create table. Dies ermöglicht mehrere Spalten im Index, jedoch immer noch keine includeKlausel:

< 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" } ]  

}   

Zum Beispiel fügen wir hier einen Index für beide Spalten c und d hinzu:

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)
)
AaronLS
quelle
1
Das funktioniert super und laut BOL geht es zumindest auf das Jahr 2008 zurück. Wie beim OP finde ich, dass der Code, den ich meistens sehe (normalerweise von SSMS generiert), meine Augäpfel verletzt, und ich mag es einfach, wenn meine Tabellendefinitionen für einen rationalen Menschen Sinn machen. Vielen Dank.
Wade Hatler
8

Es ist eine separate Aussage.

Es ist auch nicht möglich, in eine Tabelle einzufügen und daraus auszuwählen und einen Index in derselben Anweisung zu erstellen.

Der BOL-Eintrag enthält die Informationen, die Sie benötigen:

CLUSTERED | NONCLUSTERED Geben Sie
an, dass ein Clustered- oder ein Nonclustered-Index für die Einschränkung PRIMARY KEY oder UNIQUE erstellt wird. PRIMARY KEY-Einschränkungen sind standardmäßig CLUSTERED und UNIQUE-Einschränkungen standardmäßig NONCLUSTERED.

In einer CREATE TABLE-Anweisung kann CLUSTERED nur für eine Einschränkung angegeben werden. Wenn CLUSTERED für eine EINZIGARTIGE Einschränkung angegeben ist und auch eine PRIMARY KEY-Einschränkung angegeben ist, ist der PRIMARY KEY standardmäßig NONCLUSTERED.

Sie können einen Index für ein PK-Feld erstellen, jedoch keinen nicht gruppierten Index für ein nicht pk-nicht eindeutig eindeutiges Feld.

Ein NCL-Index ist für die Struktur der Tabelle nicht relevant und stellt keine Einschränkung für die Daten in der Tabelle dar. Es handelt sich um eine separate Entität, die die Tabelle unterstützt, jedoch nicht in die Funktionalität oder das Design integriert ist.

Deshalb ist es eine separate Aussage. Der NCL-Index ist aus Entwurfssicht für die Tabelle irrelevant (trotz Abfrageoptimierung).

JNK
quelle
7

Die akzeptierte Antwort zum Erstellen eines Index inline eines Tabellenerstellungsskripts hat bei mir nicht funktioniert. Dies tat:

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

Denken Sie daran, dass Fremdschlüssel keine Indizes erstellen. Es wird daher empfohlen, sie zu indizieren, da Sie höchstwahrscheinlich Mitglied werden.

ScubaSteve
quelle
Ich folge dieser letzten Aussage nicht. Ich würde dieser Aussage zustimmen, wenn es üblich ist, Ihre Tabelle mit dem Fremdschlüssel abzufragen. aber nicht einfach, dass Sie daran teilnehmen, deshalb sollte es indiziert werden. Beispiel: Finden Sie alle Mitarbeiter und ihren Firmennamen mit der Firmen-ID X - dann hilft sicher ein Index auf der FK. Finden Sie alle Mitarbeiter und ihren Firmennamen, wobei der Nachname mit A beginnt. Index auf der FK hilft nicht. Mit anderen Worten, ich bin mir nicht sicher, ob "weil Sie daran teilnehmen, sollten Sie es indizieren" eine gute Praxis ist. Vermisse ich etwas
Paul
2
Indizes beschleunigen Join-Abfragen.
ScubaSteve