Die SQL Server-Syntax zum Erstellen eines Clustered-Index, der auch ein Primärschlüssel ist, lautet:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Was Ihren Kommentar betrifft: "Eine PK einen benannten Index verwenden lassen", führt der obige Code dazu, dass der Primärschlüsselindex "PK_c" heißt.
Der Primärschlüssel und der Clusterschlüssel müssen nicht dieselben Spalten sein. Sie können sie separat definieren. Ändern Sie im obigen Beispiel das CLUSTEREDSchlüsselwort in NONCLUSTEREDund fügen Sie dann einfach einen Clustered-Index mit der folgenden CREATE INDEXSyntax hinzu:
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 der Clustered - Index ist der Tisch, sie sind ein-und-die-gleiche. Ein Clustered-Index definiert die logische Reihenfolge der in der Tabelle gespeicherten Zeilen. In meinem ersten Beispiel werden Zeilen in der Reihenfolge der Werte der Spalten c1und gespeichert c2. Da der Clustering-Schlüssel auch als Primärschlüssel definiert ist, muss die Kombination von c1und c2tabellenweit eindeutig sein.
Im zweiten Beispiel besteht der Primärschlüssel aus den Spalten c1und c2, der Clustering-Schlüssel ist jedoch nur die c2Spalte. Da ich das UNIQUEAttribut in der CREATE INDEXAnweisung nicht angegeben habe , muss der Clustering-Schlüssel ( c2) nicht in der gesamten Tabelle eindeutig sein. Ein "Eindeutiger" wird automatisch von SQL Server erstellt und an die Werte in der c2Spalte angehängt , um den Clustering-Schlüssel zu erstellen. Dieser Clustering-Schlüssel wird, da er jetzt eindeutig ist, als Zeilen-ID in anderen in der Tabelle erstellten Indizes verwendet.
Um zu beweisen, dass der Clustering-Schlüssel das Layout der im Speicher befindlichen Zeilen steuert, können Sie die undokumentierte Funktion verwenden fn_PhysLocCracker(%%PHYSLOC%%). Der folgende Code zeigt, dass die Zeilen in der Reihenfolge der c2Spalte, die ich als Clustering-Schlüssel definiert habe , auf der Festplatte angeordnet sind :
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;
Die Ergebnisse meiner Tempdb sind:

In der Abbildung oben werden die ersten drei Spalten von der fn_PhysLocCrackerFunktion ausgegeben und zeigen die physische Reihenfolge der Zeilen auf der Festplatte. Sie können sehen, dass der slot_idWert den Sperrschritt mit dem Wert erhöht c2, der der Clustering-Schlüssel ist. Der Primärschlüsselindex speichert Zeilen in einer anderen Reihenfolge. Dies lässt sich feststellen, indem SQL Server gezwungen wird, Ergebnisse vom Scannen des Primärschlüssels zurückzugeben:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Beachten Sie, dass ich ORDER BYin der obigen Anweisung keine Klausel verwendet habe, da ich versuche, die Reihenfolge der Elemente im Primärschlüsselindex anzuzeigen.
Die Ausgabe der obigen Abfrage lautet:

Wenn fn_PhysLocCrackerwir uns die Funktion ansehen, können wir die physikalische Reihenfolge des Primärschlüsselindex sehen.
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;
Da wir ausschließlich aus dem Index selbst lesen, dh in der Abfrage keine Spalten außerhalb des Index referenziert werden, %%PHYSLOC%%repräsentieren die Werte die Seiten im Index selbst.
Die Ergebnisse:

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