Intégrité des données
Contraintes d’intégrité
Une contrainte d’intégrité est une condition à vérifier sur un enregistrement afin qu'elle contienne une valeur qui a un sens. On utilise cela pour LIMITER (contraindre) les valeurs qu'un champs peut prendre. Cela permet donc de maintenir l'intégrité de la table.
Clé primaire, clé étrangère et valeur par défaut
Les contraintes de clé primaire, de clé étrangère et de valeur par défaut ont déjà été couvertes. On a pu voir que certaines sont spécifiées directement dans la déclaration d’une colonne (DEFAULT, PRIMARY KEY), tandis que d’autres sont spécifiés sur leur ligne à part (FOREIGN KEY, PRIMARY KEY). Ajouter un enregistrement ne respectant pas la contrainte déclenche une erreur.
Rappel des contraintes déjà vues
Clé primaire : PRIMARY KEY Force la valeur à être unique et est utilisé pour trouver rapidement un enregistrement. Permet l’utilisation par une clé étrangère. Une seule clé primaire permise par table.
Clé étrangère : FOREIGN KEY Référence un enregistrement d’une autre table. Garanti que l’enregistrement existe.
Valeur par défaut : DEFAULT Spécifie la valeur utilisée lorsqu’un enregistrement est créé et qu’aucune valeur n’est spécifiée. Si aucune valeur par défaut n’est indiquée, NULL est utilisée par le système.
Suppression en CASCADE
Jusqu’à présent le code suivant provoque une erreur.
DELETE FROM enseignants
WHERE code_employe = 8765;
Parce que la table programmes contient une clé étrangère vers enseignants et qu'elle ne pointerait sur rien si l'enseignant est supprimé.
erDiagram
enseignants ||--o{ programmes : " "
enseignants {
NUMERIC(8) code_employe
VARCHAR(255) nom
VARCHAR(255) prenom
NUMERIC(9) num_assurance_sociale
TINYINT anciennete
}
programmes {
INTEGER code PK
VARCHAR(255) nom
NUMERIC(8) prof_responsable FK
}
La stratégie ON DELETE CASCADE permet de supprimer tous les enregistrements qui sont référencés, donc qui posent problème.
--- Exercice 4.1.1 ---
À partir de la BD école (partez de la BD complète ecole2), identifiez les enregistrements de quelles tables seraient supprimés si toutes les clés étrangères utilisent la stratégie ON DELETE CASCADE, et que l'on supprime une session.
Mise-à-jour en CASCADE
La mise à jour en cascade permet de modifier la valeur d’une clé primaire et de mettre à jour simultanément toutes les clés étrangères (conserver l’intégrité).
Cela est utile seulement si la clé primaire n’est pas un identifiant autoincrémenté.
FOREIGN KEY (colonne) REFERENCES Nom_table(colonne) ON UPDATE CASCADE
Clé unique
Une clé unique est une façon de préciser qu’une valeur ou un groupe de valeur sont uniques dans la table. Avec un champs qui est unique, on ne peut pas entrer deux fois la même valeur.
La clé primaire est un type particulier de clé unique.
Attention
Contrairement à une clé primaire, une clé unique peut être nulle et même si c'est unique, plusieurs enregistrements peuvent être nuls.
Pour indiquer qu’une colonne est unique, on place le mot-clé UNIQUE après le nom de la colonne.
CREATE TABLE programmes (
code CHAR(6) PRIMARY KEY,
nom VARCHAR(255) UNIQUE,
prof_responsable NUMERIC(8),
...
);
erDiagram
programmes {
INTEGER code PK
VARCHAR(255) nom
NUMERIC(8) prof_responsable FK
}
Pour indiquer une clé unique portant sur plusieurs colonnes, on utilise la syntaxe suivante:
CONSTRAINT nom UNIQUE (colonne1, colonne2...)
CREATE TABLE sessions (
id_session INTEGER
PRIMARY KEY AUTO_INCREMENT,
semestre ENUM('Automne', 'Hiver'),
annee YEAR,
debut_session DATE,
fin_session DATE,
CONSTRAINT semestre_annee_unique
UNIQUE (semestre, annee));
erDiagram
sessions {
INTEGER session_id PK
ENUM semestre "not null"
YEAR annee "not null"
DATE debut_session "not null"
DATE fin_session "not null"
}
Nullité
Par défaut, à l’exception des clés primaires, toutes les colonnes peuvent prendre la valeur NULL.
On peut empêcher la présence de valeur nulle dans une colonne en ajoutant NOT NULL après le type.
Pour éviter des étudiants dont le nom est NULL, on ajoute | not null après le type sur le diagramme.
CREATE TABLE etudiants (
code NUMERIC(7) PRIMARY KEY,
nom VARCHAR(255) NOT NULL
...
);
erDiagram
etudiants {
NUMERIC(8) code_etudiant PK
VARCHAR(255) nom "not null"
YEAR annee_admission
DATETIME date_naissance
VARCHAR(10) programme
}
--- Exercice 4.1.2 ---
Modifiez le script de création de la base de données ecole pour inclure les contraintes suivantes :
A) Deux programmes ne peuvent pas porter le même nom
B) Chaque programme doit toujours avoir un professeur responsable
C) Un même numéro de groupe ne peut pas être affecté au même cours à la même session (il y a un seul groupe 1 de BD1 à la session H22).
D) Si l'on supprime une Évaluation, on veut supprimer toutes les evaluations_etudiants associées.
Check
La contrainte CHECK permet de vérifier que les valeurs suivent une certaine condition. On insère cette contrainte directement dans la définition de la table.
CREATE TABLE Nom_table (
colonne TYPE,
...
CONSTRAINT nom_contrainte CHECK (condition));
Exemple : les pondérations des évaluations doivent être entre 0 et 100.
CREATE TABLE evaluations (
evaluation_id INTEGER
PRIMARY KEY AUTO_INCREMENT
...
ponderation NUMERIC(5,2),
...
CONSTRAINT note_0_a_100
CHECK (ponderation BETWEEN 0 AND 100));
erDiagram
evaluations {
INTEGER evaluation_id PK
INTEGER groupe_id FK
VARCHAR(64) titre
NUMERIC(4_1) ponderation
DATETIME date_passage
}
--- Exercice 4.1.3 ---
Insérez une vérification pour vous assurer que :
A) La note obtenue à une évaluation est positive
B) L'ancienneté d'un enseignant est entre 0 et 50
C) Les sigles des cours sont dans le format suivant (A est lettre majuscule, # est un entier) : ###-#A#-AA
Limitations des CHECK
Certaines colonnes ne peuvent pas faire l’objet d’un CHECK dont:
- Colonne avec l’attribut AUTO_INCREMENT
- Colonne avec référence d’action (CASCADE).
On ne peut pas non plus appeler les éléments suivants dans un CHECK :
- Fonctions non natives (non incluses à SQL)
- Procédures stockées
- Variables
- Requêtes
- Fonctions non déterministe, tel que NOW()
Finalement, un CHECK peut contenir les éléments suivants :
- Opérateurs arithmétiques
- Opérateurs de comparaison
- Fonctions déterministe (count, avg, year, …)
- Comparaisons / opérations sur plusieurs colonnes d’une même table.
Tricher et éviter les CHECK
À l’occasion, on peut vouloir insérer une valeur qui ne respecte pas une condition en raison d’un élément spécial.
On peut utiliser alors les requêtes spéciales avec la clause IGNORE :
INSERT IGNORE INTO ...
UPDATE IGNORE ...
LOAD DATA INFILE 'nom' IGNORE INTO TABLE ...
Comme toute vérification, il faut une bonne raison pour l’éviter !
--- Exercice 4.1.4 ---
Implémentez, lorsque possible, les vérifications (CHECK) suivantes. Expliquez pourquoi lorsque vous ne pouvez pas les implémenter.
A) Le nom des documents remis n'excède pas 64 caractères (indice: fonction CHAR_LENGTH)
B) La durée d'une session n'excède pas 17 semaines
C) Pour une évaluation, tous les étudiants reçoivent une note
D) Tous les documents sont remis à la date du jour (si je le dépose le 15 mars, alors la valeur dans date_remise est le 15 mars)
Ajouter ou retirer des contraintes
Dans le cas où on n'a pas défini la contrainte lors de la création de la table, on peut modifier un table pour ajouter (ou supprimer) des contraintes.
ALTER TABLE Nom_table
ADD CONSTRAINT nom TYPE_CONTRAINTE (contrainte)
ALTER TABLE Nom_table
DROP [PRIMARY KEY | FOREIGN KEY | CHECK] nom
Ajouter une clé primaire
ALTER TABLE evaluations
ADD CONSTRAINT evaluation_pk PRIMARY KEY (id_evaluation);
Ajouter un CHECK
ALTER TABLE evaluations_etudiants
ADD CONSTRAINT note_0_a_100 CHECK (note BETWEEN 0 AND 100);
Supprimer une clé primaire
ALTER TABLE evaluations
DROP PRIMARY KEY;
Supprimer un CHECK
ALTER TABLE evaluations_etudiants
DROP CHECK note_0_a_100;