Синтаксис SQL Server для створення кластерного індексу, який також є первинним ключем:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Що стосується Вашого коментаря: "зробити ПК використовувати названий індекс", вищевказаний код призведе до того, що індекс первинного ключа буде названий "PK_c".
Первинний ключ та кластерний ключ не повинні бути однаковими стовпцями. Визначити їх можна окремо. У наведеному вище прикладі змініть CLUSTEREDключове слово на NONCLUSTERED, а потім просто додайте кластерний індекс за допомогою CREATE INDEXсинтаксису:
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);
У SQL Server кластерний індекс - це таблиця, вони є одним і тим же. Кластерний індекс визначає логічний порядок рядків, що зберігаються в таблиці. У моєму першому прикладі рядки зберігаються в порядку значень стовпців c1та c2. Оскільки ключ кластеризації також визначається як основний ключ, комбінація c1та c2повинна бути унікальною для всієї таблиці.
У другому прикладі первинний ключ складається із стовпців c1та c2, проте кластерний ключ - це лише c2стовпець. Оскільки я не вказав UNIQUEатрибут у CREATE INDEXвиписці, ключ кластеризації ( c2) не повинен бути унікальним у таблиці. SQL Server автоматично створить «уніфікатор» та додається до значень у c2стовпці для створення ключа кластеризації. Цей ключ кластеризації, оскільки він тепер унікальний, буде використовуватися як ідентифікатор рядка в інших індексах, створених у таблиці.
Для того , щоб довести , кластеризація ключ управляє розташування рядків в пам'яті, ви можете використовувати недокументовані функції fn_PhysLocCracker(%%PHYSLOC%%). Наступний код показує, що рядки викладаються на диск у порядку c2стовпця, який я визначив як кластерний ключ:
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;
Результати мого tempdb:

На зображенні вище, перші три стовпці виводяться з fn_PhysLocCrackerфункції, показуючи фізичне упорядкування рядків на диску. Ви можете бачити, що slot_idзначення збільшує крок блокування зі c2значенням, яке є кластерним ключем. Індекс первинного ключа зберігає рядки в іншому порядку, що можна побачити, змушуючи SQL Server повертати результати від сканування первинного ключа:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Зауважте, я не використав ORDER BYзастереження у наведеному вище твердженні, оскільки я намагаюся показати порядок елементів у індексі первинного ключа.
Вихід із наведеного вище запиту:

Придивившись до fn_PhysLocCrackerфункції, ми можемо побачити фізичний порядок індексу первинного ключа.
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;
Оскільки ми читаємо виключно з самого індексу, тобто в запиті не посилаються жодні стовпці поза індексом, ці %%PHYSLOC%%значення представляють сторінки самого індексу.
Результати:

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