Vous êtes sur la page 1sur 4

Corrigé TD intégrité

Question 1 /:
La valeur de la clé de la relation doit permettre d'identifier un seul tuple dans la relation "BAIGNADE".
- Si on ne doit répertorier qu'une seule baignade au maximum par nageur et par plage, la clé est constituée des
deux attributs "NN" et "NP". L'attribut "date" est une information « complémentaire » sur la baignade.
- Si on veut pouvoir répertorier plusieurs baignades pour un nageur sur une plage, il faut en sus de NN et NP un
autre attribut pour identifier ces différentes baignades. L'attribut date peut servir à cette fin. En revanche on ne
pourra enregistrer qu'une baignade pour un nageur donné, sur une plage donnée à une date donnée. La clé
serait donc constituée de trois attributs: NN, NP, date. Si on voulait plusieurs baignades par jour pour un
nageur et une plage donnés, il faudrait que l'attribut "date" soit de type TIMESTAMP (date et heure). Il devrait
avoir un nom qui reflète cette définition, par exemple "date_heure".
Question 2 :
a) La qualité d'un nageur est excellente, bonne ou médiocre (contrainte de domaine)
s'exprime en SQL par une contrainte d'attribut avec CHECK:
qualite VARCHAR(10) CHECK (qualite IN ( 'excellente', 'bonne', 'médiocre'),
b) Toute baignade a été effectuée par un nageur connu dans la base et sur une plage connue (contraintes
référentielles)
Dans les deux cas, la clé étrangère étant constituée d'un seul attribut, la contrainte référentielle peut être déclarée
sous forme de contrainte d'attribut (déclaration avec l'attribut). Elle peut aussi être déclarée sous forme de contrainte
de relation (après la déclaration de l'attribut et séparément de celle-ci). La syntaxe est différente puisque dans le
deuxième cas il faut rappeler quel est l'attribut (ou ensemble d'attributs) clé étrangère:
contraintes d'attribut:
nn INTEGER CONSTRAINT cle-etr-nageur REFERENCES nageur(nn),

nom de la contrainte seule partie obligatoire à indiquer


pour avoir une contrainte mieux
documentée et plus maintenable

np INTEGER CONSTRAINT cle-etr-plage REFERENCES plage(np),


contraintes de relation:
nn INTEGER,
np INTEGER, [….,]
CONSTRAINT cle-etr-nageur FOREIGN KEY (nn) REFERENCES nageur (nn),
CONSTRAINT cle-etr-plage FOREIGN KEY (np) REFERENCES plage(np),
c) NN,NP,date constituent la clé de "BAIGNADE"
La clé étant constituée de trois attributs, elle doit être obligatoirement déclarée par une contrainte de relation après
la déclaration des trois attributs la constituant:
nn INTEGER,
np INTEGER,
baignade_date DATE, [….,] /* date est un mot réservé */
CONSTRAINT cle-baignade PRIMARY KEY(nn,np, baignade_date),

N.B. De façon implicite cela entraine que les trois attributs ne doivent jamais être vides (contrainte NOT NULL).
d) l'attribut "nbbaignades" compte le nombre de baignades effectuées par chaque nageur
"nbbaignades" est un attribut calculé. On peut définir une contrainte d'attribut pour contrôler sa valeur.

nbbaignades INTEGER CHECK (nbbaignade = (SELECT COUNT(*) FROM baignade b


WHERE b.nn = nageur.nn)),
Cette forme de contrainte avec un SELECT imbriqué est rarement admise par les SGBD. L'autre solution, plus répandue,
pour s'assurer que la valeur de cet attribut est toujours correctement mise à jour est de définir un trigger.

Question 3 :
a) La contrainte de domaine, portant sur un seul tuple peut être vérifiée à chaque mise à jour et uniquement pour
les mises à jour qui introduisent de nouvelles valeurs dans la base: INSERT, UPDATE de l'attribut "qualité".
b) Une contrainte référentielle porte sur deux tuples dans deux relations différentes (donc mises à jour par deux
requêtes différentes nécessairement). Elles peuvent être vérifiées après les mises à jour ou en fin de transaction.
Si elles sont vérifiées après la mise à jour, cela impose de respecter un ordre dans les mises à jour. Par exemple
si on veut introduire dans la base une nouvelle baignade pour un nouveau nageur il faut obligatoirement
insérer d'abord le nouveau nageur puis la nouvelle baignade. Si on ne veut pas imposer cet ordre, il faut vérifier
la contrainte en fin de transaction. Dans ce cas on pourra avoir l'insertion de la nouvelle baignade, puis celle du
nouveau nageur et la vérification de la contrainte après ces deux insertions sera correcte.
Une contrainte référentielle doit être contrôlée quand on effectue des mises à jour dans la relation référençante (INSERT)
et dans la relation référencée (DELETE). Par exemple la contrainte référentielle définissant la clé étrangère "nn" dans
"BAIGNADE" doit être vérifiée quand on insère un nouveau tuple dans "BAIGNADE" et quand on supprime un tuple
dans "NAGEUR".
c) La contrainte de clé porte sur l'ensemble des tuples d'une seule relation. Elle peut donc être vérifiée après
chaque mise à jour. Si on fait beaucoup d'insertions différentes (avec plusieurs requêtes INSERT) dans la même
relation, la vérification en fin de transaction, globalement pour l'ensemble des INSERT, peut être plus
économique, mais cela dépend du SGBD. En général il y a un index sur la clé pour permettre de vérifier la
contrainte de clé à chaque insert de tuple sans coût trop important. En général il est interdit de modifier (update
) la valeur d’une clé.
d) La contrainte sur l'attribut "nbbaignades" porte sur les tuples appartenant à deux relations différentes, donc mis
à jour par deux requêtes différentes nécessairement. Si on insère ou supprime des tuples dans BAIGNADE
(requête INSERT ou DELETE), il faut une autre requête UPDATE pour modifier en conséquence "nbbaignades"
dans NAGEUR. La contrainte doit donc obligatoirement être vérifiée en fin de transaction, après la mise à jour
des deux tables.

N.B. Dans PostgreSQL on ne peut spécifier une vérification en fin de transaction que pour les contraintes référentielles.
Les contraintes sur les clés sont vérifiées efficacement à chaque insertion de tuple et il n'y aurait aucun intérêt à faire
cette vérification globalement après plusieurs insertions. Les contraintes du type d) ne sont pas possibles et l'intégrité est
maintenue dans ce cas par des triggers.

Question 4 :
Il faut obligatoirement ajouter aux requêtes SQL la vérification de leur exécution. Le mode opératoire dépend du langage
de programmation dans lequel sont insérées les requêtes SQL, mais il existe toujours une possibilité de récupérer la
réponse du SGBD à l'exécution d'une requête SQL.
Il faut également savoir quand sont vérifiées les contraintes référentielles en consultant le schéma de la relation.
Dans l'exemple, la suppression d'un nageur peut entraîner une erreur si celui-ci avait des baignades:
a) si la CI référentielle est vérifiée après la mise à jour
Après exécution du DELETE, vérifier la réponse du SGBD. Si celle-ci indique une violation de la C.I.
référentielle "cle-etr-nageur", il faut effectuer un traitement qui maintienne l'intégrité de la base: trois solutions
sont possibles, le choix dépend des règles de gestion de l'application qui ont été en principe spécifiées lors de la
phase préalable d’analyse conception de l’application.
- on peut annuler le DELETE en faisant un ROLLBACK après avoir indiqué pourquoi le DELETE est impossible,
- on peut supprimer les baignades de ce nageur, puis le nageur
- on peut ne pas mettre de valeur (NULL, vide) pour l'attribut "nn" des baignades du nageur supprimé, ce qui
pourrait vouloir dire "pas de valeur pour nn: nageur inconnu".
Le choix de la solution dépend de la règle de gestion spécifiée.
b) si la CI référentielle est vérifiée au commit
Après le DELETE, il faut vérifier que celui-ci a marché. Si le DELETE n'est pas effectué, ou n'a supprimé aucun
tuple, le COMMIT ne peut pas provoquer d'erreur.
Si le DELETE a supprimé au moins un tuple, il faut vérifier l’exécution du COMMIT. Si la réponse du SGBD
indique une violation de la C.I. référentielle "cle-etr-nageur", on a les mêmes solutions que ci-dessus pour
maintenir l'intégrité de la base.
Il faut bien voir que si on ne teste pas s'il y a violation de la C.I. référentielle, on peux croire que le commit a été effectué
et que la transaction est close, ce qui n'est pas le cas: elle continue. S'il y a d'autres mises à jours faites ensuite (en croyant
qu'elles sont dans une autre transaction), elles seront toutes annulées quand le programme s'arrêtera en faisant
automatiquement un ROLLBACK.

Question 5 :
La règle de gestion ne peut pas être traduite par une contrainte d'intégrité, et donc pas vérifiée automatiquement par le
SGBD. Il faut le faire systématiquement dans le programme d'application :

DEBUT TRANSACTION
DELETE FROM baignade WHERE "condition de sélection";
SI au moins un tuple supprimé
/* supprimer les nageurs auxquels il ne reste plus de baignades*/
DELETE FROM nageur WHERE nn NOT IN (SELECT nn FROM baignade);
COMMIT
SI exécution non OK
édition erreur;
ROLLBACK /* aucun des deux DELETE ne sera effectif */;
FSI
FSI
FIN

Vous aimerez peut-être aussi