Cú pháp SQL Server để tạo một chỉ mục cụm cũng là một khóa chính là:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Theo như nhận xét của bạn: "tạo PK sử dụng chỉ mục được đặt tên", đoạn mã trên sẽ dẫn đến chỉ mục khóa chính được đặt tên là "PK_c".
Khóa chính và khóa phân cụm không phải là cùng một cột. Bạn có thể định nghĩa chúng một cách riêng biệt. Trong ví dụ trên, thay đổi CLUSTEREDtừ khóa thành NONCLUSTERED, và sau đó chỉ cần thêm một chỉ mục được nhóm bằng CREATE INDEXcú pháp:
CREATE TABLE dbo.c
(
c1 INT,
c2 INT,
CONSTRAINT PK_c
PRIMARY KEY NONCLUSTERED (c1, c2)
);
CREATE CLUSTERED INDEX CX_c ON dbo.c (c2);
Trong SQL Server, chỉ mục được nhóm là bảng, chúng là một và giống nhau. Một chỉ mục cụm xác định thứ tự logic của các hàng được lưu trữ trong bảng. Trong ví dụ đầu tiên của tôi, các hàng được lưu trữ theo thứ tự các giá trị của cột c1và c2cột. Vì khóa phân cụm cũng được định nghĩa là khóa chính, nên sự kết hợp c1và c2phải là toàn bảng duy nhất.
Trong ví dụ thứ hai, khóa chính bao gồm các cột c1và c2cột, tuy nhiên khóa phân cụm chỉ là c2cột. Vì tôi không chỉ định UNIQUEthuộc tính trong CREATE INDEXcâu lệnh, khóa cluster ( c2) không bắt buộc phải là duy nhất trên bảng. Một "uniquifier" sẽ được SQL Server tự động tạo và gắn vào các giá trị trong c2cột để tạo khóa phân cụm. Khóa phân cụm này, vì nó là duy nhất, sau đó sẽ được sử dụng làm id hàng trong các chỉ mục khác được tạo trên bảng.
Để chứng minh khóa phân cụm điều khiển bố cục các hàng trong bộ lưu trữ, bạn có thể sử dụng chức năng không có giấy tờ , fn_PhysLocCracker(%%PHYSLOC%%). Đoạn mã sau cho thấy các hàng được đặt trên đĩa theo thứ tự của c2cột, mà tôi đã xác định là khóa phân cụm:
USE tempdb;
CREATE TABLE dbo.PKTest
(
c1 INT NOT NULL
, c2 INT NOT NULL
, c3 VARCHAR(256) NOT NULL
);
ALTER TABLE PKTest
ADD CONSTRAINT PK_PKTest
PRIMARY KEY NONCLUSTERED (c1, c2);
CREATE CLUSTERED INDEX CX_PKTest
ON dbo.PKTest(c2);
TRUNCATE TABLE dbo.PKTest;
INSERT INTO dbo.PKTest (c1, c2, c3)
SELECT TOP(25) o1.object_id / o2.object_id, o2.object_id, o1.name + '.' + o2.name
FROM sys.objects o1
, sys.objects o2
WHERE o1.object_id >0
and o2.object_id > 0;
SELECT plc.file_id
, plc.page_id
, plc.slot_id
, pk.*
FROM dbo.PKTest pk
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;
Các kết quả từ tempdb của tôi là:

Trong hình trên, ba cột đầu tiên được xuất ra từ fn_PhysLocCrackerhàm, hiển thị thứ tự vật lý của các hàng trên đĩa. Bạn có thể thấy slot_idgiá trị tăng bước khóa với c2giá trị, đó là khóa phân cụm. Chỉ mục khóa chính lưu trữ các hàng theo một thứ tự khác, có thể được nhìn thấy bằng cách buộc SQL Server trả về kết quả từ việc quét khóa chính:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Lưu ý, tôi đã không sử dụng một ORDER BYmệnh đề trong tuyên bố trên vì tôi đang cố gắng hiển thị thứ tự của các mục trong chỉ mục khóa chính.
Đầu ra từ truy vấn trên là:

Nhìn vào fn_PhysLocCrackerhàm, chúng ta có thể thấy thứ tự vật lý của chỉ số khóa chính.
SELECT plc.file_id
, plc.page_id
, plc.slot_id
, pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN)
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;
Vì chúng tôi chỉ đọc từ chính chỉ mục, tức là không có cột nào bên ngoài chỉ mục được tham chiếu trong truy vấn, nên các %%PHYSLOC%%giá trị đại diện cho các trang trong chính chỉ mục.
Kết quả:

create table c (c1 int not null primary key, c2 int)