Équivalent SQL Server de la clause Oracle USING INDEX

9

Existe-t-il un équivalent SQL Server 2008 de la clause USING INDEX dans Oracle? Spécifiquement pour la construction:

CREATE TABLE c(c1 INT, c2 INT);
CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;

Dans la documentation Sql Server sur les index uniques, il indique (emphase ajoutée):

Les index uniques sont implémentés des manières suivantes:

CLÉ PRIMAIRE ou contrainte UNIQUE

Lorsque vous créez une contrainte PRIMARY KEY, un index cluster unique sur la ou les colonnes est automatiquement créé si un index cluster sur la table n'existe pas déjà et que vous ne spécifiez pas un index non cluster unique . La colonne de clé primaire ne peut pas autoriser les valeurs NULL.

Ce qui semble impliquer qu'il existe un moyen de spécifier quel index doit être utilisé pour une clé primaire.

nik
la source
Définissez simplement le PK avec le tableau. create table c (c1 int not null primary key, c2 int)
a_horse_with_no_name
C'est la partie "faire en sorte qu'un PK utilise un index nommé" qui m'intéresse.
nik
Non, il n'y a aucun moyen de le faire. Une clé primaire est une contrainte et un index. Dans ce que vous avez fourni, la clé primaire serait par défaut un index cluster unique. Ce qui ferait de l'autre index défini un doublon à moins que vous n'incluiez à la fois c1 et c2 dans la clause where.
Aaron

Réponses:

7

Existe-t-il un équivalent SQL Server 2008 de la clause USING INDEX dans Oracle?

Non. Lorsque vous créez une clé primaire ou une contrainte unique dans SQL Server, un index unique pour prendre en charge cette contrainte est créé automatiquement, avec les mêmes clés.

Ce qui semble impliquer qu'il existe un moyen de spécifier quel index doit être utilisé pour une clé primaire.

Non. La documentation tente seulement d'expliquer si l'index de prise en charge automatique sera créé en cluster ou non cluster, si vous ne spécifiez pas. Il est libellé de façon confuse, je suis d'accord.

Pour clarifier, lorsque vous ajoutez une contrainte de clé primaire à une table existante sans exprimer de préférence, l'index de prise en charge sera mis en cluster s'il n'y a pas d'index en cluster préexistant sur la table. L'index de prise en charge sera créé comme non cluster s'il existe déjà un index cluster

Vous pouvez spécifiquement demander une clé primaire en cluster ou non cluster à l'aide de: PRIMARY KEY CLUSTEREDou PRIMARY KEY NONCLUSTERED.

En toute honnêteté, la documentation est beaucoup plus claire sur le sujet à:

table_constraint (Transact-SQL)

Paul White 9
la source
5

La syntaxe SQL Server pour créer un index cluster qui est également une clé primaire est la suivante:

CREATE TABLE dbo.c
(
    c1 INT NOT NULL, 
    c2 INT NOT NULL,
    CONSTRAINT PK_c
    PRIMARY KEY CLUSTERED (c1, c2)
);

En ce qui concerne votre commentaire: "faire en sorte qu'un PK utilise un index nommé", le code ci-dessus entraînera l'index de la clé primaire qui sera nommé "PK_c".

La clé primaire et la clé de cluster ne doivent pas nécessairement être les mêmes colonnes. Vous pouvez les définir séparément. Dans l'exemple ci-dessus, remplacez le CLUSTEREDmot - clé par NONCLUSTERED, puis ajoutez simplement un index cluster à l'aide de la CREATE INDEXsyntaxe:

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

Dans SQL Server, l'index cluster est la table, ils sont identiques. Un index cluster définit l'ordre logique des lignes stockées dans la table. Dans mon premier exemple, les lignes sont stockées dans l'ordre des valeurs des colonnes c1et c2. Étant donné que la clé de clustering est également définie comme clé primaire, la combinaison de c1et c2doit être unique à l'échelle de la table.

Dans le deuxième exemple, la clé primaire est composée des colonnes c1et c2, mais la clé de clustering est juste la c2colonne. Étant donné que je n'ai pas spécifié l' UNIQUEattribut dans l' CREATE INDEXinstruction, la clé de clustering ( c2) n'est pas requise pour être unique sur la table. Un "uniquifier" sera automatiquement créé par SQL Server et ajouté aux valeurs de la c2colonne pour créer la clé de clustering. Cette clé de cluster, car elle est désormais unique, sera ensuite utilisée comme identifiant de ligne dans d'autres index créés sur la table.

Afin de prouver les contrôles clés de clustering la mise en page des lignes de stockage, vous pouvez utiliser la fonction non documentée, fn_PhysLocCracker(%%PHYSLOC%%). Le code suivant montre que les lignes sont disposées sur le disque dans l'ordre de la c2colonne, que j'ai définie comme clé de 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;

Les résultats de mon tempdb sont:

entrez la description de l'image ici

Dans l'image ci-dessus, les trois premières colonnes sont sorties de la fn_PhysLocCrackerfonction, montrant l'ordre physique des lignes sur le disque. Vous pouvez voir que la slot_idvaleur augmente l'étape de verrouillage avec la c2valeur, qui est la clé de clustering. L'index de clé primaire stocke les lignes dans un ordre différent, ce qui peut être vu en forçant SQL Server à renvoyer les résultats de l'analyse de la clé primaire:

SELECT pkt.c1
    , pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);

Remarque, je n'ai pas utilisé de ORDER BYclause dans l'instruction ci-dessus car j'essaie d'afficher l'ordre des éléments dans l'index de clé primaire.

Le résultat de la requête ci-dessus est:

entrez la description de l'image ici

En regardant la fn_PhysLocCrackerfonction, nous pouvons voir l'ordre physique de l'index de clé primaire.

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;

Puisque nous lisons exclusivement à partir de l'index lui-même, c'est-à-dire qu'aucune colonne en dehors de l'index n'est référencée dans la requête, les %%PHYSLOC%%valeurs représentent les pages de l'index lui-même.

Les resultats:

entrez la description de l'image ici

Max Vernon
la source