2011-05-31 18 views
51

Es posible crear una clave principal o índice único dentro de una instrucción CREATE TABLE de SQL Server. ¿Es posible crear un índice no único dentro de una instrucción CREATE TABLE?Crear un índice no único no agrupado dentro de la instrucción CREATE TABLE con SQL Server

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 

Una vez más, el objetivo es crear el índice no exclusivo dentro de la sentencia CREATE TABLE, no después.

Por lo que vale, no encontré el [SQL Server Books Online entry for CREATE TABLE] para ser útil.

Además, [This Question] es casi idéntico, pero la respuesta aceptada no se aplica.

Respuesta

75

No puede. CREAR/ALTERAR TABLA solo acepta RESTRICCIONES para agregar, no índices. El hecho de que la clave principal y las restricciones únicas se implementen en términos de un índice es un efecto secundario. Para administrar los índices, tiene CREAR/ALTERAR/BAJAR ÍNDICE, como bien sabe.

¿Por qué tiene un requerimiento tal como para agregar índices no únicos no agrupados en la instrucción CREATE TABLE?

Tenga en cuenta que SQL Server 2014 introdujo la inline index create option:

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

¡Gracias por la gran explicación! ¿Por qué? Puramente por razones estéticas. Pensé que podría ser conveniente para cualquiera que lea la secuencia de comandos si todas las restricciones/índices están contenidos en la misma declaración. Personalmente, me gusta saber si las columnas que pertenecen a una clave externa también tienen un índice, y este puede haber sido un buen método para agrupar lógicamente esta información en la misma declaración. – Mike

+0

Recibí 'Error: (1146) La tabla 'nombre de tabla' no existe', hahahah, irónico –

7

Es una declaración separada.

Tampoco es posible insertarlo en una tabla y seleccionarlo y crear un índice en la misma instrucción.

La entrada BOL contiene la información que necesita:

CLUSTERED | NONCLUSTERED
Indicate that a clustered or a nonclustered index is created for the PRIMARY KEY or UNIQUE constraint. PRIMARY KEY constraints default to CLUSTERED, and UNIQUE constraints default to NONCLUSTERED.

In a CREATE TABLE statement, CLUSTERED can be specified for only one constraint. If CLUSTERED is specified for a UNIQUE constraint and a PRIMARY KEY constraint is also specified, the PRIMARY KEY defaults to NONCLUSTERED.

Se puede crear un índice en un campo de PK, pero no es un índice no agrupado en un campo-pk no no único con limitaciones.

Un índice NCL no es relevante para la estructura de la tabla, y no es una restricción en los datos dentro de la tabla. Es una entidad separada que admite la tabla pero no forma parte de su funcionalidad o diseño.

Es por eso que es una declaración separada. El índice de NCL es irrelevante para la tabla desde una perspectiva de diseño (a pesar de la optimización de consultas).

+0

¡Gracias por responder! El bit de indexación de la entrada de BOL no fue lo suficientemente explícito como para capturar los índices dentro de la sentencia CREATE TABLE aplicada solo a "PRIMARY KEY o UniqueIngtric constraint [s]", ¡así que gracias por enderezarlo! – Mike

4

La respuesta aceptada de cómo crear un Índice en línea un script de creación de la tabla no funcionó para mí. Esto hizo:

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

Recuerde, claves externas no crear índices, por lo que es una buena práctica para indexarlos a medida que más que probablemente se unirá a ellos.

+0

No estoy siguiendo esa última afirmación. Estoy de acuerdo con esa afirmación si es una práctica habitual consultar su tabla con la clave externa; pero no simplemente que te unas a él, por lo tanto, debe indexarse. Ejemplo: Encuentre todos los empleados y el nombre de su empresa de la identificación de la compañía X. Luego, asegúrese de que un índice en FK ayuda. Encuentre todos los empleados y el nombre de su compañía con apellido que comienza con A; índice en el FK no ayuda. En otras palabras, no estoy seguro de que "porque te unes a él deberías indexarlo" es una buena práctica. ¿Me estoy perdiendo de algo? – Paul

+0

Los índices hacen que las consultas de combinación sean más rápidas. – ScubaSteve

3

Según T-SQL CREATE TABLE documentación, en 2014 la definición de columna es compatible con la definición de un índice:

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

y la gramática se define como:

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

Así que mucho de lo que puede hacer como una separada la declaración se puede hacer en línea.Noté que include no es una opción en esta gramática así que algunas cosas no son posibles.

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 
) 

También puede haber índices línea definida como otra línea después de las columnas, pero dentro de la instrucción create table, y esto permite que múltiples columnas en el índice, pero todavía no hay include cláusula:

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

} 

Para ejemplo aquí agregamos un índice en ambas columnas c y d:

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) 
) 
Cuestiones relacionadas