10 KiB
Corrections
1. Les titulaires
person : informations propres aux personnes physiques
- prénom, nom, date de naissance
company : informations propres aux entreprises
- raison sociale, numéro d’immatriculation, date de création
1.6 Contôle de l'âge
Contrainte déclarative
alter table person
add constraint chk_person_minimum_age
check (birthdate <= current_date - interval '15 years');
Contrainte procédurale avec un trigger :
create or replace function check_person_age()
returns trigger as $$
begin
if new.birthdate > current_date - interval '15 years' then
raise exception 'Holder must be at least 15 years old';
end if;
return new;
end;
$$ language plpgsql;
create trigger trg_check_person_age
before insert or update on person
for each row execute procedure check_person_age();
insert into holder (type) values ('BANK')
returning holder;
insert into bank (id, name) values (1, 'Banque de l''Est');
La création d'un titulaire s'effectue en deux étapes :
- Créer un compte individuel pour Françoise Zanetti, née le 12 avril 1995.
- Créer une entreprise nommée Boulangerie de Valorgue, créée le 19 août 2014, numéro d’immatriculation FR19803269968.
- Ajouter un nouveau titulaire : Justin Hébrard né le 11/03/1993.
1.1 Contraintes à respecter
- Chaque
personoucompanydoit correspondre à exactement un seulholder. - La suppression d’un
holderdoit supprimer automatiquement la ligne correspondante danspersonoucompany. - La banque souhaite désormais que toute personne titulaire d’un compte ait au moins 15 ans à la date de création de sa fiche. Il n'y a pas de restriction sur l'âge de la société.
- Le type doit être contraint à
'PERSON'ou'COMPANY'.
Il existe deux méthodes pour gérer le type.
-
vérifier par la commande
CHECKla validité de la valeur. -
utiliser une énumération
enum.
1.2 Vérifications
- Lister tous les titulaires. Pour réutiliser rapidement la requête enregistrer la dans une vue.
- Supprimer un titulaire, vérifier que cela supprime l'individu ou la société correspondante.
1.4 L'intégrité des données
Lorsque l’on tente d'insèrer une nouvelle personne qui n'a pas l'âge requis. La ligne dans holder est d'abord créée, puis l'insertion dans person échoue à cause de la vérification d'âge. Mais la ligne du titulaire est toujours présente sans être rattachée à une personne. On parle alors d'enregistrement orphelin.
Chaque commande SQL est exécutée indépendamment. Si la deuxième commande échoue, la première n’est pas annulée automatiquement.
Réalisez l’insertion d’un titulaire complet (dans holder et person) à l’aide d’une transaction. Testez le cas où la contrainte d’âge échoue et vérifiez que rien n’est inséré dans holder.
begin;
...
commit;
1.5 Procédure stockée
Pour fiabiliser le process et être sûr que l'execution s'effectue toujours dans une transaction, nous allons encapsuler la création d’un titulaire dans une procédure stockée.
Créez une procédure stockée appelée create_person_holder.
Cette procédure prend en paramètre :
- le prénom (
p_firstname text) - le nom (
p_lastname text) - la date de naissance (
p_birthdate date)
Cette procédure doit :
- Vérifier que la personne a au moins 15 ans ;
- Créer automatiquement un enregistrement dans
holderde type'PERSON'; - Récupérer l’identifiant généré et créer la fiche dans
person; - Afficher un message de confirmation.
- Si la personne a moins de 15 ans :
- La procédure doit refuser la création et afficher une erreur claire.
Note
La procédure garantit l’atomicité : soit tout est créé, soit rien.
2. Les comptes
- Le solde des comptes ne peuvent être négatifs.
- Créez un compte joint à 50/50 pour Françoise et Justin.
Écrire une requête pour vérifier la somme des parts
Jusqu’à présent, nous savons créer des titulaires (holder) de façon sûre.
Il est temps de leur ouvrir des comptes bancaires.
Un compte doit toujours :
- être associé à au moins un titulaire,
- et la somme des parts (
share) des titulaires doit être exactement égale à 1 (c’est-à-dire 100 % du compte).
Nous allons donc écrire une procédure stockée create_account qui vérifie ces règles avant d’enregistrer les données.
- Créez une procédure stockée
create_accountqui :
-
prend en paramètre :
p_holders int[](tableau des identifiants de titulaires),p_shares numeric[](tableau des parts correspondantes).
-
vérifie que :
- le nombre d’éléments dans
p_holdersetp_sharesest identique ; - la somme des parts est exactement égale à 1 ;
- chaque
holder_idexiste dans la tableholder.
- le nombre d’éléments dans
- Si tout est correct :
- crée un nouveau compte dans
account; - insère les lignes correspondantes dans
account_holder.
- Si une condition échoue :
-
la procédure doit lever une erreur explicite (
RAISE EXCEPTION) ; -
aucune insertion ne doit être faite (transaction annulée).
-
Les tableaux peuvent être parcourus avec une boucle :
for i in 1..array_length(p_holders, 1) loop
...
end loop;
- Pour vérifier la somme :
select sum(unnest(p_shares));
(ou additionner dans la boucle)
- Vous pouvez lever une erreur personnalisée :
raise exception 'La somme des parts doit être égale à 1 (%.4f)', somme;
Exemples d’appel
call create_account(
'FR761234567890',
'Compte commun',
array[1, 5],
array[0.5, 0.5]
);
Crée un compte partagé 50/50 entre les titulaires 1 et 2.
call create_account(
'FR009999999999',
'Compte déséquilibré',
array[1, 5],
array[0.7, 0.4]
);
Doit refuser la création avec une erreur claire :
ERROR: La somme des parts (1.1000) doit être égale à 1.0000
3. Monnaies et taux de change
insert into currency values ('EUR');
insert into currency values ('YEN');
insert into exchange_rate values
('YEN', '2025-11-03', 177.57),
('YEN', '2025-11-04', 176.39),
('YEN', '2025-11-05', 176.67),
('YEN', '2025-11-06', 177.15),
('YEN', '2025-11-07', 176.99);
Séance 3 : Exploitation des données
Utiliser la correction de la base de données
1. Vue : taux de change de la veille
Créer une vue yesterday_exchange_rates qui affiche pour chaque devise son taux de change de la veille présent dans exchange_rate.
Si aucun taux du jour n’existe, la ligne ne doit pas apparaître.
2. Fonction : dernier taux connu pour une devise et une date données
Créer une fonction latest_exchange_rate qui donne, pour une devise, son taux de change le plus récent :
3. Vue : liste détaillées des titulaires
Créer une vue holder_details permettant d’afficher tous les titulaires (banque, personne ou entreprise) sous une forme unifiée.
La vue doit contenir :
-
l’identifiant du titulaire
-
son type
-
un champ
display_namecalculé ainsi :- pour un titulaire de type PERSON : firstname lastname
- pour un titulaire de type COMPANY : name
- pour un titulaire de type BANK : name
4. Vue : liste des comptes avec devise et solde
Créer une vue account_detail affichant :
- l’identifiant du compte
- la date d’ouverture
- la devise
- le solde
- le nombre de titulaires du compte
5. Vue : comptes par titulaire
Créer une vue holder_accounts permettant de lister les comptes détenus par chaque titulaire, avec :
- le titulaire (id et type)
- le nom du titulaire
- l’identifiant du compte
- la part détenue (
share) - le solde total du compte
La vue doit fusionner les informations venant de holder, person et company.
6. Vue : opérations enrichies
Créer une vue operation_details affichant les opérations avec :
- la date de l’opération
- le compte impacté
- la direction (DEBIT ou CREDIT)
- le montant de l’opération
- le montant signé (crédit positif, débit négatif)
- le solde du compte après l’opération (bonus : fenêtre analytique)
7. Vue : solde converti en EUR
Créer une vue account_balance_eur pour afficher :
- compte
- devise d’origine
- solde original
- taux de change correspondant à la date du jour
- solde converti en EUR (solde × taux)
8. Vue : transactions complètes
Créer une vue transaction_summary affichant un regroupement par transaction :
- id de la transaction
- date
- montant total de la transaction (somme des opérations)
- liste des comptes concernés (optionnel : concaténation)
9. Vue : comptes en découvert imminent
Créer une vue accounts_at_risk listant les comptes dont le solde est inférieur à 50 (dans leur devise), ou qui auraient un solde négatif s'ils effectuaient un débit supplémentaire de 20.
Vérification simple :
balance - 20 < 0 OR balance < 50.
10. Vue : âge des personnes
Créer une vue person_age indiquant :
- id
- nom complet
- date de naissance
- âge en années (utiliser
age())
11. Vue : répartition des parts d’un compte
Créer une vue account_shares affichant :
- id du compte
- nombre de titulaires
- somme des parts
- une colonne booléenne
is_validvérifiant si la somme = 1
Objectif : vérifier que les parts des comptes joints sont bien réparties.
12. Vue : solde par titulaire
Créer une vue holder_total_balance indiquant pour chaque titulaire :
- id
- type
- nom
- somme des soldes de tous ses comptes (pondérée par
share), calcul :total = SUM(share × balance)
13. Vue : opérations d’un compte en sens unique
Créer une vue account_debits listant uniquement les opérations de type DEBIT, avec :
- date
- compte
- montant négatif
Créer une seconde vue account_credits (montants positifs).
14. Vue : liste des entreprises avec ancienneté
Créer une vue company_age indiquant :
- id
- name
- registration_number
- age de l’entreprise en années (
age(current_date, created_at))
15. Vue : recapitulatif bancaire complet
Créer une vue bank_overview qui croise :
- les titulaires
- leurs comptes
- leurs transactions
- leurs opérations
Voir les adresses des serveurs postgreSQL