La sintassi di SQL Server per la creazione di un indice cluster che è anche una chiave primaria è:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Per quanto riguarda il tuo commento: "fare in modo che un PK utilizzi un indice denominato", il codice sopra riportato farà sì che l'indice della chiave primaria venga chiamato "PK_c".
La chiave primaria e la chiave di clustering non devono essere le stesse colonne. Puoi definirli separatamente. Nell'esempio sopra, cambia la CLUSTEREDparola chiave in NONCLUSTERED, quindi aggiungi semplicemente un indice cluster usando la CREATE INDEXsintassi:
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);
In SQL Server l'indice cluster è la tabella, sono tutti uguali. Un indice cluster definisce l'ordine logico delle righe memorizzate nella tabella. Nel mio primo esempio, le righe sono memorizzate nell'ordine dei valori delle colonne c1e c2. Poiché la chiave di clustering è anche definita come chiave primaria, la combinazione di c1e c2deve essere unica a livello di tabella.
Nel secondo esempio, la chiave primaria è composta dalle colonne c1e c2, tuttavia la chiave di clustering è solo la c2colonna. Poiché non ho specificato l' UNIQUEattributo CREATE INDEXnell'istruzione, la chiave di clustering ( c2) non deve essere univoca in tutta la tabella. Un "uniquifier" verrà creato automaticamente da SQL Server e aggiunto ai valori nella c2colonna per creare la chiave di clustering. Questa chiave di clustering, poiché ora è unica, verrà quindi utilizzata come ID di riga in altri indici creati nella tabella.
Al fine di dimostrare i controlli chiave di clustering il layout di righe in deposito, è possibile utilizzare la funzione non documentata, fn_PhysLocCracker(%%PHYSLOC%%). Il codice seguente mostra che le righe sono disposte sul disco in ordine di c2colonna, che ho definito come chiave di clustering:
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;
I risultati dal mio tempdb sono:

Nell'immagine sopra, le prime tre colonne vengono emesse dalla fn_PhysLocCrackerfunzione, mostrando l'ordine fisico delle righe sul disco. Puoi vedere che il slot_idvalore aumenta il passo di blocco con il c2valore, che è la chiave di clustering. L'indice della chiave primaria memorizza le righe in un ordine diverso, che può essere visto forzando SQL Server a restituire risultati dalla scansione della chiave primaria:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Nota, non ho usato una ORDER BYclausola nell'istruzione precedente poiché sto tentando di mostrare l'ordine degli elementi nell'indice della chiave primaria.
L'output della query sopra è:

Osservando la fn_PhysLocCrackerfunzione, possiamo vedere l'ordine fisico dell'indice della chiave primaria.
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;
Poiché stiamo leggendo esclusivamente dall'indice stesso, vale a dire che nessuna colonna esterna all'indice viene referenziata nella query, i %%PHYSLOC%%valori rappresentano le pagine dell'indice stesso.
I risultati:

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