สร้างดัชนีที่ไม่ซ้ำกันแบบไม่เป็นคลัสเตอร์ภายในคำสั่ง CREATE TABLE ด้วย SQL Server


95

เป็นไปได้ที่จะสร้างคีย์หลักหรือดัชนีเฉพาะภายในคำสั่ง SQL Server CREATE TABLE เป็นไปได้ไหมที่จะสร้างดัชนีที่ไม่ซ้ำกันภายในคำสั่ง CREATE TABLE

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

อีกครั้งเป้าหมายคือการสร้างดัชนีที่ไม่ซ้ำกันภายในคำสั่ง CREATE TABLE ไม่ใช่หลังจากนั้น

สำหรับสิ่งที่คุ้มค่าฉันไม่พบว่า[รายการ SQL Server Books Online สำหรับ CREATE TABLE]จะเป็นประโยชน์

นอกจากนี้[คำถามนี้]เกือบจะเหมือนกัน แต่คำตอบที่ยอมรับจะใช้ไม่ได้

คำตอบ:


126

คุณไม่สามารถ. สร้าง / แก้ไขตารางยอมรับเฉพาะ CONSTRAINT ที่จะถูกเพิ่มไม่ใช่ดัชนี ความจริงที่ว่าคีย์หลักและข้อ จำกัด เฉพาะถูกนำมาใช้ในแง่ของดัชนีนั้นเป็นผลข้างเคียง ในการจัดการดัชนีคุณมี CREATE / ALTER / DROP INDEX ตามที่คุณทราบดี

เหตุใดคุณจึงมีข้อกำหนดดังกล่าวในการเพิ่มดัชนีที่ไม่ซ้ำกัน - ไม่ใช่คลัสเตอร์ในคำสั่ง CREATE TABLE

โปรดสังเกตว่า SQL Server 2014 แนะนำตัวเลือกการสร้างดัชนีแบบอินไลน์ :

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
ขอบคุณสำหรับคำอธิบายที่ยอดเยี่ยม! ทำไม? ด้วยเหตุผลด้านความงามล้วนๆ ฉันคิดว่ามันจะสะดวกสำหรับทุกคนที่อ่านสคริปต์หากมีข้อ จำกัด / ดัชนีทั้งหมดอยู่ในคำสั่งเดียวกัน โดยส่วนตัวแล้วฉันต้องการทราบว่าคอลัมน์ที่เป็นของ Foreign Key นั้นมีดัชนีหรือไม่และนี่อาจเป็นวิธีการที่ดีในการจัดกลุ่มข้อมูลนี้อย่างมีเหตุผลในคำสั่งเดียวกัน
Mike

ฉันเข้าใจError: (1146) Table 'tablename' doesn't existแล้วฮ่า ๆ ๆ แดกดัน
Aminah Nuraini

13

ตามเอกสารT-SQL CREATE TABLEในปี 2014 คำจำกัดความของคอลัมน์สนับสนุนการกำหนดดัชนี:

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

และไวยากรณ์ถูกกำหนดให้เป็น:

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

ดังนั้นหลายสิ่งที่คุณสามารถทำได้ในฐานะคำสั่งแยกต่างหากสามารถทำได้แบบอินไลน์ ฉันสังเกตว่าincludeไม่ใช่ตัวเลือกในไวยากรณ์นี้ดังนั้นบางสิ่งจึงเป็นไปไม่ได้

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
)

คุณยังสามารถกำหนดดัชนีแบบอินไลน์ให้เป็นบรรทัดหลังคอลัมน์ได้อีกด้วย แต่อยู่ในคำสั่งสร้างตารางและสิ่งนี้อนุญาตให้มีหลายคอลัมน์ในดัชนี แต่ยังไม่มีincludeอนุประโยค:

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

}   

ตัวอย่างเช่นที่นี่เราเพิ่มดัชนีทั้งคอลัมน์ c และ 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)
)

1
สิ่งนี้ใช้งานได้ดีและตาม BOL ย้อนกลับไปอย่างน้อยปี 2008 เช่นเดียวกับ OP ฉันพบว่ารหัสที่ฉันเห็นเป็นส่วนใหญ่ (มักสร้างโดย SSMS) ทำให้ลูกตาของฉันเจ็บและฉันก็ชอบคำจำกัดความตารางของฉันเพื่อให้เหมาะสมกับมนุษย์ที่มีเหตุผล ขอบคุณ.
Wade Hatler

8

มันเป็นคำสั่งต่างหาก

นอกจากนี้ยังไม่สามารถแทรกลงในตารางและเลือกจากตารางและสร้างดัชนีในคำสั่งเดียวกันได้

รายการ BOL ประกอบด้วยข้อมูลที่คุณต้องการ:

คลัสเตอร์ | ไม่รวม
ระบุว่าดัชนีคลัสเตอร์หรือที่ไม่เป็นคลัสเตอร์ถูกสร้างขึ้นสำหรับคีย์หลักหรือข้อ จำกัด ที่ไม่ซ้ำกัน ข้อ จำกัด คีย์หลักเริ่มต้นเป็น CLUSTERED และข้อ จำกัด UNIQUE เริ่มต้นเป็น NONCLUSTERED

ในคำสั่ง CREATE TABLE สามารถระบุ CLUSTERED สำหรับข้อ จำกัด เดียวเท่านั้น ถ้า CLUSTERED ถูกระบุสำหรับข้อ จำกัด UNIQUE และระบุข้อ จำกัด ของคีย์หลักไว้ด้วยคีย์หลักจะมีค่าดีฟอลต์เป็น NONCLUSTERED

คุณสามารถสร้างดัชนีบนฟิลด์ PK แต่ไม่ใช่ดัชนีที่ไม่ใช่คลัสเตอร์บนฟิลด์ที่ไม่ใช่ pk ที่ไม่ซ้ำกัน จำกัด

ดัชนี NCL ไม่เกี่ยวข้องกับโครงสร้างของตารางและไม่ใช่ข้อ จำกัด ของข้อมูลภายในตาราง เป็นเอนทิตีแยกต่างหากที่รองรับตาราง แต่ไม่รวมอยู่ในฟังก์ชันการทำงานหรือการออกแบบ

นั่นเป็นเหตุผลว่าทำไมจึงเป็นคำสั่งแยกต่างหาก ดัชนี NCL ไม่เกี่ยวข้องกับตารางจากมุมมองการออกแบบ (แม้ว่าจะมีการเพิ่มประสิทธิภาพการสืบค้น)


7

คำตอบที่ได้รับการยอมรับของวิธีการสร้างดัชนีแบบอินไลน์สคริปต์การสร้างตารางไม่ได้ผลสำหรับฉัน สิ่งนี้ทำ:

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

โปรดจำไว้ว่า Foreign Keys ไม่ได้สร้างดัชนีดังนั้นจึงเป็นแนวทางปฏิบัติที่ดีในการจัดทำดัชนีเนื่องจากคุณมีแนวโน้มที่จะเข้าร่วมกับพวกเขามากกว่า


ฉันไม่ได้ทำตามคำสั่งสุดท้ายนั้น ฉันจะเห็นด้วยกับคำสั่งนั้นหากเป็นเรื่องปกติในการสืบค้นตารางของคุณด้วยคีย์ต่างประเทศ แต่ไม่ใช่เพียงแค่คุณเข้าร่วมดังนั้นจึงควรจัดทำดัชนี ตัวอย่าง: ค้นหาพนักงานทั้งหมดและชื่อ บริษัท ของรหัส บริษัท X - จากนั้นตรวจสอบให้แน่ใจว่าดัชนีใน FK ช่วยได้ ค้นหาพนักงานทั้งหมดและชื่อ บริษัท ของพวกเขาด้วยนามสกุลขึ้นต้นด้วย A; ดัชนีบน FK ไม่ได้ช่วยอะไร กล่าวอีกนัยหนึ่งฉันไม่แน่ใจว่า "เพราะคุณเข้าร่วมคุณควรจัดทำดัชนี" เป็นแนวทางปฏิบัติที่ดี ฉันพลาดอะไรไปรึเปล่า?
พอล

2
ดัชนีทำให้การสืบค้นเข้าร่วมเร็วขึ้น
ScubaSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.