0% ont trouvé ce document utile (0 vote)
53 vues6 pages

Optimisation SQL et Triggers en BDD

Ce document décrit des exercices SQL sur la manipulation de tables, l'ajout de colonnes et la création de triggers pour vérifier des dépendances fonctionnelles. Il contient également des explications sur différentes décompositions possibles d'une relation.

Transféré par

Francine Fayo
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
53 vues6 pages

Optimisation SQL et Triggers en BDD

Ce document décrit des exercices SQL sur la manipulation de tables, l'ajout de colonnes et la création de triggers pour vérifier des dépendances fonctionnelles. Il contient également des explications sur différentes décompositions possibles d'une relation.

Transféré par

Francine Fayo
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

INFOB212 - B ASES DE DONNEES 2

Travaux pratiques
SQL

Trouver, dans la table suivante, les utilisateurs ayant le même nom et la même adresse email.

Users
ID Name Email
1 John [email protected]
2 Sam [email protected]
3 Tom [email protected]
4 Tom [email protected]
5 Tom [email protected]
Output attendu :

ID Name Email Count


3 Tom [email protected] 2

SELECT name, email, COUNT(*) FROM users


GROUP BY name, email
HAVING COUNT(*) > 1

Ajouter, dans la table précédente, une nouvelle colonne de type INT avec une valeur par défaut.

Exemple de résultat :

Users
ID Name Email Age
1 John [email protected] 20
2 Sam [email protected] 20
3 Tom [email protected] 20
4 Tom [email protected] 20
5 Tom [email protected] 20

ALTER TABLE Users ADD Age Int NOT NULL


CONSTRAINT D_Users_Age DEFAULT(20)
Créer les triggers nécessaires à la vérification des dépendances fonctionnelles de la relation
suivante. Et ce pour les trois décomposition possible (Peste, Choléra, Peste et Choléra) :
R(REGION, VILLE, RUE, CPOST, BUREAU)
VILLE, RUE → CPOST
VILLE → REGION
CPOST → VILLE, BUREAU

Les solutions sont également disponibles (ici)

Peste

Il faut éviter les insert et update sur la table R afin de garantir la DF CPOST->VILLE

Selon cette DF on ne peut pas insert la ligne : "Rue Royale, Bruxelles, 5000". Il est également interdit
de modifier le CPOST de la Rue des Brasseurs à 5000.

Rue Ville Cpost

Rue Grandgagnage Namur 5000

Rue des Brasseurs Bruxelles 1000

create or replace function check_insert_rue() returns trigger as


$$ begin
if (exists(select cpost from post_peste.rue where cpost = new.cpost and
ville != new.ville)) then
raise exception 'cpost % is already linked to %', new.cpost, (select
ville from post_peste.rue where cpost = new.cpost limit 1);
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_insert_rue before insert or update post_peste.rue


for each row
execute procedure check_insert_rue()

Choléra

Appendix 1

Peste et choléra

Si l’on ajoute la ligne Rue de la Montagne, Charleroi, 6000 dans la table rue la règle d’inclusion n’est
plus respectée.
alter table post_pstnchol.ville add unique (cpost, ville);
alter table post_pstnchol.rue add foreign key (cpost, ville)
references post_pstnchol.ville(cpost, ville);
Donnez la liste exhaustive des événements de la base de données pouvant potentiellement mener
à la violation de la contrainte ci-dessous.

Contrainte : Une commande d’un client de Namur ne peut pas comporter plus de 2 détails.

Schéma de la base de données :

• Insertion d’un 3ème détail pour une commande passée par un client de Namur
• Mise à jour de la colonne Orders.cli_id afin de référencer un client de Namur pour une
commande avec plus de 2 détails.
• Mise à jour de la colonne Details.ord_id afin de référencer une commande ayant déjà 2 détails
et appartenant à un client de Namur.
• Mise à jour de la localité d’un client de venant pas de Namur et ayant déjà passé une commande
avec plus de 2 détails.

Créer deux triggers, de type after et before pour deux de ces événements.

Insertion d’un 3ème détail d’une commande passée par un client vivant à Namur, la contrainte sera
violée
create or replace function customers.check_insert() returns trigger as
$$ begin
if ((select count(*) from customers.customers CUS, customers.orders ORD,
customers.details DET
where DET.order_id = ORD.id
and ORD.user_id = CUS.id
and CUS.city = 'Namur'
and ORD.id = new.order_id) >= 2)
then
raise exception 'the maximal number of details per order (2) is reached';
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_insert before insert


on customers.details
for each row
execute procedure customers.check_insert();
Mise à jour de la colonne Orders.cli_id afin de référencer un client de Namur pour une commande
avec plus de 2 détails.
create or replace trigger check_insert before insert
on customers.details
for each row
execute procedure customers.check_insert();

-- Mise à jour de la colonne Orders.user_id afin de référencer un client de Namur pour une
commande avec plus de 2 détails.
create or replace function customers.check_update_order() returns trigger as
$$ begin
if ((select city from customers.customers where id = new.user_id) = 'Namur' and
(select count(*) from customers.details where order_id = new.id) > 2)
then
raise exception 'the maximal number of details per order (2) is reached';
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_update_order before update of user_id


on customers.orders
for each row
execute procedure customers.check_update_order();

Mise à jour de la colonne Details.ord_id afin de référencer une commande ayant déjà 2 détails et
appartenant à un client de Namur.
create or replace function customers.check_update_detail() returns trigger as
$$ begin
if ((select count(*)
from customers.customers CUS, customers.orders ORD, customers.details DET
where DET.order_id = ORD.id
and ORD.user_id = CUS.id
and CUS.city = 'Namur'
and ORD.id = new.order_id
) >= 2)
then
raise exception 'the maximal number of details per order (2) is reached';
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_update_detail before update of order_id


on customers.details
for each row
execute procedure customers.check_update_detail();
Mise à jour de la localité d’un client de venant pas de Namur et ayant déjà passé une commande
avec plus de 2 détails.
create or replace function customers.check_update_customer() returns trigger as
$$ begin
if (old.city <> 'Namur'
and new.city = 'Namur'
and exists(
select count(*)
from customers.orders ORD
where ORD.user_id = new.id
and (
select count(*)
from customers.details DET
where DET.order_id = ORD.id
) > 2
))
then
raise exception 'the maximal number of details per order (2) is reached';
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_update_customer before update of city


on customers.customers
for each row
execute procedure customers.check_update_customer();
Appendix 1
create or replace view post_cholera.ville_rue as
select r.rue as rue, v.ville as ville, r.cpost as r_cpost, v.cpost as v_cpost
from post_cholera.ville v
full join post_cholera.rue r on v.cpost=r.cpost
order by r.rue, r.cpost;
select * from post_cholera.ville_rue;

create or replace function post_cholera.check_rue() returns trigger as


$$ begin
if (exists(select *
from post_cholera.ville_rue
where ville=(select ville from post_cholera.ville where new.cpost=cpost limit 1)
and v_cpost != new.cpost
and rue = new.rue
and r_cpost != new.cpost
)) then
raise exception 'the ''ville'' % and the ''rue'' % are already linked to the % ''cpost''',
(select ville from post_cholera.ville where new.cpost = cpost limit 1),
new.rue,
(select v_cpost from post_cholera.ville_rue where ville=(select ville from
post_cholera.ville where new.cpost=cpost limit 1) and rue=new.rue limit 1);
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_rue before insert or update


on post_cholera.rue
for each row
execute procedure post_cholera.check_rue();

create or replace function post_cholera.check_ville() returns trigger as


$$ begin
if (exists(
select *
from post_cholera.ville_rue
where rue = (select rue from post_cholera.rue where new.cpost = rue.cpost limit 1)
and r_cpost != new.cpost
and ville = new.ville
and v_cpost != new.cpost
)) then
raise exception 'the ''ville'' % and the ''rue'' % are already linked to the % ''cpost''',
new.ville,
(select rue from post_cholera.rue where new.cpost = cpost limit 1),
(select r_cpost from post_cholera.ville_rue where rue = (select rue from
post_cholera.rue where new.cpost = cpost limit 1) and ville = new.ville limit 1);
end if;
return new;
end $$
language plpgsql;

create or replace trigger check_ville before insert or update


on post_cholera.ville
for each row
execute procedure post_cholera.check_ville();

Vous aimerez peut-être aussi