Paris-Saclay University

Bases de données 2

Les contraintes

D'après le cours d'Emmanuel Waller

Contraintes et Séquences

Introduction

  • Les contraintes d'intégrité et les séquences sont des éléments essentiels pour garantir la cohérence et la stabilité des données dans les systèmes de gestion de bases de données (SGBD).
  • Objectif du cours : Comprendre le rôle et l'importance des contraintes dans la gestion des erreurs et des incohérences, et des séquences dans la gestion des identifiants uniques.

Contexte et importance des contraintes d'intégrité

  • Les contraintes d'intégrité sont des règles imposées sur les données pour garantir leur validité.
    • Elles assurent que les données sont conformes aux règles métiers (par exemple, un âge ne peut pas être négatif, un email doit être unique).
    • Elles empêchent l'insertion, la modification ou la suppression de données incorrectes.
  • Les contraintes sont définies dans le SGBD pour s'assurer que toutes les opérations sur les données respectent ces règles.
    • Lorsqu'une contrainte est violée, l'opération est annulée et un message d'erreur est retourné.
    • Cela garantit que les erreurs humaines ou les bugs dans les programmes ne corrompent pas la base de données.

Types de contraintes dans SQL

  • NOT NULL : Empêche l'enregistrement de valeurs nulles dans une colonne. Exemple : un champ "nom" ne peut pas être vide dans une table "Personne".
  • UNIQUE : Assure que toutes les valeurs dans une colonne sont uniques. Exemple : aucune adresse email ne doit être dupliquée dans une table "Utilisateurs".
  • PRIMARY KEY : Définit une ou plusieurs colonnes comme clé primaire, garantissant l'unicité et servant d'identifiant pour chaque ligne. Exemple : une colonne "id" dans une table "Personne".
  • FOREIGN KEY : Garantit la validité des relations entre plusieurs tables en établissant un lien entre une clé primaire et une clé étrangère. Exemple : la colonne "id_personne" dans une table "Réservations" référant à la clé primaire "id" dans une table "Personne".
  • CHECK : Vérifie qu'une condition logique est respectée. Exemple : un champ "âge" doit toujours être supérieur ou égal à zéro.

Contrainte multi-colonnes

  • Les contraintes peuvent impliquer plusieurs colonnes, comme les clés uniques composées.
  • Exemple : Supposons que nous souhaitions garantir qu'une combinaison de deux colonnes soit unique.
create table Employe (
  id integer primary key,
  prenom varchar(50),
  nom varchar(50),
  email varchar(100),
  unique (prenom, nom)
);

Explication : Cet exemple impose qu'une combinaison de "prenom" et "nom" soit unique dans la table "Employe". Cela peut être utilisé pour éviter des doublons où des personnes auraient le même prénom et nom.

Mécanismes internes des contraintes

  • Les contraintes telles que les clés primaires et les clés uniques reposent souvent sur des index sous-jacents dans le SGBD.
  • Ces index permettent de garantir l'unicité de manière rapide et efficace, mais peuvent aussi impacter les performances sur des tables de grande taille.
  • Les contraintes comme CHECK et FOREIGN KEY peuvent être implémentées à l'aide de triggers automatiques au niveau de la base de données.

Remarque : Bien que ces contraintes améliorent la sécurité et la fiabilité des données, il est important de prendre en compte leur impact sur les performances, surtout pour les opérations massives d'insertion ou de modification.

Gestion des violations de contraintes

  • Lorsqu'une contrainte est violée, une exception est levée et l'opération échoue.
  • Les SGBD permettent de gérer ces erreurs avec des transactions qui peuvent être annulées en cas de violation.
  • Exemple : Utilisation d'une transaction pour vérifier des conditions avant insertion.
begin transaction;
  insert into Personne (id, nom, age, email)
  values (seq_personne.nextval, 'Alice', -25, 'alice@example.com'); -- échoue
rollback; -- annule l'opération

Explication : Dans cet exemple, la tentative d'insertion échoue en raison de la contrainte CHECK sur l'âge. L'utilisation d'une transaction permet d'annuler automatiquement toute modification de la base de données.

Contraintes côté application vs côté SGBD

  • Les contraintes peuvent également être implémentées côté application, par exemple en Java, pour garantir la cohérence des données avant qu'elles ne soient envoyées au SGBD.
  • Cependant, les contraintes dans le SGBD offrent une garantie supplémentaire, car elles sont exécutées au niveau de la base et ne dépendent pas de la qualité du code de l'application.

Exemple : Validation de la syntaxe d'une adresse email dans une application Java avant de l'insérer dans une base de données. Cette validation est utile, mais elle ne remplace pas une contrainte UNIQUE dans la base.

Exemple : Contrainte NOT NULL

insert into Personne (id, nom, age, email)
  values (1, null, 25, 'example@example.com'); -- Échoue à cause de NOT NULL

Explication : Cet exemple montre comment une tentative d'insertion échoue parce que la colonne "nom" ne peut pas être nulle en raison de la contrainte NOT NULL.

Exemple de contraintes sur une table Personne

create table Personne (
  id integer primary key,
  nom varchar(50) not null,
  age integer check (age >= 0),
  email varchar(100) unique
);

Explication : Cette table "Personne" impose des contraintes pour garantir que chaque personne a un identifiant unique, un nom obligatoire, un âge positif, et une adresse email unique.

Exemple : Clé étrangère avec suppression en cascade

create table Commande (
  id_commande integer primary key,
  id_client integer,
  foreign key (id_client) references Client(id)
  on delete cascade
);

delete from Client where id = 1; -- supprime également les commandes liées

Explication : Ici, la suppression d'un client dans la table "Client" entraîne la suppression automatique des commandes associées dans la table "Commande" grâce à l'option on delete cascade.

Exemple : Cascade sur mise à jour

create table Commande (
  id_commande integer primary key,
  id_client integer,
  foreign key (id_client) references Client(id)
  on update cascade on delete cascade
);

update Client 
  set id = 2 where id = 1; -- met également à jour l'id dans la table "Commande"

Explication : Ici, toute mise à jour de la colonne "id" dans la table "Client" sera répercutée automatiquement dans la table "Commande" grâce à l'option on update cascade.

Exemple : Contrainte CHECK complexe

create table Employe (
  id integer primary key,
  salaire decimal check (salaire > 0 and salaire < 10000)
);

Explication : Cette contrainte garantit que le salaire des employés est compris entre 0 et 10 000, empêchant l'insertion de valeurs négatives ou excessivement élevées.

Principe des séquences

  • Les séquences sont utilisées pour générer automatiquement des identifiants uniques dans une base de données.
    • Elles garantissent que chaque nouvel enregistrement obtient une valeur unique, ce qui est essentiel pour les clés primaires.
    • Dans les systèmes multi-utilisateurs, elles permettent d'éviter les conflits d'identifiants lors de l'insertion simultanée de données.
  • Les séquences sont créées avec un ordre SQL spécifique et peuvent être utilisées dans des commandes d'insertion pour générer automatiquement de nouveaux identifiants.

Paramètres avancés des séquences

  • Les séquences peuvent être paramétrées avec différents attributs pour répondre aux besoins spécifiques.
  • Par exemple, les valeurs générées peuvent avoir un intervalle défini, un cycle ou une limite maximale.
create sequence seq_personne
start with 100
increment by 10
maxvalue 1000
cycle;

Explication : Cette séquence commence à 100, incrémente de 10 à chaque appel, et reprend à 100 lorsque la valeur maximale de 1000 est atteinte (grâce à l'option cycle).

Exemples d'ordres SQL pour les séquences

create sequence seq_personne;
select seq_personne.nextval;  -- génère la prochaine valeur de la séquence
select seq_personne.currval;  -- renvoie la dernière valeur générée

Explication : L'ordre nextval génère la prochaine valeur dans la séquence, tandis que currval renvoie la dernière valeur générée par nextval. Ces commandes sont essentielles pour l'insertion d'enregistrements avec des identifiants uniques dans des systèmes multi-utilisateurs.

Utilisation des séquences dans les insertions

insert into Personne (id, nom, age, email) 
  values (seq_personne.nextval, 'Alice', 30, 'alice@example.com');

Explication : Lors de l'insertion d'une nouvelle personne dans la table "Personne", une nouvelle valeur de séquence est générée pour l'identifiant unique "id". Cette méthode assure que chaque personne a un identifiant distinct.

Gestion des permissions et confidentialité

  • Dans un SGBD, il est essentiel de gérer les permissions pour protéger les données sensibles.
    • Les permissions permettent de restreindre l'accès aux séquences, tables, et autres objets de la base de données à des utilisateurs autorisés uniquement.
    • Cette gestion fine des droits d'accès renforce la sécurité des données, empêchant les modifications ou accès non autorisés.
  • Exemple : Donner le droit à un autre utilisateur d'utiliser une séquence pour insérer des données dans la table "Personne".

Contraintes temporelles et transactions

  • Les contraintes temporelles sont des règles qui dépendent du moment où une opération est effectuée.
  • Elles sont souvent utilisées dans des systèmes nécessitant une gestion précise des périodes de validité des données.
  • Les transactions assurent que les contraintes sont respectées de bout en bout en garantissant l'atomicité des opérations (tout ou rien).
create table Contrat (
  id integer primary key,
  date_debut date,
  date_fin date,
  check (date_fin > date_debut)
);

Explication : Cet exemple impose que la date de fin d'un contrat soit toujours postérieure à la date de début, une contrainte essentielle pour garantir la cohérence des informations temporelles.

Compétences à acquérir

  • Savoir analyser le comportement des ordres SQL en présence de contraintes et de séquences.
  • Être capable d'écrire des ordres SQL adéquats pour modéliser les contraintes du cahier des charges d'une application.
  • Connaître les limites du langage SQL et savoir quand utiliser des approches complémentaires, comme Java, pour pallier ces limites.

Démonstration

Présentation pratique des contraintes sur des tables, de l'utilisation des séquences et de la gestion des permissions pour illustrer concrètement les concepts abordés.