APSQL

Contrainte UNIQUE et index

Pour garantir l'unicité des valeurs en dehors de la clé primaire, il est nécessaire de définir une contrainte d'unicité composé de la ou des colonnes sur lesquelles portent l'unicité.

Par exemple dans le cadre d'une table des Clients la clé primaire est composé du numéro de client mais il est également possible de garantir l'unicité des adresses mail en définissant une contrainte d'unicité sur la colonne des adresses mails, comme le propose le script suivant:

create table clients(
  id int identity(1,1),
  nom nvarchar(80) not null,
  prenom nvarchar(80) not null,
  email nvarchar(80) not null,
  constraint pk_clients primary key(id),
  constraint uk_clients unique (email));

La table est alors définie et l'exécution de la procédure stockée sp_help permet de comprendre que la contrainte d'unicité est mise en place par l'intermédiaire d'un index:

résultat exécution sp_help

La différence entre contrainte d'unicité et index est simplement une question de normalisation. La fait de définir uniquement un index unique sans passer par la contraint d'unicité ne permet pas de constater ou une hausse ou ou une baisse des performances.

Toutefois le fait d'utiliser la notion de contrainte d'unicité reste plus en norme et permet de gagner en lisibilité au niveau de la structure de la base. En effet les index sont nécessaire pour gagner en performance, ce n'est pas le rôle des index que de définir les règles d'intégrité.

Si par la suite la contrainte d'unicité est modifiée et que l'on souhaite ajouter par exemple le nom, étant donné qu'il n'est pas possible de modifier une contrainte d'intégrité, le premier reflexe consiste à modifier directement l'index c'est-à-dire en le supprimant puis en le créant de nouveau à l'aide du script suivant:

drop index Clients.uk_clients;
go
create unique index uk_clients on Clients (nom,email);

Une erreur d'exécution se produit car l'index est lié à la définition de la contrainte d'intégrité il n'est donc pas possible de supprimer l'index sans supprimer la contrainte. Le bon script est alors:

alter table clients drop constraint uk_clients;
go
alter table clients add constraint uk_clients unique (nom, email);

Il faut cependant noter qu'il est maintenant possible de reconstruire l'index sans toucher à la définition de la contrainte en utilisant l'option DROP EXISTING de l'instrauction CREATE INDEX comme par exemple:

create unique index uk_clients on clients(nom, email) with drop_existing