6. PRODUCTION DU CODE DE LA BASE DE DONNEES
Version 2 - Septembre 2018
6.1 Introduction
6.2 Expression déclarative
6.3 Comportements non standard
6.4 Contraintes d'intégrité de base et additionnelles 6.5 Contraintes dérivées du modèle Entité-association 6.6 Contraintes d'intégrité dynamiques
6.7 Traduction des relations is-a 6.8 Traduction des vues
Contenu
6. PRODUCTION DU CODE DE LA BASE DE DONNEES
6.1 INTRODUCTION
6.1 Introduction
La production du code consiste à traduire les structures du schéma physique et des vues dans un code exécutable propre à un SGBD.
Observation : il n'est pas possible de traduire explicitement toutes les structures et toutes les contraintes dans le DDL du SGD.
⇒ recours à diverses techniques internes ou externes au SGD, plus ou moins
élégantes, plus ou moins faciles à maintenir.
Donc, le code comporte deux parties (pour une BD relationnelle) :
• code SQL-DDL : structures et contraintes natives déclarables directement en SQL
• code additionnel : tout le reste; expression en SQL générique ou selon d'autres techniques (= code additionnel)
physique
code DDL code
additionnel
vues
Production de code
• SGBD
6.1 Introduction
Les concepts SQL d’expression de contraintes
• Les déclarations natives
• Les prédicats de colonne et de table (check)
• Les vues filtrantes (view with check option)
• Les déclencheurs (trigger)
• Les procédures SQL (stored procedures)
Autres techniques
• Modules d’accès (wrappers)
• Méthodes des tables typées (SQL3)
• Interfaces Object-Relational Mapping ou ORM
6.2 Expression déclarative
objet code schéma
create database <nom schéma>;ou
create schema <nom schéma>;ou . . .
table
create table <nom table> (<colonnes> <contraintes>) in <espace stockage>;colonne facultative
<nom colonne> <type colonne>colonne obligatoire
<nom colonne> <type colonne> not nullidentifiant primaire
primary key (<composants>)identifiant secondaire
unique (<composants>)clé étrangère
foreign key (<composants>) references <nom table>index
create index <nom index> on <nom table> (<composants>)espace de stockage
create tablespace;ou
create dbspace;ou . . .
Règles de base (SQL2)
6.2 Expression déclarative
Un exemple (rappel)
Voir "Methodologie-des-BD-(court)-(Production-sch-BD).ppt",
section "Traduction des structures en SQL"
6.3 Comportements non standard
6.3 Comportements non standard
On peut exiger d'une construction native un comportement non standard.
Exemple : gestion atypique de l'intégrité référentielle.
Mode cascade lors d'une insertion
create trigger TRG_COMMANDE_CLI_MANQUANT before insert on COMMANDE
for each row declare I number begin
select count(*) into :I from CLIENT where NCLI = new.NCLI;
if I = 0 then
insert into CLIENT (NCLI,NOM,ADRESSE,LOCALITE,COMPTE) values (new.NCLI,'?','?','?',0);
end if;
end;
6.3 Comportements non standard
Mode cascade inversé
create trigger TRG_DETAIL_SUPP_DERNIER after delete on DETAIL
for each row declare I number begin
select count(*) into :I
from DETAIL where NCOM = old.NCOM;
if I = 0 then
delete from COMMANDE where NCOM = old.NCOM;
end if;
end;
6.4 Contraintes d'intégrité de base et additionnelles
6.4 Contraintes d'intégrité de base et additionnelles
Contraintes d'intégrité de base
• Contrainte de domaine
• Contrainte inter-valeurs
• Contrainte d'existence
Contraintes d'intégrité additionnelles
• Contraintes cycliques
• Contraintes sur le graphe des instances
• Contraintes de redondance
CI de base : contraintes de domaine
alter table EMPLOYE add constraint CHECK_DOM_EMP_SEXE check(SEXE in ('M','m','F','f'));
create table MP(MODE_PAIEMENT char(5) not null primary key);
create table FACTURE(..., MODE char(5), ...,
foreign key (MODE) references MP on delete no action
on update cascade);
6.4 Contraintes d'intégrité de base
CI de base : contraintes d'existence
alter table T add constraint CHECK_T_COEX_AB check( (A is not null and B is not null)
or (A is null and B is null) );
coex: A,B ⇒
contrainte prédicat
coex: A, B (A ∧ B) ∨ (¬A ∧ ¬B)
excl: A, B (¬B) ∨ (¬A)
at-lst-1: A, B A ∨ B
exact-1: A, B (A ∧ ¬B) ∨ (¬A ∧ B)
if: A, B B ∨ ¬A
CI de base : contraintes d'existence
alter table T add constraint CHECK_T_COEX_AB
check( (A is not null and B is not null and C is not null) or (A is null and B is null and C is null) );
coex: A,B,C ⇒
contrainte prédicat
coex: A, B (A ∧ B) ∨ (¬A ∧ ¬B)
coex: A, B, C (A ∧ B ∧ C) ∨ (¬A ∧¬B ∧¬C)
excl: A, B (¬B) ∨ (¬A)
excl: A, B, C (¬B ∧ ¬C) ∨ (¬A ∧ ¬C) ∨ (¬A ∧ ¬B) at-lst-1: A, B A ∨ B
at-lst-1: A, B, C A ∨ B ∨ C
exact-1: A, B (A ∧ ¬B) ∨ (¬A ∧ B)
exact-1: A, B, C (A ∧ ¬B ∧ ¬C) ∨ (¬A ∧ B ∧ ¬C) ∨ (¬A ∧ ¬B ∧ C)
if: A, B B ∨ ¬A
if: A, B, C (B ∧ C) ∨ ¬A
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : cycliques
Règle générale difficile à trouver. Raisonnement au cas par cas
CI additionnelles : cycliques
1-1 0-N départ
1-1 0-N arrivée STATION NomCommune id: Nom
SECTION NumOrdre Longueur
SECTION.départ.STATION ≠ SECTION.arrivée.STATION
SECTION.StationDepart ≠ SECTION.StationArrivée STATION
NomCommune id: Nom SECTION
NumOrdre Longueur StationDepart StationArrivee ref: StationDepart ref: StationArrivee
⇒
alter table SECTION
add constraint CHECK_SECTION_STATIONS
⇓
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : cycliques
VEHICULE.couvre.CONTRAT.signe.CLIENT
VEHICULE.appartient.CLIENT=
⇓
1-1 0-N signe
1-1 couvre 0-1 1-1
appartient 0-N
VEHICULE NumVéh Marque Modèle Année Cylindrée id: NumVéh
CONTRAT NumCtr TypeDateSign id: signe.CLIENT
NumCtr CLIENT
NumClient NomAdresse id: NumClient
VEHICULE.SIGNATAIRE = VEHICULE.NUMCLIENT
⇒
VEHICULE NUMVEH MARQUE MODELE ANNEE CYLINDREE SIGNATAIRE NUMCTR NUMCLIENT id: NUMVEH id': SIGNATAIRE
NUMCTR ref: NUMCLIENTref
CLIENT NUMCLIENT NOMADRESSE id: NUMCLIENT
CONTRAT SIGNATAIRE NUMCTR TYPEDATESIGN id: SIGNATAIRE
NUMCTR ref: SIGNATAIRE
CI additionnelles : cycliques
EMPRUNTEUR.emprunte.EXEMPLAIRE.de.DOCUMENT
⊄
EMPRUNTEUR.réserve.DOCUMENT
⇒
0-N 0-N réserve
0-N 0-N 0-N
emprunte 1-1
0-N de D
PROJET CodeProjet id: CodeProjet OUVRAGE
ISBN Editeur id': ISBN
EXEMPLAIRE Numéro-série id: de.OUVRAGE
Numéro-série
EMPRUNTEUR NumPers id: NumPers DOCUMENT
ID-Doc id: ID-Doc
RESERVATION NumPers ID-Doc id: ID-Doc
NumPers ref: ID-Doc ref: NumPers
PROJET CodeProjet id: CodeProjet OUVRAGE
ID-Doc ISBNEditeur id: ID-Doc
ref
id': ISBN EXEMPLAIRE
ID-Doc Numéro-série id: ID-Doc
Numéro-série ref: ID-Doc
EMPRUNTEUR NumPers id: NumPers
EMPRUNT ID-Doc Numéro-série NumPers CodeProjet id: CodeProjet
NumPers ID-Doc Numéro-série ref: NumPers ref: CodeProjet ref: ID-Doc
Numéro-série DOCUMENT
ID-Doc id: ID-Doc
pour tout EMPRUNT E,
il n'existe pas (RESERVATION R
where E.ID-Doc = R.ID-Doc and E.NumPers = R.NumPers) un emprunteur qui emprunte un exemplaire d'un ouverage
ne peut en même temps réserver ce dernier
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : cycliques
pour tout EMPRUNT E,
create trigger TRG_EMPRUNT_NON_RESERVE before insert on EMPRUNT
for each row declare I number begin
⇒
RESERVATION NumPers ID-Doc id: ID-Doc
NumPers ref: ID-Doc ref: NumPers
PROJET CodeProjet id: CodeProjet OUVRAGE
ID-Doc ISBN Editeur id: ID-Doc
ref
id': ISBN EXEMPLAIRE
ID-Doc Numéro-série id: ID-Doc
Numéro-série ref: ID-Doc
EMPRUNTEUR NumPers id: NumPers
EMPRUNT ID-Doc Numéro-série NumPers CodeProjet id: CodeProjet
NumPers ID-Doc Numéro-série ref: NumPers ref: CodeProjet ref: ID-Doc
Numéro-série DOCUMENT
ID-Doc id: ID-Doc
CI additionnelles : graphe des instances
Raisonnement au cas par cas. En général procédures récursives
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : graphe des instances
subordonné0-1 responsable0-N
supervise PERSONNE NPers Nom id: NPers
le graphe des instances de superviseest acyclique
PERSONNE NPERS
NOMRESPONSABLE[0-1]
id: NPERS
ref: RESPONSABLE
⇒
create trigger TRG_SUPERVISE_ACYCLIQUE before update of RESPONSABLE on PERSONNE for each row
declare S char(4) begin
S := new.RESPONSABLE;
while S is not null
if S = new.NPERS then abort(); end if;
= "tail recursion"
la contrainte ne peut
être violée que par
un update
CI additionnelles : redondances
Méthodologie sommaire :
1. identifier les événements susceptible d'affecter l'état de l'objet redondant C
2. définir pour chacun une réaction de mise à jour de C 3. coder cette réaction
Gestion de la redondance le plus souvent par triggers
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : redondances
∀ cli ∈ CLIENT, cli.Total = Σ com.Montant
com ∈cli.passe.COMMANDE 1-1
0-N passe
COMMANDE NumCom DateCom Montant id: NumCom CLIENT
NumCli NomAdresse Total id: NumCli
COMMANDE NumCom DateCom Montant NumCli id: NumCom ref: NumCli CLIENT
NumCli NomAdresse Total id: NumCli
∀ cli ∈ CLIENT,
cli.Total = Σ com.Montant
com ∈COMMANDE ∧com.NumCli = cli.NumCli
⇒
CI additionnelles : redondances
Événement Réaction et codage
insert into CLIENT mise à 0 de Total ;
codage : par trigger ; "default 0" insuffisant
update CLIENT set Total opération interdite;
codage
: "revoke update(Total) on CLIENT from public"
ou trigger annulant l’opération
update CLIENT set NumCli propager la modification vers la clé étrangère ;
codage : clé étrangère avec "on update cascade"insert into COMMANDE ajouter à Total la valeur de Montant ;
codage : trigger TRG_COMMANDE_INSERT
delete from COMMANDE retirer de Total la valeur de Montant ;
codage : trigger TRG_COMMANDE_DELETE
update COMMANDE set Montant ajouter à Total la différence des valeurs nouvelle et
ancienne de Montant ;
codage : trigger TRG_COMMANDE_UPDATE_Montant
update COMMANDE set NumCli retirer de Total de l’ancien client la valeur de Montant ;
ajouter à Total du nouveau client la valeur de Montant ;
codage: trigger TRG_COMMANDE_UPDATE_NumCli
6.4 Contraintes d'intégrité additionnelles
CI additionnelles : redondances
create trigger TRG_COMMANDE_UPDATE_NumCli after update of NumCli on COMMANDE
for each row begin
update CLIENT set Total = Total - old.Montant where NumCli = old.NumCli;
update CLIENT set Total = Total + new.Montant
COMMANDE NumCom DateCom Montant NumCli id: NumCom ref: NumCli CLIENT
NumCli NomAdresse Total id: NumCli
6.5 Contraintes dérivées du modèle Entité-association
6.5 Contraintes dérivées du modèle Entité-association
Contraintes complexes dérivant du modèle Entité-association
mais pour lesquelles il n'existe pas de traduction immédiate en SQL
• contrainte référentielle totale : equ
• cardinalités spéciales : [0-10]
• contraintes de sous-types : ⇒ section 7.7
VEHICULE NumVéh Marque id: NumVéh
IMPLICATION NumAcc NumVéh id: NumAcc
NumVéh ref: NumVéh equ: NumAcc
ACCIDENT NumAcc DateAcc id: NumAcc
Contrainte référentielle totale : equ
Mécanisme des FK et triggers insuffisants.
Résolution par transactions, par procédures SQL, par méthodes SQL3.
• pour créer une ligne d'ACCIDENT, une ligne d'IMPLICATION doit exister au préalable
• pour créer une ligne d'IMPLICATION, une ligne d'ACCIDENT doit exister au préalable
⇒ les deux lignes doivent être créées en même temps
6.5 Contraintes dérivées du modèle Entité-association
Événement Réaction et codage
insert into ACCIDENT au moins une ligne d’IMPLICATION doit être insérée simultanément ;
codage : transaction ou procédure SQL
si la ligne d’ACCIDENT n’existe pas, elle est insérée simultanément ;
codage : transaction ou procédure SQL
insert into IMPLICATION
si la ligne d’ACCIDENT existe déjà, comportement standard delete from ACCIDENT blocage ou propagation ; codage : "on delete no action" ou
"on delete cascade"
si cette ligne n’est pas la dernière de sa ligne d’ACCIDENT, comportement standard
delete from IMPLICATION
si cette ligne est la dernière de sa ligne d’ACCIDENT, soit l’opération est annulée, soit cette ligne d’ACCIDENT est
Contrainte référentielle totale : equ
Observation : objet complexe ACCIDENT = 1 ACCIDENT + n IMPLICATION 1. Jeux de procédures SQL gérant les instances de cet objet
VEHICULE NumVéh Marque id: NumVéh
IMPLICATION NumAcc NumVéh id: NumAcc
NumVéh ref: NumVéh equ: NumAcc
ACCIDENT NumAcc DateAcc id: NumAcc
2. Méthodes de la table typée ACCIDENT (en SQL3)
objet complexe ACCIDENT
Contrainte référentielle totale : equ
3. Egalement via un ORM, mais prudence !
voir tutoriel Legacy and Future of Database Reverse Engineering, site LIBD
accès au tutoriel
6.5 Contraintes dérivées du modèle Entité-association
Cardinalités spéciales : [0-10]
MOTCLE_DE_DOC ID_Doc
MotCle id: ID_Doc
MotCle ref: ID_Doc DOCUMENT
ID_Doc Titre Date_Public RAPPORT[0-1]
OUVRAGE[0-1]
id: ID_Doc
pas plus de 10 mots clés par document pas plus de 10 instances de MOTCLE_DE_DOC=
pour une même valeur de ID_Doc
create trigger TRG_MOTCLE_DE_DOC_MAX_10
before insert or update of ID_Doc on MOTCLE_DE_DOC for each row
declare I number begin
select COUNT(*) in :I from MOTCLE_DE_DOC
where ID_Doc = new.ID_Doc;
6.6 Contraintes d'intégrité dynamiques
6.6 Contraintes d'intégrité dynamiques
Une contrainte dynamique
1. exige la comparaison des états des données avant et après la modification 2. ou impose des préconditions à la modification
⇒ utilisation de triggers ou de procédures SQL
create trigger TRG_CLIENT_OBSOLETE before delete on CLIENT
for each row declare I number begin
select count(*) into :I from COMMANDE
where NCLI = old.NCLI and DATECOM >= '1-1-2009';
if I > 0 then abort(); end if;
end;
Exemple
on n’autorise la suppression d’un client
que s’il n’a plus envoyé de commandes depuis le 1er janvier 2009
6.7 Traduction des relations is-a
D
⇒
RAPPORT Code-Rapport Projet
OUVRAGE ISBNEditeur DOCUMENT ID-DOC Titre id: ID-DOC
D
⇒
⇒
⇒
excl: RAPPORT, OUVRAGE
Technique privilégiée
pour tout DOCUMENT D, D.RAPPORT is not null
= existe(RAPPORT R where R.ID_Doc = D.ID_Doc) pour tout DOCUMENT D,
D.OUVRAGE is not null
= existe(OUVRAGE O where O.ID_Doc = D.ID_Doc) RAPPORT
ID-DOC Code-Rapport Projet id: ID-DOC
ref
OUVRAGE ID-DOC ISBNEditeur id: ID-DOC
ref DOCUMENT
ID-DOC Titre
RAPPORT[0-1]
OUVRAGE[0-1]
id: ID-DOC excl: OUVRAGE
RAPPORT
???
6.7 Traduction des relations is-a
Traduction en SQL
Deux cas distincts :
1. pas de contrainte de totalité : D ou libre
2. contrainte de totalité : T ou P plus difficile
facile
Traduction en SQL : pas de contrainte de totalité
• via le programmeur : comment programmer ?
• via le SGBD : comment gérer ?
6.7 Traduction des relations is-a
Traduction en SQL : pas de contrainte de totalité
• création d’un rapport
insert into DOCUMENT(ID_Doc,Titre) values('12','Etude finale');
insert into RAPPORT(ID_Doc,Code_rapport,Projet) values('12','R0177','BIOGEN');
• suppression d’un rapport
delete from DOCUMENT where ID_Doc='12';
• un document n’est plus un rapport
delete from RAPPORT where ID_Doc='12';
• un document devient un rapport
insert into RAPPORT(ID_Doc,Code_rapport,Projet) values('12','R0177','BIOGEN')
Programmeur : comment programmer ?
Traduction en SQL : pas de contrainte de totalité
• à la création d’un document
create trigger TRG_DOCUMENT_INSERT_SURTYPE before insert on DOCUMENT
for each row begin
new.RAPPORT = null; new.OUVRAGE = null;
end;
SGBD : comment gérer ?
• pas de manipulation directe des indicateurs de type
revoke update (RAPPORT, DOCUMENT) on DOCUMENT from public;
revoke update (ID_Doc) on RAPPORT from public;
1. Initialisation des indicateurs de sous-types
6.7 Traduction des relations is-a
Traduction en SQL : pas de contrainte de totalité
alter table RAPPORT add constraint FK_RAPPORT_DOC foreign key (ID_Doc) references DOCUMENT
on delete cascade on update cascade;
SGBD : comment gérer ?
2. Clés étrangères
Traduction en SQL : pas de contrainte de totalité
create trigger TRG_RAPPORT_INSERT_ISA_DOC before insert on RAPPORT
for each row declare I number begin
select COUNT(*) in :I from DOCUMENT where ID_Doc = new.ID_Doc
and (RAPPORT is not null or OUVRAGE is not null);
if I = 1 then abort(); end if;
update DOCUMENT set RAPPORT = '*' where ID_Doc = new.ID_Doc;
end;
SGBD : comment gérer ? 3. A la création d'un rapport (DOCUMENT existant)
si disjonction
6.7 Traduction des relations is-a
Traduction en SQL : pas de contrainte de totalité
create trigger TRG_RAPPORT_DELETE_ISA_DOC after delete on RAPPORT
for each row begin
update DOCUMENT set RAPPORT = null where ID_Doc = new.ID_Doc;
end;
SGBD : comment gérer ?
4. A la suppression d'un rapport (DOCUMENT subsistant)
Traduction en SQL : contrainte de totalité (T ou P)
Créer un rapport
insertion simultanée de 1 ligne de DOCUMENT + 1 ligne de RAPPORT =
Problème similaire à la contrainte référentielle totale equ ...
6.7 Traduction des relations is-a
Traduction en SQL : contrainte de totalité (T ou P)
1. Jeux de procédures SQL (RAPPORT_CREER, etc.)
2. Tables typées RAPPORT et OUVRAGE avec héritage (en SQL3) 3. ORM (prudence)
Mais : Procédures et O/RM interdisent SQL !
Traduction en SQL : contrainte de totalité (T ou P)
create view DOC_RAPPORT(ID_Doc, Titre, Code_Rapport, Projet) as select D.ID_Doc, Titre, Code_Rapport, Projet
from DOCUMENT D, RAPPORT S where D.ID_Doc = R.ID_Doc;
• création d’un rapport
insert into DOC_RAPPORT(ID_Doc, Titre, Code_Rapport, Projet) values ('12','Etude finale','R0177','BIOGEN');
• suppression d’un rapport
delete from DOC_RAPPORT where ID_Doc='12';
• modification d’un rapport
update DOC_RAPPORT set Titre='Etude finale', Projet='BIOSTAT'
Deux approches plus légères en SQL2
1. Via une vue (si vue modifiable)
6.7 Traduction des relations is-a
Traduction en SQL : contrainte de totalité (T ou P)
create view DOC_RAPPORT(ID_Doc, Titre, Code_Rapport, Projet) as select D.ID_Doc, Titre, Code_Rapport, Projet
from DOCUMENT D, RAPPORT S where D.ID_Doc = R.ID_Doc;
• création d’un rapport
create trigger TRG_INSERT_DOC_RAPPORT instead of insert on DOC_RAPPORT
for each row begin
insert into DOCUMENT(ID_Doc,Titre,RAPPORT)
Deux approches plus légères en SQL2
2. Via une vue (si vue non modifiable et si "triggers instead of" autorisés)
Piste à explorer
create table DOCUMENT(
ID_DOC char(20) not null,
Subtype char(1) not null default '', ...,
primary key (ID_DOC), unique (ID_DOC,Subtype),
check(Subtype in ('R','O','') );
create table RAPPORT(
ID_DOC char(20) not null,
Subtype char(1) default 'R' not null, primary key (ID_DOC), ...,
foreign key (ID_DOC,Subtype) references DOCUMENT(ID_DOC,Subtype) on delete cascade on update cascade,
check(Subtype = 'R') );
create table OUVRAGE(
ID_DOC char(20) not null,
Subtype char(1) default 'O' not null, primary key (ID_DOC), ...,
D
RAPPORT Code-Rapport Projet
OUVRAGE ISBNEditeur DOCUMENT ID-DOC Titre id: ID-DOC