FACULTES UNIVERSITAIRES NOTRE-DAME DE LA PAIX Institut d'informatique NAMUR Séminaires DB-MAIN/Objectif 1 ST3 : Techniques de bases de données avancées Deuxième version Namur - Mai 2000 Avec le soutien du Fonds Social Européen et de la Région Wallonne
Les séminaires DB-MAIN/Objectif 1 Ce séminaire s'inscrit dans une série de six modules coordonnés. D'autres modules sont en préparation. Introduction aux bases de données (Objectif 1-2 jours) Présentation des structures de bases de données relationnelles. Introduction au langage SQL. Les fonctions des SGBD. Analyse de l'information et conception de bases de données (3 jours) Introduction aux problèmes, raisonnements et outils relatifs au développement systématique des bases de données. Introduction aux outils CASE (2 + 1 jours) Etude crititique des fonctions des outils CASE modernes. La présentation et les discussions sont basées sur l'utilisation de l'outil DB- MAIN. La troisième journée est consacrée aux problèmes de l'extensibilité des outils (méta-case). Introduction à la rétro-ingénierie (3 jours) Repérage et analyse des problèmes de la reconstruction de la documentation d'une base de données (ou ensemble de fichiers) existante. Proposition de techniques et de méthodes de résolution. Rôles des outils CASE en rétro-ingénierie. Une journée de travaux pratiques sur outil CASE (y compris problème de l'an 2000). Techniques de bases de données avancées (2 jours) Etudes des problèmes liés aux applications complexes utilisant des bases de données. Programmation transactionnelle. Intégrité, protection contre les incidents, régulation de la concurrence. Les prédicats, les Triggers et Stored procedures. Application au contrôle de l'intégrité, de la redondance et aux bases de données réactives. Les architectures d'applications de bases de données (2 jours) Les applications distribuées. Middleware. Etude comparée de différentes architectures d'applications utilisant des bases de données : client/serveurs, fat/thin client, business objects, serveurs d'objets actifs, etc. DB-MAIN - Techniques de BD avancées ( FUNDP) 0.2
Le programme DB-MAIN DB-MAIN est un programme de R&D et de transfert de technologie consacré à l'ingénierie des applications de bases de données. Il étudie la modélisation, les méthodes et les outils qui supportent non seulement les processus d'ingénierie classiques (analyse et conception) mais également les processus plus complexes tels que la normalisation, l'optimisation, la génération de code, la rétro-ingénierie, la maintenance, l'évolution, la migration et l'intégration de systèmes. Le programme comprend actuellement huit projets. DB-MAIN : ingénierie générale, rétro-ingénierie, évolution, outils CASE, méta-case. Personnel : Jean Henrard, Vincent Englebert, Didier Roland, Jean-Marc Hick. DB-Process : modélisation des méthodes, pilotage méthodologique via les outils CASE. Personnel : Didier Roland. DB-MAIN/Objectif 1 : transfert de technologie et assistance méthodologique à destination des entreprises et organismes du Hainaut. Etude des architectures d'objets distribués. Personnel : Alain Gofflot, Pierre Delvaux, Anne-France Brogneaux, Vincent Englebert. InterDB : intégration de systèmes, interopérabilité des systèmes autonomes, hétérogènes et distribués. Personnel : Philippe Thiran, Jean-Marc Hick, Majid Chougrani, N. TimeStamp : méthodologie et programmation des bases de données à référence temporelle (ou BD historiques). Développement d'outils CASE et d'accélérateurs de requêtes. Personnel : Denis Zampuniéris, Virginie Detienne, Didier Roland. PROAGEC : élaboration d'un schéma conceptuel des informations de gestion communale en Wallonie, administration de données. Migration de données : techniques et méthodes de concersion de données. Application à la migration BD-BD, BD-datawarehouse, BD-XML. Personnel : Christine Delcroix. BD actives : analyse, validation et génération de BD actives (triggers). DB-MAIN - Techniques de BD avancées ( FUNDP) 0.3
Les séminaires de formation, dont le présent module, ainsi que l'outil CASE DB-MAIN sont parmi les principaux produits de ce programme. Le programme dispose du soutien financier de : l'université de Namur (F.U.N.D.P) la communauté Française de Belgique (projets DB-PROCESS, BD actives) la Région Wallonne (projets DB-MAIN/Objectif 1, InterDB, TimeStamp, PROAGEC, Migration de données) l'union Européenne (projets DB-MAIN/Objectif 1, Migration de données) un consortium (ouvert) de partenaires : ACEC-OSI ARIANE-II ASCII Banque UCL (Lux) BBL Cap Gemini (Lux) Carrières du Hainaut Centre de Rech. Pub. H. Tudor (Lux) Cliniques Universitaires St-Luc CGER COCKERILL-SAMBRE CONCIS (Fr) Régie des Bâtiments D'Ieteren DIGITAL EDF (Fr) Euro Views Services Groupe S IBM Institut Nat. de Criminalistique Ministère Région Bxl-Capitale OBLOG Software (Port) ORIGIN TEC de Charleroi Ville de Namur WINTERTHUR 3 SUISSES autres partenariats en discussion DB-MAIN - Techniques de BD avancées ( FUNDP) 0.4
Contacts Responsable du programme prof. Jean-Luc Hainaut Institut d'informatique rue Grandgagnage, 21 B-5000 Namur (Belgium) +32 (0)81 / 72.49.96 jlhainaut@info.fundp.ac.be DB-MAIN, site de Namur Programme DB-MAIN Institut d'informatique rue Grandgagnage, 21 B-5000 Namur (Belgium) Tél. +32 (0)81 / 72.49.85 Fax +32 (0)81 / 72.49.67 E-mail : db-main@info.fundp.ac.be URL : http://www.info.fundp.ac.be/~dbm DB-MAIN, site de Charleroi DB-MAIN/Objectif 1 CTTC - FUNDP Charleroi Boulevard Tirou, 130 B-6000 Charleroi (Belgium) Tél. +32 (0)71 / 20.71.55/54/57 Fax +32 (0)71 / 30.66.36 E-mail : {agf, pde, afb}@fun.cediti.be DB-MAIN - Techniques de BD avancées ( FUNDP) 0.5
CONTENU DU SEMINAIRE 1. Rappel des notions de base de données 1.1 Notion de SGBD 1.2 Le langage SQL 1.3 La programmation d'application 1.4 Architectures des systèmes applicatifs 2. Intégrité des données 2.1 Notion(s) d'intégrité 2.2 Responsabilité des contraintes d'intégrité 2.3 Etats de correction d'une base de données 2.4 Sources de corruption d'une base de données 3. Transactions 3.1 Définition et propriétés 3.2 Les primitives 3.3 Définition d'une transaction 3.4 Comportement de la transaction 3.5 Structures de transaction 3.6 Transactions hiérarchiques 3.7 Transactions et triggers 3.8 Transactions et intégrité 4. Protection contre les incidents 4.1 Principes 4.2 Principes de la gestion des tampons 4.3 Sauvegarde (backup) 4.4 Journal (log) 4.5 Reprise suite à un incident grave 4.6 Reprise suite à un incident léger 4.7 Protocoles de gestion de la BD et des journaux 5. Régulation de la concurrence 5.1 Principes 5.2 Trois problèmes de concurrence 5.3 Sérialisabilité d'un ensemble de transactions DB-MAIN - Techniques de BD avancées ( FUNDP) 0.6
5.4 Techniques de régulation 5.5 Techniques de verrouillage 5.6 Le problème de l'interblocage 6. Les techniques SQL 6.1 Organisation 6.2 Techniques natives 6.3 Prédicats 6.4 Views with check option 6.5 Langage procédural 6.6 Stored procedures 6.7 Triggers 7. La gestion de l'intégrité 7.1 Architectures de validation 7.2 Commentaires 7.3 Techniques natives 7.4 Prédicats 7.5 Triggers 7.6 Views with check option 7.7 Stored procedures 7.8 Modules d accès 7.9 Sections de code distribuées dans les programmes d application 7.10 Procédures de validation attachées aux écrans de saisie 7.11 Programme de validation avant chargement 7.12 Programme de validation après chargement 7.13 Comportement en cas de violation 7.14 Les objets à contraintes multiples 8. Applications 8.1 Gestion de l intégrité statique 8.2 Gestion de l intégrité dynamique 8.3 Gestion de la redondance 8.4 Alerteurs DB-MAIN - Techniques de BD avancées ( FUNDP) 0.7
8.5 Gestion de données temporelles 9. Les interfaces ODBC et JDBC 9.1 Principes 9.2 ODBC 9.3 JDBC 9.4 Références ODBC, JDBC 10. Bibliographie DB-MAIN - Techniques de BD avancées ( FUNDP) 0.8
Techniques SQL avancées 1. Rappel des notions de bases de données 1.1 Notion de SGBD 1.2 Le langage SQL 1.3 La programmation d'application 1.4 Architectures des systèmes applicatifs 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
1. Rappel des notions de bases de données 1.1 Notion de SGBD Système de gestion de bases de données Système logiciel assurant, entre autres, les fonctions de définition des structures de données, de leur évolution, de gestion des données, d'accès aux données, de contrôle de l'intégrité, du contrôle d'accès, de la protection contre les incidents, de la régulation de la concurrence. Permet de gérer de gros volumes de données complexes, d'offrir un accès performant et de garantir une qualité et une continuité de service. Offre commerciale de moteurs SQL Oracle Ingres Sybase Informix DB2 SQL Server autres DB-MAIN - Techniques SQL avancées ( FUNDP) 1.2
1. Rappel des notions de bases de données 1.2 Le langage SQL SQL = Lingua franca des bases de données. A. Définition/modification des structures de la BD (DDL) Création de tables, de colonnes, de clés (primaires et étrangères). create table CLIENT ( NCLI char(4) not null, NOM char(12) not null, ADRESSE char(20) not null, LOCALITE char(12) not null, CAT char(2), COMPTE decimal(9,2) not null, primary key (NCLI) ) create table COMMANDE ( NCOM char(4) not null, NCLI char(4) not null, DATE date not null, primary key (NCOM), foreign key (NCLI) references CLIENT on delete cascade) create table DETAIL (NCOM char(4) not null, NPRO char(5) not null, QCOM decimal(4) not null, primary key (NCOM, NPRO), foreign key (NCOM) references COMMANDE on delete restrict, foreign key (NPRO) references PRODUIT ) DB-MAIN - Techniques SQL avancées ( FUNDP) 1.3
1. Rappel des notions de bases de données 1.2 Le langage SQL Suppression et modification de tables drop table DETAIL alter table PRODUIT add POIDS smallint alter table PRODUIT drop PRIX alter table CLIENT add primary key (NCLI) alter table COMMANDE add foreign key FK_CLI (NCLI) references CLIENT Création/suppression d'index create index XLOC on CLIENT (LOCALITE asc) create unique index XLIGNE on DETAIL (NCOM,NPRO) drop index XLIGNE DB-MAIN - Techniques SQL avancées ( FUNDP) 1.4
1. Rappel des notions de bases de données 1.2 Le langage SQL B. Consultation/extraction des données select NCLI, NOM from CLIENT where LOCALITE ='Toulouse' select 'TVA de ', NPRO, ' = ',0.21*PRIX*QSTOCK from PRODUIT where QSTOCK > 500 select 'Namur', avg(compte), count(*) from CLIENT where LOCALITE = 'Namur' select NCOM,DATE from COMMANDE where NCLI in (select NCLI from CLIENT where LOCALITE = 'Namur') select NCOM, NCLI, DATE, NOM, ADRESSE from COMMANDE, CLIENT where COMMANDE.NCLI = CLIENT.NCLI and CAT = 'C1' and DATE < 15/3/94 select NCLI, count(*), sum(qcom) from COMMANDE C, DETAIL L where C.NCOM = L.NCOM and NPRO = 'PA60' group by NCLI having count(*) >= 2 order by NCLI DB-MAIN - Techniques SQL avancées ( FUNDP) 1.5
1. Rappel des notions de bases de données 1.2 Le langage SQL C. Modification des données insert into COMMANDE values ('30191','S712','12/4/2000') insert into CLIENT_TOULOUSE select NCLI, NOM, ADRESSE from CLIENT where LOCALITE = 'Toulouse' delete from DETAIL where NPRO = 'PA60' update PRODUIT set PRIX = PRIX * 1.05 where LIBELLE like '%SAPIN%' update PRODUIT P set QSTOCK = QSTOCK - (select sum(qcom) from DETAIL where NPRO = P.NPRO) and NCOM in (select NCOM from COMMANDE where DATE => X)) DB-MAIN - Techniques SQL avancées ( FUNDP) 1.6
1. Rappel des notions de bases de données 1.2 Le langage SQL D. Définition des vues create view HABITUDE-ACHAT(LOCALITE,NPRO,VOLUME) as select LOCALITE, P.NPRO, sum(qcom*prix) from CLIENT L, COMMANDE C, DETAIL D, PRODUIT P where C.NCLI = L.NCLI and D.NCOM = C.NCOM and P.NPRO = D.NPRO group by LOCALITE, P.NPRO create view CLI(NCLI,NOM,ADR,LOC,CAT,CPTE) as select * from CLIENT where CAT is null or CAT in ('B1','B2','C1','C2') with check option DB-MAIN - Techniques SQL avancées ( FUNDP) 1.7
1. Rappel des notions de bases de données 1.2 Le langage SQL E. Contrôle d'accès (privilèges) grant select, update(qstock) on PRODUIT to GPERS2, FINCT grant all on CLIENT to GPERS2, FINCT with grant option grant run on COMPTA01 to GES66 revoke update(qstock) on PRODUIT from GPERS2 DB-MAIN - Techniques SQL avancées ( FUNDP) 1.8
1. Rappel des notions de bases de données 1.2 Le langage SQL F. Les prédicats Un prédicat (ou contrainte) est une condition que les données doivent vérifier après chaque modification (statement / commit). check de colonne ou de table : évalué pour toute modification de la colonne ou de la table; assertion : évaluée pour toute modification de la base de données. create assertion A_COMDET check(select * from COMMANDE where NCOM not in (select NCOM from DETAIL)) > 0) alter table DETAIL add constraint C_QCOM check(qcom > 0) alter table CLIENT add constraint C_SEXE check(sexe is null or SEXE in ('M','F')) alter table DETAIL add constraint C_Q check(qcom <= (select QSTOCK from PRODUIT where NPRO = DETAIL.NPRO)) Attention Certains SGBD n'admettent que des checks très rudimentaires, réduits à la ligne courante. DB-MAIN - Techniques SQL avancées ( FUNDP) 1.9
1. Rappel des notions de bases de données 1.2 Le langage SQL G. Les Triggers Trigger = mécanisme constitué d'une section de code accompagnée des conditions qui entraînent son exécution. Forme générale E-C-A (event-condition-action) : before/after E when C begin A end si un événement E (insert, delete, update) survient, et si la condition C est satisfaite, alors exécuter l'action A soit avant (before) soit après (after) l'événement E. Exemple 1 modification automatique de la valeur de CAT lorsque l'état du compte d'un client descend en dessous d'un certain seuil create trigger MAJ_CLI before update of COMPTE on CLIENT for each row when (new.compte < -10000) begin if old.cat = 'B2' then new.cat := 'B1'; end if; if old.cat = 'C2' then new.cat := 'C1'; end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 1.10
1. Rappel des notions de bases de données 1.2 Le langage SQL Exemple 2 Le trigger suivant protège les produits contre toute augmentation de prix qui dépasserait 5%. Les états old et new sont renommés pour des raisons de lisibilité. create trigger MAJOR before update of PRIX on PRODUIT referencing old as ANCIEN new as NOUVEAU for each row begin if NOUVEAU.PRIX > (ANCIEN.PRIX * 1.05) then abort(); end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 1.11
1. Rappel des notions de bases de données 1.2 Le langage SQL H. Les Stored procedures Séquence d'instructions SQL précompilées dont l'exécution peut être demandée par un utilisateur, un programme d'application, un trigger ou une autre procédure. Stockée dans la base de données; peut être considérée comme une ressource unique et commune pour toutes les applications, évitant une duplication de code. Permet aussi de définir des comportements complexes, en particulier en ce qui concerne l'intégrité des données. Exemple La procédure ci-dessous supprime la ligne de détail dont elle reçoit le numéro de commande et le numéro de produit. Si cette ligne est la dernière de sa commande, cette dernière est également supprimée. create procedure MAJ_CMD (in COM char(4), in PRO char(5)) begin delete from DETAIL where NCOM = COM and NPRO = PRO; if (select count(*) from DETAIL where NCOM = COM) = 0 then delete from COMMANDE where NCOM = COM end if; end; On pourra invoquer cette procédure par la commande suivante : CALL MAJ_CMD(182,'PA60') DB-MAIN - Techniques SQL avancées ( FUNDP) 1.12
1. Rappel des notions de bases de données 1.3 La programmation d'application A. Extraction de données (résultat mono-ligne) exec SQL begin declare section end-exec. NOM char(12) ADR char(20) LOC char(12) NUM char(4) exec SQL end declare section end-exec. read NUM exec SQL select NOM,ADRESSE,LOCALITE into :NOM,:ADR,:LOC from CLIENT where NCLI = :NUM; end-exec. display NOM, ADR, LOC DB-MAIN - Techniques SQL avancées ( FUNDP) 1.13
1. Rappel des notions de bases de données 1.3 La programmation d'application B. Extraction de données (résultat multi-ligne) Analogie : déclarer le fichier F... ouvrir F lire un enregistrement dans F tant que la lecture a réussi faire traiter l enregistrement lire un enregistrement dans F fin fermer F Mécanisme SQL... exec SQL declare CURCLI cursor for select NCLI, NOM, ADRESSE from CLIENT where LOCALITE = :LOC; end-exec.... LOC := 'Toulouse' exec SQL open CURCLI end-exec exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec. while SQLCODE = 0 do <traiter le client> exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec. endwhile; exec SQL close CURCLI end-exec.... DB-MAIN - Techniques SQL avancées ( FUNDP) 1.14
1. Rappel des notions de bases de données 1.3 La programmation d'application C. Modification des données Classique ou positioned update... exec SQL declare CURCLI cursor for select... from CLIENT where LOCALITE = :LOC; end-exec.... LOC := 'Toulouse' exec SQL open CURCLI end-exec exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec. while SQLCODE = 0 do exec SQL update CLIENT set CAT = 'A1' where current of CURCLI end-exec exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec. endwhile; exec SQL close CURCLI end-exec.... D. SQL dynamique DB-MAIN - Techniques SQL avancées ( FUNDP) 1.15
1. Rappel des notions de bases de données 1.4 Architectures des systèmes applicatifs Application monolithique interface utilisateur traitement accès aux données fichier. Client/serveur à 2 couches (2 tiers) client serveur de données interface utilisateur traitement SGBD BDR Client/serveur à 3 couches (3 tiers) client serveur d' application serveur de données interface utilisateur application SGBD BDR DB-MAIN - Techniques SQL avancées ( FUNDP) 1.16
1. Rappel des notions de bases de données 1.4 Architectures des systèmes applicatifs Types de serveurs Serveur SQL de base Intégrité assurée pour les contraintes d'intégrité déclarées super-fat client présentation et contrôle dynamique des objets objets de gestion validation des données super-thin server gestion des données BDR Serveur SQL avec validation Intégrité assurée pour toutes les contraintes d'intégrité fat client présentation et contrôle dynamique des objets objets de gestion thin server validation des données gestion des données BDR DB-MAIN - Techniques SQL avancées ( FUNDP) 1.17
1. Rappel des notions de bases de données 1.4 Architectures des systèmes applicatifs Serveur SQL d'objets passifs Le serveur gère des objets complexes (passive business objects) thin client présentation et contrôle dynamique des objets fat server objets de gestion validation des données gestion des données BDR Serveur SQL d'objets actifs Le serveur gère des objets complexes autonomes (active business objects) super-thin client présentation et contrôle super-fat server dynamique des objets objets de gestion validation des données gestion des données BDR DB-MAIN - Techniques SQL avancées ( FUNDP) 1.18
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 2.1 Notion(s) d'intégrité 2.2 Responsabilité des contraintes d'intégrité 2.3 Etats de correction d'une base de données 2.4 Sources de corruption d'une base de données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
2. Intégrité des données 2.1 Notion(s) d'intégrité A. Définitions Intégrité (théorique) Etat d'une base de données qui constitue une image fidèle du domaine d'application. Remarque : impossible à vérifier. Intégrité (pratique) Etat d'une base de données qui respecte un ensemble de contraintes d'intégrité. Remarque : techniquement vérifiable; simulation imparfaite de l'intégrité théorique. Contrainte d'intégrité Propriété formelle que les données et leur évolution doivent respecter à défaut de quoi elles sont réputées corrompues. Contrainte d'intégrité statique Propriété formelle que les données doivent respecter à tout instant (ou à des instants prédéfinis), à défaut de quoi elles sont réputées corrompues. Définit les états valides. Contrainte d'intégrité dynamique Ensemble des transitions d'état d'un objet considérées comme valides. Toute transition non valide partant d'un état valide conduit à un état corrompu des données, même si cet état respecte toutes les contraintes d'intégrité statiques. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.2
2. Intégrité des données 2.1 Notion(s) d'intégrité B. Exemples de contraintes statiques (niveau conceptuel) Les contraintes de base CLIENT Num Client Nom Adresse Numéro Voie Ville Téléphone[0-5] 0-N passe 1-1 0-N FOURNISSEUR Num Fourn Raison Sociale Adresse administrative Contact[0-1] 0-N COMMANDE Num Commande Date Montant[0-1] 1-20 assignée Quantité 0-N propose Prix Délai 0-N PRODUIT Code Produit Libellé Prix Qté Stock Les domaines Les valeurs d'un attribut doivent respecter la définition du domaine de l'attribut. Les identifiants Contrainte d'unicité. Les contraintes de cardinalité (attributs et rôles) Le nombre de valeurs d'attribut par entité et le nombre d'associations par entité doivent respecter les bornes mini et maxi. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.3
2. Intégrité des données 2.1 Notion(s) d'intégrité Les contraintes de domaine Restreignent les valeurs d'un domaine valeurs permises : sexe = {'M','m','F','f'} intervalle : date = [1/1/1940-31/12/2019] règle de formation des valeurs : code = [A-Z][0-9]* valeurs exclues DB-MAIN - Techniques SQL avancées ( FUNDP) 2.4
2. Intégrité des données 2.1 Notion(s) d'intégrité Les contraintes d'existence Définissent les conditions de présence de composants facultatifs d'une entité (attributs et rôles). Contrainte de coexistence PROJET Code-projet Titre id: Code-projet 0-N affecté 0-1 EMPLOYE Matricule Nom Date-affectation[0-1] Nom-conjoint[0-1] Date-mariage[0-1] id: Matricule coex: affecté.projet Date-affectation coex: Nom-conjoint Date-mariage Si un employé est affecté à un projet, alors il a une date d'engagement, et réciproquement. Contrainte d'exclusivité PROJET Code-projet Titre id: Code-projet 0-N affecté 0-1 EMPLOYE Matricule Nom Date-affectation[0-1] Nom-conjoint[0-1] Date-mariage[0-1] Salaire-mensuel[0-1] Salaire-horaire[0-1] id: Matricule coex: affecté.projet Date-affectation coex: Nom-conjoint Date-mariage excl: Salaire-mensuel Salaire-horaire excl: affecté.projet Nom-conjoint Un employé peut avoir un salaire horaire ou un salaire mensuel, mais pas les deux. Les employés mariés ne peuvent être affectés à un projet. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.5
2. Intégrité des données Contrainte au-moins-un CANDIDAT NumInscription Nom Diplôme-technique[0-1] Expérience-industrielle[0-1] id:numinscription at-lst-1:diplôme-technique Expérience-industrielle Un candidat doit avoir obtenu un diplôme technique ou pouvoir justifier d'une expérience industrielle (ou les deux). Contrainte exactement-un (= au-moins-un + exclusivité) EMPLOYE Matricule Nom Salaire-mensuel[0-1] Salaire-horaire[0-1] id: Matricule exact-1: Salaire-mensuel Salaire-horaire Un employé doit avoir un salaire horaire ou un salaire mensuel, mais pas les deux. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.6
2. Intégrité des données 2.1 Notion(s) d'intégrité Les contraintes d'inclusion de rôles FOURNISSEUR Num Fourn Raison Sociale Adresse administrative Contact[0-1] 0-N 0-N COMMANDE Num Commande Date Montant[0-1] 1-20 assignée Quantité incl: FOURNISSEUR PRODUIT propose Prix Délai gr:fournisseur PRODUIT 0-N 0-N PRODUIT Code Produit Libellé Prix Qté Stock On ne peut assigner le produit d'une commande à un fournisseur que si celui-ci propose ce produit. assignée[fournisseur, PRODUIT] propose[fournisseur, PRODUIT] CLUB Nom Ville id:nom ECOLE Nom Adresse id:nom 0-N affilié 0-1 JOUEUR Matricule Nom id: Matricule incl:inscrit.ecole gr:affilié.club 0-1 0-N inscrit Un joueur ne peut s'inscrire dans une école de perfectionnement que s'il est affilié à un club sportif. inscrit[joueur] affilié[joueur] DB-MAIN - Techniques SQL avancées ( FUNDP) 2.7
2. Intégrité des données Les contraintes d'exclusion de rôles ENTREPRISE 0-N possède r-ex:entreprise IMMEUBLE 0-N IMMEUBLE 0-N loue r-ex:entreprise IMMEUBLE 0-N Une entreprise qui loue un immeuble n'en est pas propriétaire, et inversement. possède[entreprise,immeuble] loue[entreprise,immeuble] = Les contraintes intra-objet Définissent des propriétés organisant les composants d'une entité ou d'une association. COMMANDE NCom Date Qté-commandée Qté-livrée id: NCom Qté-livrée Qté-commandée FACTURE NFact Montant Date-envoi Date-paiement id: NFact Date-envoi < Date-paiement DB-MAIN - Techniques SQL avancées ( FUNDP) 2.8
2. Intégrité des données 2.1 Notion(s) d'intégrité Redondances structurelles Les contraintes de redondance CLIENT NumCli Nom Adresse Compte id: NumCli 0-N passe 1-1 COMMANDE NumCom Date Client Adresse id: NumCom COMMANDE.Client = COMMANDE.passe.CLIENT.NumCli COMMANDE.Adresse = COMMANDE.passe.CLIENT.Adresse Dépendances fonctionnelles PROJET Code-projet Nom 0-N occupé Proportion 0-N EMPLOYE Matricule Nom 0-N DEPARTEMENT Nom Localisation EXPEDITION Numéro Date Transporteur Code-cli Nom-cli Adresse-cli Montant id: Numéro occupé: EMPLOYE DEPARTEMENT EXPEDITION: Code-cli Nom-cli, Adresse-cli DB-MAIN - Techniques SQL avancées ( FUNDP) 2.9
2. Intégrité des données 2.1 Notion(s) d'intégrité C. Exemple de contraintes dynamiques PERSONNE Matricule Nom Adresse EtatCivil id: Matricule Transitions valides pour l'attribut EtatCivil "C" "M" "M" "S","D","V" "D" "M" "V" "M" "S" "D","V","M" DB-MAIN - Techniques SQL avancées ( FUNDP) 2.10
2. Intégrité des données 2.2 Responsabilité des contraintes d'intégrité Système de gestion de données (SGF / SGBD) Le SGD peut explicitement prendre en charge, par déclaration DDL, certaines contraintes d'intégrité. domaines de valeurs colonnes obligatoires identifiants char(10), decimal(10,2), date not null primary key unique unique index clés étrangères foreign key... references... Serveur de données Des mécanismes génériques du SGD permettent de programmer la validation de certaines contraintes d'intégrité. prédicats triggers stored procedures check create assertion create trigger create procedure Le code applicatif Les programmes d'application ou l'interface utilisateur incluent du code de validation des contraintes. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.11
2. Intégrité des données 2.3 Etats de correction d'une base de données Dernier état correct La base de données contient toutes les données introduites et elles seulement. Etat correct L'un des états corrects, mais pas nécessairement le dernier. Etat correct possible Ensemble de parties correctes. N'a pas nécessairement existé dans le passé (parties asynchrones). Pertes possibles. Etat valide statiquement Respecte les contraintes d'intégrité statiques. Etat valide dynamiquement Obtenu à partir d'une chaîne de changements d'état vérifiant les contraintes d'intégrité dynamiques. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.12
2. Intégrité des données 2.4 Sources de corruption d'une base de données Introduction de données valides mais incorrectes Les données introduites respectent les contraintes d'intégrité statiques et dynamiques mais ne correspondent pas à l'état ou au comportement du domaine d'application. Exemple : erreur de montant déposé sur un compte (4500 au lieu de 5400). Introduction de données invalides Les données introduites ne respectent pas les contraintes d'intégrité statiques et dynamiques. Exemple : introduction d'une date de facturation antérieure à la date de commande. Fausse manoeuvre de l'utilisateur Le comportement de l'utilisateur conduit à la corruption de certaines données. Exemples : oubli de lancer une procédure de validation des données, exécution d'une fonction ou d'un programme inadéquats, interruption prématurée d'une séquence de saisie, abandon d'un poste de saisie (syndrôme de la pause café), etc. Erreur technique dans le logiciel applicatif Une situation imprévue provoque un incident d'exécution du programme d'application. Exemple : division par zéro, dépassement de longueur de champ, etc. DB-MAIN - Techniques SQL avancées ( FUNDP) 2.13
2. Intégrité des données 2.4 Sources de corruption d'une base de données Erreur logique dans le logiciel applicatif La logique de l'application traduit mal les spécifications initiales. Le comportement du programme est erroné, bien que techniquement correct (pas d'incident). Erreur dans un logiciel système Comportement erroné, inadéquat ou arrêt prématuré d'un composant système : SGBD, système d'exploitation, gestionnaire d'écran, gestionnaire de communication, etc. Attaques ciblées, fraudes, malveillance Des individus, utilisateurs réguliers ou occasionnels, tentent de modifier frauduleusement ou de détruire les données. Attaques anonymes, virus Des individus, via des logiciels d'attaque, recherchent des sites présentant des failles de protection, et s'y installent en cherchant à détruire ou corrompre les fichiers accessibles. Interactions parasites entre processus concurrents Un processus de traitement est perturbé par un autre processus concurrent. Exemple : deux processus A et B lisent la même donnée, la modifient, puis la réécrivent dans la base de données. Seule la dernière modification sera prise en compte (problème de la mise à jour perdue). DB-MAIN - Techniques SQL avancées ( FUNDP) 2.14
2. Intégrité des données 2.4 Sources de corruption d'une base de données Incident matériel Panne ou comportement inadéquat d'un composant matériel : mémoire centrale, bus, processeur, carte contrôleur, terminal, modem, ligne, serveur distant, etc. Perte du support Le support de la base de données (en général disque magnétique) subit un incident qui le rend irrécupérable. Les données qu'il contenait sont perdues. Destruction des installations Catastrophes naturelles (tremblements de terre, inondations, foudre) ou d'origine humaine (incendies, chutes d'avion, attentats). DB-MAIN - Techniques SQL avancées ( FUNDP) 2.15
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 3.1 Définition et propriétés 3.2 Les primitives 3.3 Définition d'une transaction 3.4 Comportement de la transaction 3.5 Structures de transaction 3.6 Transactions hiérarchiques 3.7 Transactions et triggers 3.8 Transactions et intégrité 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
3. Transactions 3.1 Définition et propriétés Transaction Section d'un programme qui constitue une unité logique de traitement du point de vue des accès à la base de données. Exemples : enregistrer un client, enregistrer une commande et ses détails, transférer un montant d'un compte vers un autre, etc. Une transaction vérifie, relativement à la base de données, les quatre propriétés A.C.I.D : Atomicity (atomicité) : l'ensemble des instructions de la section sont exécutées complètement (en cas de succès), ou pas du tout (en cas d'incident), mais jamais partiellement; Consistency (cohérence) : si la BD est cohérente avant la transaction, elle le sera à la sortie de celle-ci (respect des contraintes d'intégrité); Isolation (indépendance) : les interactions entre la transaction et la base de données s'effectuent comme si la transaction était seule à travailler sur la BD (pas d'interférences nuisibles avec les autres programmes); Durability (permanence) : si la transaction s'est terminée correctement, les modifications faites dans la BD sont garanties permanentes (sauf modifications via d'autres transactions), quels que soient les incidents ultérieurs. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.2
3. Transactions 3.2 Les primitives Une instruction ou requête primitive (unique) jouit des propriétés ACID (garantie contractuelle du SGBD). Exemple : CLIENT NCli Nom Adresse Localite Cat Compte id: NCli COMMANDE NCli NCom Date id: NCom ref: NCli DETAIL NPro NCom QCom id: NCom NPro ref: NCom ref: NPro PRODUIT NPro Libelle Prix QStock id: NPro delete from CLIENT where NCLI = 'C400' Cette requête induira en général un nombre important de modifications dans la base de données : suppression d'une ligne de CLIENT suppression de plusieurs lignes de COMMANDE suppression de plusieurs lignes de DETAIL modification des index de CLIENT modification des index de COMMANDE modification des index de DETAIL ajout de données dans les journaux modification de la structure des fichiers (p. ex. restitution espace libre) DB-MAIN - Techniques SQL avancées ( FUNDP) 3.3
3. Transactions 3.2 Les primitives Atomicité Cohérence l'ensemble de ces actions est réalisé complètement ou pas du tout; si les données sont cohérentes au départ, elles le sont à l'arrivée (intégrité référentielle par exemple) Indépendance l'exécution de primitives d'autres processus n'interfère pas avec l'exécution de cette primitive (les lignes de COMMANDE et DETAIL touchées sont protégées, de même que les régions des index modifiées); Durabilité si la primitive se termine normalement, les lignes supprimées le restent, quel que soient les incidents qui pourront se produire ultérieurement. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.4
3. Transactions 3.2 Les primitives Problème La granularité des primitives peut être trop fine pour certaines opérations sur les données. Exemple : transfert d'une somme d'un compte vers un autre = 2 primitives... (si incident: OK) update du compte source : - 1000 F... (si incident: incohérence) update du compte destination : + 1000 F... (si incident: OK) Solution... (si incident: OK) primitive ( update du compte source : - 1000 F... update du compte destination : + 1000 F)... (si incident: OK) transaction = super primitive construite par le programmeur DB-MAIN - Techniques SQL avancées ( FUNDP) 3.5
3. Transactions 3.3 Définition d'une transaction Une transaction est construite à l'aide de 3 primitives offertes par le SGBD Attention ouverture d'une transaction begin-transaction clôture avec confirmation commit-transaction clôture avec annulation abort-transaction Certains SGBD n'offrent pas de begin-transaction explicite. Le fonctionnement obéit alors aux règles suivantes. 1. Une transaction est démarrée lors de l'exécution de la première opération de modification. 2. Un commit-transaction démarre automatiquement la transaction suivante. 3. Lors de la déconnexion de la base de données (fin du travail), un abort-transaction est effectué automatiquement. Principe : le SGD garantit les propriétés ACID lorsqu'il exécute une primitive; si le programmeur désire que cette propriété s'applique à une séquence de d'instructions, il doit en faire une transaction. préparation begin-transaction acquisition des données modification des données si erreur abort-transaction et sortie commit-transaction suite du traitement DB-MAIN - Techniques SQL avancées ( FUNDP) 3.6
3. Transactions 3.3 Définition d'une transaction Exemple simple : transfert d'une somme d'un compte vers un autre COMPTE NumCpte Client Montant id: NumCpte get('comptes et somme :',N1,N2,Somme); begin-transaction read(compte(numcpte=n1),cpt1); if record-not-found then goto SUITE; CPT1.Montant := CPT1.Montant - Somme; update(compte,cpt1); read(compte(numcpte=n2),cpt2); if record-not-found then goto SUITE; CPT2.Montant := CPT2.Montant + Somme; update(compte,cpt2); commit-transaction SUITE... DB-MAIN - Techniques SQL avancées ( FUNDP) 3.7
3. Transactions 3.4 Comportement de la transaction Un incident grave affecte la base de données et le programme. transaction incident état BD état programme s1 actif update... begin-transaction... update... update... commit-transaction... action... s1 s2 s1 actif actif tué transaction incident état BD état programme s1 actif update... begin-transaction... update... update... commit-transaction... action... s1 s2 s3 s3 s3 s4 s3 actif actif actif actif actif tué DB-MAIN - Techniques SQL avancées ( FUNDP) 3.8
3. Transactions 3.4 Comportement de la transaction Un incident grave affecte la base de données et mais pas le programme. Celui-ci garde la main et peut réagir transaction incident état BD état programme s1 actif update... begin-transaction... update... update if error then abort-transaction goto L endif... commit-transaction... action... L:... s1 s2 s1 s1 actif actif actif goto L poursuite DB-MAIN - Techniques SQL avancées ( FUNDP) 3.9
3. Transactions 3.5 Structures de transaction D'une manière générale, une transaction possède la structure fonctionnelle suivante : pour chaque unité de données à traiter (par exemple compte source et compte destination), 1. on saisit les données, ce qui nécessite en général un dialogue avec l'utilisateur, 2. on les valide, notamment via des accès à la base de données 3. on modifie la base de données selon les données acquises et validées. préparation acquisition données 1 validation données 1 mise à jour enregistrement(s) 1... acquisition données n validation données n mise à jour enregistrement(s) n clôture Il peut y correspondre plusieurs organisations techniques fonctionnellement équivalentes, mais de comportements différents selon l'environnement. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.10
3. Transactions 3.5 Structures de transaction Exemple de séquence traitant une unité de donnée Introduire une commande en vérifiant qu'il existe une offre pour le produit commandé. /* acquisition donnees */ get('introduire numéro de client, numéro produit et quantité',c,p,q); /* validation donnees */ select count(*) into :N1 from CLIENT where NCli=:C; select count(*) into :N2 from OFFRE where NPro=:P; if N1 = 0 or N2 = 0 goto ERREUR_SAISIE; /* mise a jour BD */ NC := next_numcom; insert into COMMANDE values (:NC,:C,:P,:Q); DB-MAIN - Techniques SQL avancées ( FUNDP) 3.11
3. Transactions 3.5 Structures de transaction On considère la séquence simplifiée suivante (n = 2, préparation et clôture ignorée). On ignore le traitement des erreurs. acquisition données 1 validation données 1 mise à jour enregistrement(s) 1 acquisition données 2 validation données 2 mise à jour enregistrement(s) 2 Structure 1 La composition suit l'ordre intuitif des opérations : pour chaque (lot d') enregistrement(s) à traiter, les données sont saisies, validées puis enregistrées. begin-transaction acquisition données 1 validation données 1 mise à jour enregistrement(s) 1 acquisition données 2 validation données 2 mise à jour enregistrement(s) 2 commit-transaction Problèmes : (1) certaines erreurs d'acquisition peuvent n'être détectées qu'après mise à jour de la base de données, (2) l'acquisition est effectuée dans la transaction (problème potentiel de la pause café). DB-MAIN - Techniques SQL avancées ( FUNDP) 3.12
3. Transactions 3.5 Structures de transaction Structure 2 Les actions d'acquisition et de validation sont regroupées avant les mises à jour. On n'entreprend les mises à jour que lorsque toutes les données ont été saisies et validées. begin-transaction acquisition données 1 validation données 1 acquisition données 2 validation données 2 mise à jour enregistrement(s) 1 mise à jour enregistrement(s) 2 commit-transaction Problème : l'acquisition est effectuée dans la transaction (pause café). DB-MAIN - Techniques SQL avancées ( FUNDP) 3.13
3. Transactions 3.5 Structures de transaction Structure 3 Les données externes sont entièrement saisies avant leur validation. La structure de la transaction est fonction du type d'opération plutôt que des objets traités. begin-transaction acquisition données 1 acquisition données 2 validation données 1 validation données 2 mise à jour enregistrement(s) 1 mise à jour enregistrement(s) 2 commit-transaction Problèmes : (1) l'acquisition est effectuée dans la transaction (pause café), (2) les opérations de saisie et de validation sont désynchronisées. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.14
3. Transactions 3.5 Structures de transaction Structure 4 Les données externes sont entièrement saisies avant la transaction. Il n'y donc plus de problème de blocage dû à l'utilisateur (pause café). Tous les accès (lecture et maj) relatifs à la base de données restent encapsulés dans la transaction. acquisition données 1 acquisition données 2 begin-transaction validation données 1 validation données 2 mise à jour enregistrement(s) 1 mise à jour enregistrement(s) 2 commit-transaction Problème : les opérations de saisie et de validation sont désynchronisées. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.15
3. Transactions 3.5 Structures de transaction Structure 5 Les données externes sont entièrement saisies et validées avant la transaction. Il est possible d'entrelacer acquisition et validation en vue d'une meilleure dynamique des dialogues. Seules les modifications de la base de données sont encapsulés dans la transaction. acquisition données 1 acquisition données 2 validation données 1 validation données 2 begin-transaction mise à jour enregistrement(s) 1 mise à jour enregistrement(s) 2 commit-transaction Problème : il n'est pas certain que les données validées avant la transaction seront encore valides dans la transaction (problème d'interférences parasites avec d'autres processus). DB-MAIN - Techniques SQL avancées ( FUNDP) 3.16
3. Transactions 3.5 Structures de transaction Structure 6 Les données externes sont entièrement saisies et validées avant la transaction. Cependant, les données qui dépendent de l'état de la base de données sont recontrôlées dans la transaction afin de vérifier que cet état n'a pas changé. acquisition données 1 acquisition données 2 validation données 1 validation données 2 begin-transaction contrôle données 1 contrôle données 2 mise à jour enregistrement(s) 1 mise à jour enregistrement(s) 2 commit-transaction Problème : il s'agit de la structure la plus complexe et la plus consommatrice de ressources. Techniquement, deux autres protocoles peuvent donner le même résultat : 1. le verrouillage des enregistrements de la BD lors de la validation hors transaction, 2. l'ouverture de deux transactions en parallèle, l'une en consultation et l'autre en mise à jour (Oracle). DB-MAIN - Techniques SQL avancées ( FUNDP) 3.17
3. Transactions 3.5 Structures de transaction Application de la structure 6 /* acquisition et validation des donnees */ OK := false; while not OK begin get('introduire numéro de client, numéro de produit et quantité',c,p,q); select count(*) into :N1 from CLIENT where NCli=:C; if N1 = 0 then ERREUR_CLIENT; select count(*) into :N2 from OFFRE where NPro=:P; if N2 = 0 then ERREUR_PRODUIT; if N1>0 and N2>0 then OK := true; endwhile; begin-transaction /* controle des donnees */ select count(*) into :N1 from CLIENT where NCli=:C; select count(*) into :N2 from OFFRE where NPro=:P; if N1=0 or N2=0 then BD_INSTABLE; abort-transaction; goto SUITE endif; /* mise a jour BD */ NC := next_numcom; insert into COMMANDE values (:NC,:C,:P,:Q); commit-transaction... SUITE:... DB-MAIN - Techniques SQL avancées ( FUNDP) 3.18
3. Transactions 3.6 Transactions hiérarchiques Une transaction constitue une super-primitive. Lors de l'exécution d'un programme, les transactions se déroulent séquentiellement, mais jamais en parallèle. Il n'est donc pas possible de définir une transaction comme formée de sous-transactions plus élémentaires. Pas de structure hiérarchique possible. La structure des transactions ne correspond pas à la structure hiérarchique d'un programme. Faiblesse d'architecture logicielle = pas de réutilisation, pas d'indépendance des modules (boite noire). Une procédure doit connaître le comportement transactionnel de ses procédures appelées et de ses procédures appelantes. Structure d'un programme hiérarchisé Programme P: call A call B Modules niv. 2 A: call C B: call D call E Modules niv. 3 C: D: E: = primitive de modification des données DB-MAIN - Techniques SQL avancées ( FUNDP) 3.19
3. Transactions 3.6 Transactions hiérarchiques Structure transactionnelle plate begin transaction commit transaction transaction unique P: call A call B A: call C B: call D call E C: D: E: Structure transactionnelle hiérarchisée (futur?) begin transaction commit transaction Transact. niv. 1 P: Transact. niv. 2 A: B: Transact. niv. 3 C: D: E: DB-MAIN - Techniques SQL avancées ( FUNDP) 3.20
3. Transactions 3.6 Transactions hiérarchiques Les palliatifs A. Savepoint / Rollback Savepoint : primitive du SGBD qui sauve (fictivement!) l'état courant de la base de données. Rollback : primitive du SGBD qui restaure l'état de la base de données sauvé lors d'un savepoint. état BD begin transaction savepoint rollback commit transaction Un seul ou plusieurs savepoints actifs simultanément? Un seul savepoint à la fois : permet de simuler 2 niveaux de transaction. Plusieurs savepoints en même temps : permet de simuler un nombre quelconque de niveaux de transaction. Aucun automatisme. programmeur. Gestion entièrement à la charge du DB-MAIN - Techniques SQL avancées ( FUNDP) 3.21
3. Transactions 3.6 Transactions hiérarchiques B. Multiprocessing Démarrage d'un processus parallèle (thread ou independent process) comportant une transaction. C. Ouverture de plusieurs connexions simultanées Chaque connexion à la base de données permet d'ouvrir une transaction. Transactions indépendantes mais synchronisation via les données. D. Autonomous transactions (Oracle 8) Toute procédure appelée dans une transaction T0 peut lancer une transaction autonome T1. Celle-ci est exécutée en parallèle de la transaction principale T0. si T1 échoue, la transaction T0 peut poursuivre son exécution ou décider se saborder (abort-transaction); si T1 se termine, et si T0 échoue par la suite, l'effet de T1 est permanent. Exemple (Note d'application Oracle) T0 gère une session d'achat électronique et enregistre le contenu du panier. L'acheteur peut confirmer son achat (commit T0) ou l'annuler (abort T0). Dès l'ouverture de T0, on mémorise les coordonnées de l'acheteur (transaction T1). Ces données sont maintenues quelle que soit l'issue de T0. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.22
3. Transactions 3.7 Transactions et triggers Quel est le statut d'un trigger déclenché par une opération interne à une transaction? 1. Que devient la transaction si le trigger échoue? 2. L'effet d'un trigger est-il conservé lorsque la transaction échoue? Type 1. L'exécution du corps du trigger s'insère dans la transaction à son point d'activation. Type 2. L'exécution du corps trigger constitue une transaction autonome à son point d'activation. Type 3. L'exécution du corps trigger s'ajoute à la fin de la transaction et fait partie de celle-ci. Type 4. L'exécution du corps trigger constitue une transaction autonome intervenant après la transaction. ExempleOracle interdit les primitives de contrôle de transaction dans le corps d'un trigger Type 1. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.23
3. Transactions 3.8 Transactions et intégrité Une transaction doit garantir la cohérence de la base de données (ACID). Plus précisément, si la base de données est cohérente à l'entrée de la transaction, alors, au sortir de la transaction, soit la base est encore dans cet état (abort, incident), soit elle se trouve dans un nouvel état (commit) qui respecte les contraintes d'intégrité qui ont été déclarées en SQL : primary key, unique, foreign key, not null, check. Qu'en est-il des contraintes qui ne sont satisfaites que suite à une séquence de plusieurs primitives? Exemples 1. Transfert d'un compte vers un autre (contrainte : la somme des comptes est invariante). Après la modification du premier compte, la BD est incohérente. 2. Introduction de commandes non vides (contrainte : tout détail doit être associé à une commande et toute commande doit avoir au moins un détail). Après l'introduction du premier enregistrement, la BD est incohérente (commande sans détail ou détail sans commande). Si l'expression des contraintes est implicite (non déclarée) : pas de problème, le SGBD ignore les états intermédiaires incohérents. Si l'expression des contraintes est implicite sauf pour l'une d'entre elles : pas de problème, il suffit de terminer la transaction par l'opération qui met en cause cette contrainte. Si l'expression d'au moins deux contraintes est explicite : problème, car aucun ordonnancement des primitives ne satisfait le SGBD dans tous les états intermédiaires. DB-MAIN - Techniques SQL avancées ( FUNDP) 3.24
3. Transactions 3.8 Transactions et intégrité Exemple : pas de Commande sans Détail(s) et pas de Détail sans Commande Expression 1 : aucune contrainte n'a été déclarée. create table COMMANDE(NCOM integer not null primary key, DATECOM date not null, NCLI integer not null); create table DETAIL(NCOM integer not null, NPRO integer not null, QCOM decimal(8,2) not null, primary key (NCOM,QCOM)) Tout ordonnancement est acceptable begin-transaction insert into COMMANDE values(:c,:d,:l) insert into DETAIL values(:c,:p,:q) commit-transaction DB-MAIN - Techniques SQL avancées ( FUNDP) 3.25
3. Transactions 3.8 Transactions et intégrité Expression 2 : seule une contrainte est déclarée (foreign key), l'autre restant implicite. create table COMMANDE(NCOM integer not null primary key, DATECOM date not null, NCLI integer not null); create table DETAIL(NCOM integer not null, NPRO integer not null, QCOM decimal(8,2) not null, primary key (NCOM,QCOM) foreign key (NCOM) references COMMANDE) Un seul ordonnancement est acceptable : begin-transaction insert into COMMANDE values(:c,:d,:l) insert into DETAIL values(:c,:p,:q) commit-transaction L'autre provoquant une erreur, et donc un incident annulant la transaction : begin-transaction insert into DETAIL values(:c,:p,:q) erreur référentielle insert into COMMANDE values(:c,:d,:l) commit-transaction DB-MAIN - Techniques SQL avancées ( FUNDP) 3.26
3. Transactions 3.8 Transactions et intégrité Expression 3 : les deux contraintes sont déclarées. create table COMMANDE(NCOM integer not null primary key, DATECOM date not null, NCLI integer not null, check(ncom in select NCOM from DETAIL)); create table DETAIL(NCOM integer not null, NPRO integer not null, QCOM decimal(8,2) not null, primary key (NCOM,QCOM) foreign key (NCOM) references COMMANDE) Aucun ordonnancement n'est acceptable : begin-transaction insert into COMMANDE values(:c,:d,:l) erreur de check insert into DETAIL values(:c,:p,:q) commit-transaction begin-transaction insert into DETAIL values(:c,:p,:q) erreur référentielle insert into COMMANDE values(:c,:d,:l) commit-transaction DB-MAIN - Techniques SQL avancées ( FUNDP) 3.27
3. Transactions 3.8 Transactions et intégrité Solution : débrayer la vérification des contraintes. create table COMMANDE(NCOM integer not null primary key, DATECOM date not null, NCLI integer not null, constraint COM_in_DET check(ncom in (select NCOM from DETAIL)) deferrable initially immediate); create table DETAIL(NCOM integer not null, NPRO integer not null, QCOM decimal(8,2) not null, primary key (NCOM,QCOM) constraint DET_in_COM foreign key (NCOM) references COMMANDE deferrable initially immediate) Sauf ordre contraire dans la transaction, la vérification des contraintes déclarées sera d'office (initially) reportée (deferrable) au commit. begin-transaction set constraint COM_in_DET deferred insert into COMMANDE values(:c,:d,:l) pas de vérification insert into DETAIL values(:c,:p,:q) vérification commit-transaction vérification de COM_in_DET DB-MAIN - Techniques SQL avancées ( FUNDP) 3.28
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 4.1 Principes 4.2 Principes de la gestion des tampons 4.3 Sauvegarde (backup) 4.4 Journal (log) 4.5 Reprise suite à un incident grave 4.6 Reprise suite à un incident léger 4.7 Protocoles de gestion de la BD et des journaux 5. Régulation de la concurrence 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
4. Protection contre les incidents 4.1 Principe Incident = événement fortuit ou intentionnel pouvant affecter l'intégrité de la base de données. Il est possible de prévenir certains types d'incident. En toute généralité, il est indispensable de pouvoir réparer des données corrompues suite à un incident. Les propriétés A(tomicité) et D(urabilité) d'une transaction relèvent de la protection contre les incidents. Atomicité En cas d'incident au sein de la transaction, la base de données est remise dans l'état du début de la transaction. Les modifications déjà réalisées doivent être défaites (rollback). Durabilité En cas d'incident après la clôture de la transaction, les données, même corrompues, doivent être remises au moins dans l'état où elles étaient au sortir de la transaction. Protection assurée par la disponibilité de deux fichiers annexes : la sauvegarde (backup) le journal (log) DB-MAIN - Techniques SQL avancées ( FUNDP) 4.2
4. Protection contre les incidents 4.2 Principes de la gestion des tampons Observation Temps de transfert mémoire centrale mémoire centrale : Temps de transfert disque mémoire centrale: Rapport : 1,5x10-5, soit 150.000 10-7 sec 1,5x10-2 sec Tampon (buffer) ou mémoire cache Espace en mémoire rapide (en général mémoire centrale) dans lequel sont rangées des données issues d' (ou destinées à) une mémoire plus lente. Est généralement constitué de cadres pouvant contenir chacun une page de la BD. Principe Eviter les accès au disque en conservant dans un tampon une quantité importante de données. Avec un peu de chance, les données demandées sont dans le tampon, ce qui évite de faire des accès au disque. la donnée réclamée est dans le tampon coût = 0,1 µsec tampon disque PA la donnée demandée n'est pas dans le tampon coût = 15.000 µsec DB-MAIN - Techniques SQL avancées ( FUNDP) 4.3
4. Protection contre les incidents 4.2 Principes de la gestion des tampons PA variable du programme abcdefg01230 échange d'enregistrements SGBD tampon du SGBD abcdefg01230 échange de pages SE tampon du SE échange de secteurs contrôleur cache du contrôleur échange de pistes et de secteurs disque décomposé en secteurs DB-MAIN - Techniques SQL avancées ( FUNDP) 4.4
4. Protection contre les incidents Principes 4.2 Principes de la gestion des tampons Lorsqu'un enregistrement est demandé par le PA, le gestionnaire le recherche dans le tampon. S'il n'y est pas, il lit la page sur disque, la place dans un cadre du tampon et livre l'enregistrement au programme. Problème : que faire s'il n'y a pas de cadre libre? Lorsqu'il doit écrire un enregistrement sur disque, le gestionnaire le range dans sa page (après l'avoir relue sur disque et introduite dans le tampon si nécessaire). La page n'est pas recopiée sur disque avant que cela ne soit nécessaire. Le programme d'application demande la lecture de l'enregistrement R 1. le SGBD détermine la page P dans laquelle se trouve R 2. Deux cas peuvent se présenter : 2.1 P se trouve dans le tampon, dans le cadre (emplacement) C : 2.2 P ne se trouve pas dans le tampon : 2.2.1 Le SGBD recherche un cadre libre dans le tampon 2.2.2 Deux cas peuvent se présenter : 2.2.2.1 Un cadre libre C est trouvé 2.2.2.2 Tous les cadres sont occupés : le SGBD recherche le cadre C dont le contenu n'a plus été utilisé (copié, modifié) depuis le plus long temps. Si le contenu de C a été modifié, il est recopié dans la mémoire secondaire. C est alors considéré comme libre (politique LRU simplifiée : least recently used) 2.2.3 La page P est lue dans la mémoire secondaire et une copie est rangée dans le cadre C 3. le SGBD recherche l'enregistrement R dans le cadre C et en transfère une copie dans la variable du programme DB-MAIN - Techniques SQL avancées ( FUNDP) 4.5
4. Protection contre les incidents 4.2 Principes de la gestion des tampons Le programme d'application demande la modification, création ou suppression de l'enregistrement R 1. le SGD détermine la page P dans laquelle se trouve (ou se trouvera) R 2. Deux cas peuvent se présenter : 2.1 P se trouve dans le tampon, dans le cadre C : 2.2 P ne se trouve pas dans le tampon : 2.2.1 Le SGBD recherche un cadre libre dans le tampon 2.2.2 Deux cas peuvent se présenter : 2.2.2.1 Un cadre libre C est trouvé 2.2.2.2 Tous les cadres sont occupés Le SGBD recherche le cadre C dont le contenu n'a plus été utilisé (copié, modifié) depuis le plus longtemps. Si le contenu de C a été modifié, il est recopié dans la mémoire secondaire. 2.2.3 La page P est lue dans la mémoire secondaire et une copie est rangée dans le cadre C 3. Le SGD effectue la modification dans le contenu du cadre C. 4. Le contenu du cadre C ne sera recopié dans la mémoire secondaire que dans les situations suivantes : - le cadre C doit être libéré (politique LRU), - on demande la fermeture du fichier (ou de la BD), - le programme décide de vider le tampon (= flush), - à la fin d'une transaction (réellement ou virtuellement). Le SGBD peut appliquer une politique plus complexe qui diminue encore le nombre de transferts vers la mémoire secondaire tout en garantissant la permanence des modifications en cas d'incident détruisant le contenu du tampon. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.6
4. Protection contre les incidents 4.2 Principes de la gestion des tampons tampon disque Observations 1. Les données qui sont dans le tampon sont généralement plus récentes que celles de la base de données. 2. Les données qui sont dans la mémoire secondaire sont généralement incohérentes. 3. L'état courant de la base de données est constitué du contenu de la mémoire secondaire et du contenu du tampon. 4. En cas d'incident entraînant la perte du contenu ou du contrôle de la mémoire centrale, la base de données en mémoire secondaire est corrompue. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.7
4. Protection contre les incidents 4.3 Sauvegarde (backup) Copie complète ou partielle de la base de données prise à un instant de référence. Copie complète Généralement compactée et stockée sur un support sûr. Le plus souvent off-line (cartouche). Parfois sur disque on-line (pour rapidité de reprise). Avantage : on dispose d'une version prête à l'emploi. Inconvénient : temps de la prise de copie. Copie partielle ou incrémentale Ne reprend que les parties (enregistrements, pages) ayant été modifiées depuis la dernière sauvegarde. Suppose l'existence d'une copie complète initiale. Avantage : temps de la prise de copie réduit. Inconvénient : pas de sauvegarde complète récente. Doit être reconstituée par application des incréments successifs à la copie complète initiale. Compromis : réactualisation progressive de la copie complète lors des moments creux ou sur une machine isolée. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.8
4. Protection contre les incidents 4.3 Journal (log) Fichier dans lequel sont consignées toutes les modification effectuées dans la base de données, ainsi que l'historique des transactions. Les modifications sont représentées par une copie (image) des données (enregistrement ou page) avant et après l'opération. Journal des images avant Contient la copie des pages avant leur modification. Permet de défaire (undo) des modifications qui ne se sont pas terminées correctement. Ce journal est en général assez court, car il ne concerne en principe que les transactions non encore terminées. Journal des images après Contient la copie des pages après leur modification. Permet de refaire (redo) des modifications qui ne se sont pas terminées correctement. Ce journal peut être très volumineux (plusieurs GB) car il concerne toutes les mises à jour réalisées depuis la dernière sauvegarde. Journal mixte Contient les copies des pages avant et après leur modification. Permet d'assurer tous les types de reprise. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.9
4. Protection contre les incidents 4.3 Journal (log) Checkpoint Point de synchronisation entre la base de données et le journal; les tampons de la base de données et du journal sont réécrits sur disque. Déclenché à intervalle régulier ou après N opérations. Entre 2 checkpoints, les états de la BD et du journal sur disque peuvent être mutuellement incohérents. Composition du journal Chaque transaction est identifiée par un code (généralement l'instant de sa commande de début). Un journal est formé d'enregistrements de 4 types, tous préfixés d'une estampille temporelle (timestamp) représentant l'instant de son écriture dans le journal : type 1 commandes de transaction : timestamp + code de la transaction + begin, commit ou abort type 2 image avant : timestamp + code de la transaction + copie d'une page qui va être modifiée type 3 image après : timestamp + code de la transaction + copie d'une page qui a été modifiée type 4 checkpoint : timestamp + code du checkpoint + liste des codes des transactions en cours. Le journal peut aussi contenir diverses informations complémentaires ainsi que des structures d'optimisation d'accès (chaînage par transaction, adresse du dernier checkpoint, adresse du dernier enregistrement, etc). Paradoxe : un fichier en écriture est en général considéré comme corrompu après une panne. Or un journal est surtout utile dans de telles conditions. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.10
4. Protection contre les incidents 4.4 Reprise suite à un incident grave La base de données est gravement déteriorée, voire inutilisable. Technique de reprise : 1. récupérer la dernière sauvegarde, 2. réappliquer (redo) des images après enregistrées dans le journal depuis la prise de cette sauvegarde, 3. seules les images concernant les transactions clôturées sont réappliquées. Optimisation : le journal est parcouru à l'envers de manière à n'appliquer que la dernière version de chaque page, et à repérer aisément les transactions clôturées. = reprise à froid DB-MAIN - Techniques SQL avancées ( FUNDP) 4.11
4. Protection contre les incidents 4.5 Reprise suite à un incident léger La base de données est localement déteriorée suite à la non terminaison de transactions ou à l'écriture de données incorrectes. Schéma temporel d'un incident start checkpoint incident T1 T2 α β T3 α β T4 α T5 α Correction (à chaud ou après redémarrage) Type de transaction état correction T1 T1 permanente T2 α permanent, β incertain undo(β); redo(β) T3 α permanent, β incomplet undo(t3) T4 T4 incertain undo(t4); redo(t4) T5 T5 incomplète undo(t5) DB-MAIN - Techniques SQL avancées ( FUNDP) 4.12
4. Protection contre les incidents 4.6 Protocoles de gestion de la BD et des journaux Scénario d'une modification 1. écrire image avant dans le (tampon du) journal 2. modifier (le tampon de) la BD 3. écrire image après dans le (tampon du) journal (en cas d'incident entre 1 et 3, le journal a priorité et permet le retour en arrière de la BD) Scénario du commit d'une transaction T 1. réécrire les données du tampon modifiées par T dans la BD 2. réécrire les données du tampon modifiées par T dans le journal (en cas d'incident entre 1 et 2, le journal a priorité et permet la réapplication des MAJ) Scénario d'un checkpoint 1. réécrire les données du tampon dans le journal 2. réécrire les données du tampon dans la BD 3. écrire le checkpoint dans le journal DB-MAIN - Techniques SQL avancées ( FUNDP) 4.13
4. Protection contre les incidents 4.6 Protocoles de gestion de la BD et des journaux Remarque Si les incidents (et donc les roll-backs) sont peu fréquents, on peut adopter le scénario minimum suivant, plus économique encore : 1. au checkpoint, les tampons de la BD et du journal sont réécrits sur disque, 2. au commit de T, seuls les cadres du tampon du journal relatifs à T sont réécrits sur disque. DB-MAIN - Techniques SQL avancées ( FUNDP) 4.14
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 5.1 Principes 5.2 Trois problèmes de concurrence 5.3 Sérialisabilité d'un ensemble de transactions 5.4 Techniques de régulation 5.5 Techniques de verrouillage 5.6 Le problème de l'interblocage 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
5. Régulation de la concurrence 5.1 Principes Concurrence = il est possible que plusieurs transactions accèdent simultanément à la base de données. Ces transactions sont concurrentes dès qu'elles utilisent les mêmes données. Si parmi les transactions concurrentes une au moins modifie les données, alors des interférences nuisibles peuvent affecter l'exécution de ces transactions. Deux types de risques : 1. Corruption des données. 2. Perception erronée des données. La propriété I(solation) relève de la régulation de la concurrence. Isolation Chaque transaction se comporte comme si elle était seule à travailler sur la base de données. Or, cette propriété est loin d'être garantie! DB-MAIN - Techniques SQL avancées ( FUNDP) 5.2
5. Régulation de la concurrence 5.2 Trois problèmes de concurrence A. La mise à jour perdue programme P1 états successifs de la BD programme P2 R read(nc='123') 123 1200 R read(nc='123') R.SOMME R.SOMME-300 R.SOMME R.SOMME+50 update(r) 123 900 123 1250 update(r) L'état correct devrait être : 123 950 La seconde mise à jour a écrasé la première. En raison d'une interférence nuisible entre les deux programmes, la première modification a été perdue. = Lost update problem DB-MAIN - Techniques SQL avancées ( FUNDP) 5.3
5. Régulation de la concurrence 5.2 Trois problèmes de concurrence B. Accès à des données instables transaction T1 états successifs de la BD transaction T2 begin-transaction R read(nc='123') 123 1200 R.SOMME R.SOMME+100 update(r) abort commit-transaction 123 1300 123 1200 begin-transaction R read(nc='123') R.SOMME R.SOMME+30 123 1330 update(r) commit-transaction L'état correct devrait être : 123 1230 La seconde transaction a utilisé des données non confirmées de la première transaction. = Dirty read or Uncommited dependency problem. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.4
5. Régulation de la concurrence 5.2 Trois problèmes de concurrence C. Incohérence statistique programme P1 états successifs de la BD transaction T2 S total des SOMMES S 0 S 0 R readfirst 1000 S S + R.SOMME R readnext 4000 S S + R.SOMME R readnext 5200 S S + R.SOMME R readnext 5500 S S + R.SOMME R readnext 6600 S S + R.SOMME R readnext 6800 S S + R.SOMME R readnext 7300 S S + R.SOMME stop 121 1000 122 3000 122 2500 123 1200 124 300 125 600 125 1100 126 200 126 500 transférer 500 F du compte 122 vers le compte 125 begin-transaction R read(nc='122') R.SOMME R.SOMME-500 update(r) R read(nc='125') R.SOMME R.SOMME+500 update(r) commit-transaction La somme correcte devrait être 6800 au lieu de 7300. Le programme de totalisation a compté deux fois la somme transférée. La transaction a modifié l'ensemble des données dont le programme calcule une statistique. = Inconsistent analysis or Unrepeatable read problem. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.5
5. Régulation de la concurrence 5.2 Trois problèmes de concurrence D. Conclusions : interférences nuisibles entre processus Un processus ne peut modifier des données qu'un autre processus est en train de modifier. Un processus ne peut accéder à des données instables, c'est à dire modifiées par une transaction qui n'a pas encore confirmé ces modifications. Un processus ne peut modifier une collection de données dont un autre processus analyse l'état. Un processus doit pouvoir obtenir la protection des données qu'il modifie, et des données qu'il consulte. Comment répondre à ces besoins sans effort excessif de la part du programmeur? par des techniques d'ordonnancement de transactions concurrentes. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.6
5. Régulation de la concurrence 5.3 Sérialisabilité d'un ensemble de transactions Question : comment ordonnancer l'exécution de transactions concurrentes de manière à éviter les interférences nuisibles? Définitions 1 On considère un ensemble E de transactions {T1, T2, T3} dont le déroulement se traduit par l'exécution de primitives de manipulation de données : T1 = <p 11 ;p 12 ;...;p 1n > T2 = <p 21 ;p 22 ;...;p 2m > T3 = <p 31 ;p 32 ;...;p 3p > Une exécution X 1 de E apparaît comme une séquence quelconque des primitives exécutées lors du déroulement des transactions de E. X 1 <p 21 ;p 11 ;p 12 ;p 31 ;p 22 ;p 32 ;...;p 3p ;...;p 1n ;...;p 2m > Dans une exécution séquentielle de E, les transactions se déroulent l'une après l'autre; une seule transaction s'exécute complètement avant qu'une autre démarre. X 2 <T2;T1;T3 > X 2 <p 21 ;p 22 ;...;p 2m ;p 11 ;p 12 ;...;p 1n ;p 31 ;p 32 ;...;p 3p > Une exécution non séquentielle est dite entrelacée. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.7
5. Régulation de la concurrence 5.3 Sérialisabilité d'un ensemble de transactions Observation : une exécution séquentielle n'entraîne aucune interférence nuisible. Mais : Remarque : pour des raisons de performance, il est indispensable d'admettre l'exécution en parallèle des transactions. on admet que les transactions sont indépendantes, c'est à dire que toutes les exécutions séquentielles sont acceptables. Définition 2 Une exécution entrelacée de E est sérialisable si elle est équivalente (a le même effet net) à une exécution séquentielle quelconque. Si deux transactions travaillent sur des données disjointes, toutes leurs exécutions entrelacées sont sérialisables. Le problème se pose lorsqu'une transaction modifie une donnée que l'autre cherche à lire ou modifier. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.8
5. Régulation de la concurrence 5.3 Sérialisabilité d'un ensemble de transactions Exemple 1 : schéma de la mise à jour perdue T1 = <p 11 ;p 12 > p 11 = R read(nc='123') p 12 = R.SOMME R.SOMME-300; update(r) T2 = <p 21 ;p 22 > p 21 = R read(nc='123') p 22 = R.SOMME R.SOMME+50; update(r) exécution résultat BD sérialisable? <p 11 ;p 12 ;p 21 ;p 22 > 950 oui (séquentielle) <p 11 ;p 21 ;p 12 ;p 22 > 1250 non <p 11 ;p 21 ;p 22 ;p 12 > 900 non <p 21 ;p 11 ;p 22 ;p 12 > 900 non <p 21 ;p 11 ;p 12 ;p 22 > 1250 non <p 21 ;p 22 ;p 11 ;p 12 > 950 oui (séquentielle) Il apparaît qu'aucune exécution entrelacée n'est sérialisable et que toutes les exécutions séquentielles produisent le même résultat. DB-MAIN - Techniques SQL avancées ( FUNDP) 5.9
5. Régulation de la concurrence 5.3 Sérialisabilité d'un ensemble de transactions Exemple 2 T1 = <p 11 ;p 12 > p 11 = update COMPTE set SOMME=SOMME-250 where NC='122' p 12 = update COMPTE set SOMME=SOMME+250 where NC='125' T2 = <p 21 ;p 22 > p 21 = update COMPTE set SOMME=SOMME*1.1 where NC='122' p 22 = update COMPTE set SOMME=SOMME*1.1 where NC='125' Etat initial de la BD : 122 500 125 2000 exécution résultat BD sérialisable? <p 11 ;p 12 ;p 21 ;p 22 > 275, 2475 oui (séquentielle) <p 11 ;p 21 ;p 12 ;p 22 > 275, 2475 oui <p 11 ;p 21 ;p 22 ;p 12 > 275, 2450 non <p 21 ;p 11 ;p 22 ;p 12 > 300, 2450 oui <p 21 ;p 11 ;p 12 ;p 22 > 300, 2475 non <p 21 ;p 22 ;p 11 ;p 12 > 300, 2450 oui (séquentielle) DB-MAIN - Techniques SQL avancées ( FUNDP) 5.10
5. Régulation de la concurrence 5.4 Techniques de régulation Comment contrôler la sérialisabilité des exécutions? Par évaluation en temps réel des états des transactions : beaucoup trop coûteux en calcul. En imposant des protocoles restrictifs qui ne produisent que des exécutions sérialisables : économiques mais peuvent limiter le parallélisme en excluant certaines exécutions sérialisables (techniques dites pessimistes). Deux techniques 1. ordonnancement par verrouillage 2. ordonnancement par estampillage DB-MAIN - Techniques SQL avancées ( FUNDP) 5.11
5. Régulation de la concurrence 5.5 Techniques de verrouillage Principes une transaction peut poser un verrou sur une donnée; il existe deux types de verrous : partagés et exclusifs; avant de lire une donnée D, la transaction doit obtenir un verrou partagé sur D; avant de modifier une donnée D, la transaction doit obtenir un verrou exclusif sur D; une transaction peut obtenir un verrou partagé sur une donnée D si celle-ci ne possède pas de verrou exclusif; une transaction peut obtenir un verrou exclusif sur une donnée D si celle-ci ne possède pas de verrous posés par d'autres transactions; DB-MAIN - Techniques SQL avancées ( FUNDP) 5.12
5. Régulation de la concurrence 5.5 Techniques de verrouillage Conséquences si une transaction a obtenu un verrou partagé sur D, une autre transaction peut lire D mais pas la modifier; si une transaction a obtenu un verrou exclusif sur D, une autre transaction ne peut ni lire ni modifier D. Pratiquement En général, une transaction qui se voit refuser un verrou est mise en attente (état wait) jusqu'à la libération de la donnée demandée. Il n'y pas de primitive explicite de demande de verrous. La demande est implicite lors de l'exécution de la primitive de mise à jour (select shared lock, update/insert/delete exclusive lock). Avant de modifier une données déjà lue, le verrou partagé doit être transformé en verrou exclusif (lock upgrade). Si une transaction lit une donnée qu'elle pourrait modifier par la suite, elle peut demander un verrou exclusif au moment de la lecture (p. ex. declare cursor for update.) La demande de libération d'un verrou est implicite : à la fin de l'exécution de la primitive (mais :... voir plus loin) DB-MAIN - Techniques SQL avancées ( FUNDP) 5.13
5. Régulation de la concurrence 5.5 Techniques de verrouillage Schéma d'une modification (avec lock upgrade) programme états successifs de la BD 123 1200 R read(nc='123') 123 1200 S-lock R.SOMME R.SOMME-300 update(r) 123 1200 X-lock 123 1200 update 123 900 unlock 123 900 DB-MAIN - Techniques SQL avancées ( FUNDP) 5.14
5. Régulation de la concurrence 5.5 Techniques de verrouillage Schéma d'une modification (avec exclusive read) programme états successifs de la BD 123 1200 R read/x(nc='123') 123 1200 X-lock R.SOMME R.SOMME-300 update(r) 123 900 123 900 unlock DB-MAIN - Techniques SQL avancées ( FUNDP) 5.15
5. Régulation de la concurrence 5.5 Techniques de verrouillage Exemple : révision du schéma de mise à jour perdue (avec exclusive read) programme P1 états successifs de la BD programme P2 R read/x(nc='123') R.SOMME R.SOMME-300 update(r) 123 1200 X-lock 123 1200 123 900 unlock 123 900 X-lock 123 900 R read/x(nc='123') wait wait wait wait wait R.SOMME R.SOMME+50 123 950 123 950 unlock update(r) DB-MAIN - Techniques SQL avancées ( FUNDP) 5.16
5. Régulation de la concurrence 5.5 Techniques de verrouillage Ces principes ne résolvent pas tous les problèmes, car ils permettent encore des exécutions non sérialisables et des lectures instables. Principe additionnel : verrouillage en 2 phases Une transaction doit être constituée de deux phases consécutives : une phase de croissance durant laquelle les verrous sont obtenus sans qu'aucun ne soit restitué; une phase de décroissance durant laquelle les verrous sont restitués sans qu'aucun autre verrou ne soit acquis. En d'autres termes, dès qu'un verrou est relâché, plus aucun verrou ne peut être demandé. Ce principe est appelé verrouillage en 2 phases, ou 2-phase locking. Implémentation la plus fréquente : Les verrous acquis durant l'exécution de la transaction ne sont restitués (unlock) qu'au moment de la clôture, c'est à dire au moment du commit ou de l'abort. Une transaction respectant le principe du 2-phase locking est sérialisable. Cependant, cette condition est suffisante (la sérialisabilité est garantie) mais pas nécessaire (d'autres scénarios moins stricts existent). DB-MAIN - Techniques SQL avancées ( FUNDP) 5.17
5. Régulation de la concurrence 5.6 Le problème de l'interblocage Le technique du verrouillage peut conduire au phénomène d'interblocage (ou verrou mortel, deadlock). transaction T1 états successifs de la BD transaction T2 R read/x(nc='123') 123 1200 123 1200 X-lock 734 900 734 900 X-lock R read/x(nc='734') S read/x(nc='734') wait wait wait wait wait wait S read/x(nc='123') wait wait wait wait wait DB-MAIN - Techniques SQL avancées ( FUNDP) 5.18
5. Régulation de la concurrence 5.6 Le problème de l'interblocage Origine de l'interblocage On considère le graphe d'attente qui décrit le fait que la transaction Ti attend la libération d'une données détenue par la transaction Tj : T i T j Il y a interblocage lorsque le graphe d'attente comporte un circuit. T1 attend la libération de 734 T 1 T 2 T2 attend la libération de 123 Comment traiter le problème de l'interblocage? Prévention (approche pessimiste) Interdire les situation qui pourraient conduire à un interblocage. Diminue le parallélisme. Rarement pratiqué. Correction (approche optimiste) Laisser les interblocages se produire, les détecter (en temps réel ou à intervalles réguliers) puis les résoudre. Technique : choisir une transaction appartenant à un circuit, la tuer (rollback), puis la redémarrer. Réclame un style de programmation particulier (état BD restauré, mais pas nécessairement les variables de la transaction, cfr Oracle). DB-MAIN - Techniques SQL avancées ( FUNDP) 5.19
5. Régulation de la concurrence 5.6 Le problème de l'interblocage programme P1 états successifs de la BD programme P2 R read/x(nc='123') 123 1200 123 1200 X-lock 734 900 734 900 X-lock R read/x(nc='734') S read/x(nc='734') wait wait S read/x(nc='734') commit détection interblocage 734 900 734 900 734 900 123 1200 unlock X-lock unlock S read/x(nc='123') wait rollback restart transaction R read/x(nc='734') S read/x(nc='123') etc DB-MAIN - Techniques SQL avancées ( FUNDP) 5.20
5. Régulation de la concurrence 3.12 Primitives et transactions Exemple complexe : enregistrement d'une commande Première version (naïve) begin-transaction get('numero du client',com.ncli); read(client(ncli=com.ncli),cli); if record-not-found then goto SUITE; get('donnees commande',com.ncom,com.date); create(commande,com); if ERROR then abort-transaction; goto ERREUR; endif; get('donnees detail',det.npro,det.qcom); while DET.NPro <> 0 do DET.NCom := COM.NCom; create(detail,det); read(produit(npro= DET.NPro),PRO); if record-not-found then abort-transaction; goto ERREUR; endif; get('donnees detail',det.npro,det.qcom); endwhile; commit-transaction;... ERREUR Problème : syndrôme de la pause café DB-MAIN - Techniques SQL avancées ( FUNDP) 5.21
5. Régulation de la concurrence 3.12 Primitives et transactions Exemple complexe : enregistrement d'une commande Deuxième version (moins naïve mais...) /* acquisition et validation des données */ /* CLIENT */ get('numero du client',com.ncli) read(client(ncli=com.ncli),cli) if record-not-found then goto ERREUR; /* COMMANDE */ get('donnees commande',com.ncom,com.date); read(commande(ncom=com.ncom),com); if record-found then goto ERREUR; /* DETAILS */ ND := 0; while ERR-DET = 0 do get('donnees detail',p,q); if P = 0 or ND = 100 then ERR-DET := 1; else read(produit(npro=det.npro),pro) if record-not-found then ERR-DET := 1; else ND := ND + 1; DET[ND].NPro := P; DET[ND].QCom := Q; endif; endif; endwhile; if ERR-DET > 0 go to ERREUR; /* creation de la commande */ begin-transaction create(commande,com); for I := 1 to ND DET.NCom := COM.NCom; DET.NPro := DET[I].NPro; DET.QCom := DET[I].QCom; DB-MAIN - Techniques SQL avancées ( FUNDP) 5.22
5. Régulation de la concurrence create(detail,det); endwhile commit-transaction... ERREUR Problème : possibilité d'interférences nuisibles avec les autres processus DB-MAIN - Techniques SQL avancées ( FUNDP) 5.23
5. Régulation de la concurrence 3.12 Primitives et transactions Exemple complexe : enregistrement d'une commande Troisième version (réaliste) /* acquisition et validation des données */ /* CLIENT */ get('numero du client',com.ncli) read(client(ncli=com.ncli),cli) if record-not-found then goto ERREUR; /* COMMANDE */ get('donnees commande',com.ncom,com.date); read(commande(ncom=com.ncom),com); if record-found then goto ERREUR; /* DETAILS */ ND := 0; while ERR-DET = 0 do get('donnees detail',p,q); if P = 0 or ND = 100 then ERR-DET := 1; else read(produit(npro=det.npro),pro) if record-not-found then ERR-DET := 1; else ND := ND + 1; DET[ND].NPro := P; DET[ND].QCom := Q; endif; endif; endwhile; if ERR-DET > 0 go to ERREUR; /* creation de la commande */ begin-transaction create(commande,com); if ERROR then begin abort-transaction goto ERREUR DB-MAIN - Techniques SQL avancées ( FUNDP) 5.24
5. Régulation de la concurrence endif for I := 1 to ND read(produit(npro= DET[I].NPro),PRO) if record-not-found then abort-transaction; goto ERREUR; endif; DET.NCom := COM.NCom; DET.NPro := DET[I].NPro; DET.QCom := DET[I].QCom; create(detail,det); if create-error then abort-transaction; goto ERREUR; endif; endwhile; commit-transaction;... ERREUR ======== get('numero du client',x) read(client(ncli=x),cli) if record-not-found then goto SUITE begin-transaction get('donnees commande',com.ncli,com.ncom,com.date) create(commande,com) get('donnees detail',det.npro,det.qcom) while DET.NPro <> 0 do begin DET.NCom := COM.NCom create(detail,det) read(produit(npro= DET.NPro),PRO) if record-not-found do begin abort-transaction goto SUITE endif get('donnees detail',det.npro,det.qcom) endwhile commit-transaction DB-MAIN - Techniques SQL avancées ( FUNDP) 5.25
5. Régulation de la concurrence SUITE.... DB-MAIN - Techniques SQL avancées ( FUNDP) 5.26
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 6.1 Organisation 6.2 Techniques natives 6.3 Prédicats 6.4 Views with check option 6.5 Langage procédural 6.6 Stored procedures 6.7 Triggers 7. La gestion de l'intégrité 8. Applications 9. Les interfaces ODBC et JDBC 10. Bibliographie
6. Les techniques SQL 6.1 Organisation Les techniques SQL Ce chapitre reprend les techniques qui permettent de traduire les caractéristiques d intégrité des données et de comportement des BD. - techniques natives : structures primitives des SGBD (identifiants primaire et secondaire, clé de référence et colonne obligatoire) ; - prédicats : checks et assertions assurant que les données respectent une condition de validation ; - views with check option : utilisation de vues restreintes par une condition pour la mise à jour des données ; - langage procédural : langage de programmation impératif comportant de nombreuses extensions ; - stored procedures : utilisation de procédures centralisées dans la BD pour la mise à jour des données ; - triggers : mécanisme de réaction automatique à la survenance d événements. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.2
6. Les techniques SQL 6.2 Techniques natives Définition : Les techniques natives sont les structures de validations (souvent) primitives offertes par les SGBD. Les techniques natives des SGBDR sont les suivantes : - primary key : identifiant primaire, - unique index : identifiant secondaire, - foreign key : intégrité référentielle, - not null : colonne obligatoire. A l heure actuelle, ces constructions de base sont offertes par la majorité des SGBD. Elles sont de plus implémentées de manière efficace. Sauf pour des raisons extrêmement rares (style de programmation, portabilité, ) on tentera d utiliser au maximum ces mécanismes. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.3
6. Les techniques SQL 6.2 Techniques natives Désactivation (ré-)activation : La création d une contrainte sur une table étant déjà garnie de valeurs ne sera acceptée par le SGBD qu à la condition qu aucune de celles-ci ne la viole. Si pour des raisons de performance, on décide de désactiver une contrainte, la règle précédente s applique lors de sa réactivation. Exemple : PERSONNEL NUMPERS NOM PRENOM NUM_SS 555256 Dupont Jules 12482134 349545 Durant 78845851 547945 Dupont Gérard 16483387 -- NUMPERS est un identifiant primaire alter table PERSONNEL add constraint ID_PERS primary key (NUMPERS); > OK -- NOM est un identifiant secondaire alter table PERSONNEL add constraint ID_NOM unique index (NOM); > KO (il existe 2 Dupont) -- NOM est obligatoire alter table PERSONNEL add constraint UN_NOM NOM not null; > OK DB-MAIN - Techniques SQL avancées ( FUNDP) 6.4
6. Les techniques SQL 6.2 Techniques natives -- PRENOM est obligatoire alter table PERSONNEL add constraint UN_PRENOM PRENOM not null; > KO (Durant n a pas de prénom) -- NUM_SS est un identifiant secondaire alter table PERSONNEL add constraint ID_NUM_SS unique index (NUM_SS); > OK DB-MAIN - Techniques SQL avancées ( FUNDP) 6.5
6. Les techniques SQL 6.3 Prédicats Définition : Types : Un prédicat est une propriété des données qui doit être vérifiée à chaque instant. Si une commande de DML viole le prédicat, cette commande est annulée et un message d erreur (exception) est généré. - check : prédicat portant (en général) sur une seule table : - check local : prédicat portant sur la ligne courante ; - check global : prédicat portant sur plusieurs lignes ; - assertion : prédicat en général multitable. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.6
6. Les techniques SQL 6.3 Prédicats Exemples : CLIENT NCLI NOM ADRESSE LOCALITE CAT[0-1] COMPTE id: NCLI COMMANDE NCOM NCLI DATECOM id: NCOM ref: NCLI DETAIL NCOM NPRO QCOM id: NCOM NPRO ref: NCOM ref: NPRO PRODUIT NPRO LIBELLE PRIX QSTOCK id: NPRO -- vérification de la catégorie des clients alter table CLIENT add constraint CHK_CAT check (CAT in ( B1, B2, C1, C2 )); -- interdiction d avoir un produit 25% plus cher -- que la moyenne alter table PRODUIT add constraint CHK_PRIX check (PRIX <= (select avg(prix) * 1.25 from PRODUIT)); -- simulation incomplète de l intégrité -- référentielle -- check alter table COMMANDE add constraint FK_NCLI check (NCLI in (select NCLI from CLIENT)); -- simulation de l intégrité référentielle -- assertion create assertion FK_NCLI check (not exists (select * from COMMANDE where NCLI not in (select NCLI from CLIENT))); DB-MAIN - Techniques SQL avancées ( FUNDP) 6.7
6. Les techniques SQL 6.3 Prédicats -- le montant d une commande ne peut dépasser -- 100.000 Euros create assertion check (not exists (select NCOM from DETAIL D, PRODUIT P where D.NPRO = P.NPRO group by NCOM having sum(qcom*prix) > 100000)); DB-MAIN - Techniques SQL avancées ( FUNDP) 6.8
6. Les techniques SQL 6.3 Prédicats Attention à la valeur NULL : Si le prédicat ne peut être évalué à cause d une valeur NULL, il n est pas invalidé. En effet, seule une évaluation à FALSE annule la commande DML. Exemple : l insertion d un client à catégorie nulle sera acceptée malgré le CHECK défini plus haut. En particulier, un prédicat n est jamais évalué à FALSE sur une table vide. Exemple : un check vérifiant que la somme des montants d une commande est supérieur à 1000 ne sera pas évalué à FALSE pour une table ne contenant aucune ligne. Variétés d implémentation des checks dans la norme SQL-92 : Chaque vendeur de SGBD interprète librement la norme SQL en ce qui concerne la commande check : - implémentation logique : accès aux données de la ligne courante. Un check étant une propriété qui doit être vérifiée à tout moment, il ne peut se baser que sur des données stables et non des données qui peuvent varier au cours du temps (typiquement une valeur agrégée calculée sur l ensemble des ligne d une table). = check local - implémentation laxiste : accès aux données de toutes les lignes de toutes les tables. Un check qui sera validé aujourd hui ne risque de ne plus l être demain pour la même opération. = check global DB-MAIN - Techniques SQL avancées ( FUNDP) 6.9
6. Les techniques SQL 6.3 Prédicats De plus, on préférera les assertions aux checks laxistes portant sur plusieurs tables. En effet, il faut généralement plusieurs checks pour avoir l équivalent d une assertion. Ces dernières sont donc plus claires et plus faciles à maintenir. Elles sont plus puissantes et permettent d implémenter des contraintes plus complexes que les checks (cf. : limitations des checks globaux). Validation des données : Les règles de validation des données sont les mêmes que pour les techniques natives. Les données existantes doivent respecter le prédicat. Si ce n est pas le cas, il n est pas crée ou activé. Limitation des checks globaux : Un check global n est pas un prédicat au sens mathématique du terme. En effet, ce genre de check est directionnel (la condition n est vérifiée que dans un seul sens). Exemple : le check suivant, sensé simuler l intégrité référentielle des commandes des clients est en fait incapable de réagir lors de la suppression d un client ou de la modification de son numéro. -- simulation de l intégrité référentielle - check alter table COMMANDE add constraint FK_NCLI check (NCLI in (select NCLI from CLIENT)); DB-MAIN - Techniques SQL avancées ( FUNDP) 6.10
6. Les techniques SQL 6.3 Prédicats Report de la vérification en fin de transaction : La plupart des SGBD offrent la possibilité de reporter la vérification des contraintes en fin de transaction. Cette technique offre les avantages suivants : - augmentation des performances : lors de longues transactions modifiant beaucoup de données, on n effectuera qu une seule fois les validations ; - déblocage de cercles vicieux : si plusieurs contraintes se bloquent mutuellement, le report de vérification en fin de transaction permet de sortir de cette situation. Performances : Il est important de se rendre compte du travail réalisé par le SGBD pour maintenir l intégrité des données via les prédicats sous peine d obtenir une baisse significative des performances. - check local : vérifications des données de la ligne insérée/modifiée. overhead négligeable - check global : exécution de requête parfois complexe. overhead dépendant de la complexité de la requête de validation - assertion : exécution de requête parfois complexe + maintenance d un diagramme de dépendances des objets concernés. overhead non négligeable qui influence plusieurs requêtes de DML DB-MAIN - Techniques SQL avancées ( FUNDP) 6.11
6. Les techniques SQL 6.4 Views with check option Définition : Une vue peut aussi servir de filtre à l introduction / modification de données. La clause with check option empêche les commandes DML d ajouter des lignes qui ne seraient pas sélectionnées par la vue et de modifier des lignes qui disparaîtraient ainsi de la vue. Les utilisateurs ont les droits d accès à la vue mais pas à la table. Exemples -- vérification de la catégorie des clients create view CLI_CAT as select * from CLIENT where CAT in ('B1','B2','C1','C2') or CAT is null with check option Remarque : Contrairement aux checks, il faut explicitement traiter le valeur nulle. -- interdiction d avoir un produit 25% plus cher que la moyenne create or replace view PRO_PRIX as select * from PRODUIT where PRIX <= (select avg(prix) * 1.25 from PRODUIT) with check option DB-MAIN - Techniques SQL avancées ( FUNDP) 6.12
6. Les techniques SQL 6.4 Views with check option Limitations Il n est pas toujours possible d insérer/modifier/supprimer des lignes via une vue. Il existe des limitations : - limitations logiques : - absence de l identifiant primaire, - absence de colonnes obligatoires, - présence de données dérivées dans le select, - présence de group by, union, except, intersect, distinct, - limitations additionnelles des SGBD : - vue multitable (Oracle, Informix, DB2, ), - condition de sélection comportant une sous-requête trop complexe (Oracle), - Une vue tombant sous le coup de ces limitations est dite non modifiable (non updatable). Une vue non modifiable with check option n a aucun intérêt. Propagation : with cascaded check option Si une vue with check option se base sur d autres vues with check option, la propagation de la vérification des contraintes est spécifiée en ajoutant le mot clé cascaded. Certains SGBD ne proposent pas cette option (Oracle, Informix, ). La vérification reste donc locale! DB-MAIN - Techniques SQL avancées ( FUNDP) 6.13
6. Les techniques SQL 6.4 Views with check option Attention - A la différence des checks, une vue with check option ne vérifie pas la condition sur les données déjà présentes lors de sa création. - Les objets utilisés dans la condition de sélection de la vue peuvent être modifiés sans vérification. Exemple : -- simulation de l intégrité référentielle create or replace view COM_FK as select * from COMMANDE where NCLI in (select NCLI from CLIENT) with check option; il faut une contrainte complémentaire (de quelque nature qu elle soit) pour propager/interdire la modification de NCLI de la table CLIENT. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.14
6. Les techniques SQL 6.4 Views with check option - Une condition de sélection trop complexe risque d être ignorée par le SGBD sans avertissement. Malheureusement, cette notion de complexité n est pas définie. Exemple : -- le montant d une commande ne peut dépasser 100.000 Euros create or replace view DET_MNT as select * from DETAIL D1 where 100000 >= (select sum(qcom * PRIX) from DETAIL D, PRODUIT P where D.NPRO = P.NPRO and D1.NCOM = D.NCOM group by NCOM) with check option; Ce check option est totalement ignoré par Oracle! Remarque : le group by se trouve dans une sous-requête et n empêche donc pas la vue d être modifiable. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.15
6. Les techniques SQL 6.5 Langage procédural Définition : La plupart des SGBD offrent des extensions procédurales. Le programmeur a alors ainsi la possibilité de mélanger des commandes déclaratives (SQL pur) et impératives (structures de contrôle). Malgré le fait que ces commandes peuvent généralement être introduites en interactif, elles montrent leur utilité lors de la rédaction de stored procedures. La rédaction de stored procedures pour un SGBD ne disposant pas d un tel langage force le programmeur à écrire des fonctions externes compilées pour le système hôte (ex : fonctions écrites en C++ compilées pour le serveur Windows NT). (Rem : il s agit de l approche inverse de l utilisation de l embedded SQL) Exemples - PL/SQL pour Oracle - SPL pour Informix - DB-MAIN - Techniques SQL avancées ( FUNDP) 6.16
6. Les techniques SQL 6.5 Langage procédural Exemple OPERATION OP_ID COMPTE CREDIT DEBIT id: OP_ID JOURNAL DATE_BAL SIGNE id: DATE_BAL declare SOLDE integer; SIGNE varchar(10); begin select sum(credit) sum(debit) into SOLDE from OPERATION; if (SOLDE < 0) then SIGNE := 'negatif'; else if (SOLDE > 0) then SIGNE := 'positif'; else SIGNE := 'zero'; end if; end if; insert into JOURNAL values (SYSDATE,SIGNE); end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.17
6. Les techniques SQL 6.5 Langage procédural Extensions - Variables : - Variables simples (INTEGER, CHAR, VARCHAR, DATE, ) - Variables structurées (RECORD), tableaux (TABLE) - Variables de type ligne (mytable%rowtype) - Structures de contrôle : - LOOP END LOOP - FOR END FOR - IF THEN ELSE - Gestion d erreurs : - Exception (TRY, RAISE, CATCH) - Gestion système : - Communication inter-process (PIPE, WAIT, ALERT, ) - Utilisation des périphériques (printer, fax, ligne EDI, ) - Exécution de processus externes sur le serveur - Divers : - package : encapsulation de plusieurs procédures (permet de cacher des procédures auxiliaires, utilisation de variables communes à plusieurs procédures, ) Remarques : - Les variables ne sont pas des objets stockés dans la BD! - Valeur non restaurée en cas de rollback - Valeur perdue en fin de session DB-MAIN - Techniques SQL avancées ( FUNDP) 6.18
6. Les techniques SQL 6.5 Langage procédural Gestion des exceptions Principe Lorsqu une erreur se produit, on ne la laisse pas arrêter le programme en cours d exécution. Problème : on ne dispose peut-être pas de toutes les informations pour traiter une erreur dans les quelques lignes de code qui suivent sa survenance. => exceptions : mécanisme de propagation et d interception des erreurs. Bonus : possibilité de centralisation du traitement des erreurs et limitation de dédoublage de code. Le fait d intercepter une erreur permet aussi de ne pas annuler toute une transaction. Exemple Lors d une jointure avec une table distante, un message d erreur est affiché en cas de time out : begin.. ṡelect EMPNUM, DEPNAME from DEPARTMENT@HOUSTON D, EMPLOYE E where D.DEPNUM = E.DEPNUM;... end; exception when TIMEOUT_ON_RESSOURCE DBMS_OUTPUT.PUT_LINE( 'CONNECTION TO HOUSTON TIMEOUT,' ' TRY AGAIN LATER'); end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.19
6. Les techniques SQL 6.5 Langage procédural Exceptions définies par l utilisateur Outre les exceptions systèmes, l utilisateur peut définir ses propres exceptions et bénéficier ainsi du mécanisme de propagation et d interception. Utilisation des exceptions prédéfinies Il est possible de générer volontairement les exceptions système. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.20
6. Les techniques SQL 6.6 Stored procedures Définition Une stored procedure est un ensemble d instructions SQL précompilées qui sont stockées dans la BD. Elle peut communiquer avec l entité appelante aux moyens de paramètres. Une procédure peut aussi contenir des extensions SQL. Caractéristiques - une procédure est compilée : l efficacité est accrue lors de l exécution car il n y a plus de parsing ni de vérification de la validité. De même, le plan d optimisation des requêtes est préétabli. - une procédure est stockée dans le SGBD : maintenance d un code centralisé plus facile. - une procédure peut avoir des privilèges différents de l utilisateur : une procédure avec les droits DBA peut être utilisée pour limiter l accès à certaines données. - une procédure peut faire plusieurs return (Informix), par exemple dans une boucle : une procédure peut retourner une table contenant des données résultant de calculs complexes. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.21
6. Les techniques SQL 6.6 Stored procedures Exemples : La procédure suivante est utilisée pour mettre à jour la table des bons clients de l entreprise. create procedure GEN_BON_CLI (out TOTAL : number) is begin delete from BON_CLI; insert into BON_CLI select * from CLIENT where COMPTE > 1000; select count(*) into TOTAL from BON_CLI; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.22
6. Les techniques SQL 6.6 Stored procedures La procédure suivante renvoie sous forme de table triée chronologiquement les numéros et les dates de commande d un client ainsi qu un numéro d ordre : create procedure GET_SORTED_COM (in CLI : COMMANDE.NCLI%type) returning integer, COMMANDE.NCOM%type, COMMANDE.DATECOM%type; is LCOUNT integer; COM COMMANDE.NCOM%type; DCOM COMMANDE.DATECOM%type; begin LCOUNT := 1; foreach select NCOM, DATECOM into COM, DCOM from COMMANDE where NCLI = CLI order by DATECOM; return LCOUNT, COM, DCOM with resume; LCOUNT = LCOUNT +1; end foreach; end GET_SORTED_COM; Pour exploiter les résultats de cette procédure, il faut utiliser un curseur. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.23
6. Les techniques SQL 6.7 Triggers Définition : Un trigger est un mécanisme primitif des BD actives. Il agit selon le principe événement-condition-action. Un trigger est attaché à une table. Principe : - en cas de survenance d un événement, - si la condition est respectée, - alors l action est exécutée. Typologie : On considère : - quatre types d événements : - insert, - delete, - update, - autre (horloge, calendrier, événement système, ). Ce type d événement n est cependant pas géré actuellement par les triggers. - deux moments d exécution : - before, - after. - deux niveaux de réaction : - for each row, - for each statement. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.24
6. Les techniques SQL 6.7 Triggers Ce qui correspond à douze types de triggers : insert triggers update triggers delete triggers BEFORE INSERT STMT BEFORE UPDATE STMT BEFORE DELETE STMT BEFORE INSERT ROW BEFORE UPDATE ROW BEFORE DELETE ROW AFTER INSERT ROW AFTER UPDATE ROW AFTER DELETE ROW AFTER INSERT STMT AFTER UPDATE STMT AFTER DELETE STMT Remarques : - On peut de plus restreindre le déclenchement des update triggers à la modification d une partie des colonnes d une table. - Un trigger peut réagir à plusieurs événements. - Certains SGBD proposent des triggers on commit et on rollback. - Il existe aussi des triggers instead of (voir plus loin). DB-MAIN - Techniques SQL avancées ( FUNDP) 6.25
6. Les techniques SQL 6.7 Triggers Exemples Le trigger suivant copie la valeur du compte d un client que l on supprime dans une autre table : CLIENT... COMPTE... PROFIT DATE_ENR MONTANT PERTE DATE_ENR MONTANT create trigger before delete on CLIENT for each row when (COMPTE!= 0) begin if COMPTE > 0 then insert into PROFIT values (DBMS_UTIL.SYSDATE, COMPTE); else insert into PERTE values (DBMS_UTIL.SYSDATE, COMPTE); end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.26
6. Les techniques SQL 6.7 Triggers Modèle d exécution : - Exécution de tous les triggers before statement - Boucle pour chaque ligne concernée par la commande SQL : - Exécution de tous les triggers before row - Lock de la ligne et vérification des contraintes d intégrité (les locks sont gardés jusqu'à la fin de la transaction) - Exécution de la commande SQL - Exécution de tous les triggers after row - Termine la vérification des contraintes d intégrité qui ont été reportées - Exécution de tous les triggers after statement Certains SGBD sont plus pauvres que d autres : - Oracle : tous - Informix : - before statement, - after row, - after statement ; - DB2 : tous sauf before statement ; - SQL Server : seulement statement triggers. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.27
6. Les techniques SQL Cas de base 6.7 Triggers Triggers réentrants tables en mutation Un trigger est réentrant si au moins une des actions qu il effectue porte sur la table sur laquelle il est défini. Ce type de trigger pose énormément de problèmes pour tous les SGBD. - risque de boucle infinie, - séquence des modifications quand plusieurs lignes sont concernées (quelle est la valeur des données en cours de modification?). Pour éviter que les triggers ne s appellent récursivement de manière infinie, il suffit de placer une condition d arrêt dans la partie condition. Ces triggers sont soumis à de nombreuses restrictions, qui varient d un SGBD à l autre. Le problème Une seule et même commande (statement) SQL peut concerner plusieurs lignes (rows). Exemple : update PERSONNEL set SALAIRE = SALAIRE * 1.20 where STATUT = 'cadre'; Cette commande modifiera le montant des salaires de tous les cadres. Il y a donc autant de lignes modifiées par cette unique commande qu il y a de cadres dans la table. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.28
6. Les techniques SQL 6.7 Triggers Considérons un trigger qui empêche qu un salaire soit supérieur à 150 % de la moyenne des salaires. Il comprend une commande de sélection portant sur l ensemble des lignes de la table : PERSONNEL NUMPERS NOM STATUT SALAIRE id: NUMPERS create trigger PERS_MAX_SAL_AUR after update of SALAIRE on PERSONNEL for each row declare MOY integer; begin select avg(salaire) INTO MOY from PERSONNEL; if (:NEW.SALAIRE > MOY * 1.50) then raise MAX_SAL; end if; end; Ce trigger est défini for each row (pour vérifier chaque modification de salaire) et after update (pour tenir compte de la nouvelle valeur du salaire dans la moyenne). Dans l exemple de mise à jour, ce trigger est donc déclenché autant de fois qu il y a de cadres dans la table. Etant donné qu en général, l ordre de modification des lignes est inconnu, les SGBD sont allergiques à ce genre de trigger dont l action n est pas déterministe et répétable dans le temps. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.29
6. Les techniques SQL 6.7 Triggers Exemple : On suppose que la table du personnel contient les trois lignes suivantes : PERSONNEL NUMPERS NOM STATUT SALAIRE 555256 Dupont cadre 120 349545 Durant cadre 200 547945 Goffin technicien 100 Dans la situation actuelle, la moyenne des salaires est de 140 et le maximum permis par la contrainte d intégrité est de 140 * 1.5, soit 210. Tous les membres du personnel respectent donc la règle du salaire maximum. Lors de l exécution de l update du salaire des cadres, deux situations sont possibles : augmentation de Dupont suivi de Durant ou, à l inverse, augmentation de Durant suivi de Dupont. 1. augmentation de Dupont suivi de Durant augmentation de salaire après moyenne maximum statut Dupont 144 148 222 O.K. Durant 240 161 242 O.K. Le trigger a accepté les modifications de salaire. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.30
6. Les techniques SQL 6.7 Triggers 2. augmentation de Durant suivi de Dupont augmentation de salaire après moyenne maximum statut Durant 240 153 230 K.O. Dupont opération annulée Le trigger annule l opération de mise à jour car le salaire de Durant ne respecte pas les conditions. En conclusion, le comportement de ce trigger n est pas déterministe. Comme toujours en programmation, un tel non déterminisme n est pas acceptable ni même souhaitable. C est pourquoi les SGBD proposent des mécanismes empêchant cette situation de survenir. Remarques 1. Ceci est aussi valable pour les insertions et les suppressions. 2. La vérification des salaires pourrait se faire par un after statement trigger. Le désavantage de cette technique est que le trigger vérifie alors le salaire de tous les employés (même ceux dont le salaire n a pas été modifié). Cette technique coûte très cher pour des tables contenant un grand nombre de lignes. Comportement des SGBD Suivant les SGBD, trois comportements sont possibles pour stabiliser ce problème : - laisser le programmeur se débrouiller (Informix), - montrer une image de la table telle qu avant ou après la commande (DB2), - interdiction d accéder à une table en cours de modification (Oracle (run-time error), Informix (compile-time error)). DB-MAIN - Techniques SQL avancées ( FUNDP) 6.31
6. Les techniques SQL 6.7 Triggers Pas de restriction Dans certains cas, Informix permet d accéder aux tables en cours de modification. C est alors au programmeur de s assurer que les actions qu il exécute sont indépendantes de l ordre des lignes. Utilisation d une image de la table avant ou après la commande (DB2) : Comme les sélections se font sur une image stable de la table en cours de modification, l ordre des mises à jour n a plus d importance. Dans notre exemple, la mise à jour sera donc acceptée car les sélections sur la table du personnel se font sur une image de la table après mise à jour. Ce comportement est simple mais peut induire en erreur le programmeur qui ne s y attend pas. Il peut en effet paraître bizarre que l on puisse connaître l état final d une table alors qu on est en train de la modifier. Interdiction d accéder à une table en cours de modification (Oracle, Informix) Ces SGBD vérifient que les triggers ne font pas d accès aux tables en cours de modification. Il existe deux types de vérification : - à la compilation : le SGBD interdit la compilation d un trigger non conforme (Informix). - à l exécution : lorsqu un trigger veut accéder à une table, le trigger vérifie qu elle n est pas en cours de modification (Oracle). Ces deux comportements, bien que semblables, ont des conséquences différentes sur la rédaction de triggers. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.32
6. Les techniques SQL 6.7 Triggers En particulier, Oracle permet à un trigger for each row d accéder à la table en cours de modification lors de la première ligne traitée. Ce n est qu à la seconde qu il génère un message d erreur. Ce comportement s explique par le fait que si une seule ligne est concernée par une commande, alors le résultat est totalement déterministe. Cette particularité est cependant à utiliser avec précaution : est-on sûr que toutes les commandes qui déclencheront ce trigger n impliqueront jamais qu une seule ligne? Et dans le futur? Technique Pour contourner ce problème, il faudra en général utiliser une technique qui demande le codage de trois triggers et d une structure de données persistantes (table SQL ou tableau en procedural language) : - T1 : before statement : initialisation des données persistantes ; - T2 : before ou after row : stockage des données nécessaires au traitement de la contrainte d intégrité dans la structure de données persistantes ; - T3 : application de la contrainte d intégrité avec, selon les cas, annulation de la commande déclencheuse ou correction automatique des données ; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.33
6. Les techniques SQL 6.7 Triggers Séquentiellement, le schéma d action de cette technique peut être représenté comme suit : Initialisation des variables (T1) Pour chaque ligne satisfaisant la condition : Stocker de l information (T2) (*) Appliquer l action de la commande (SGBD) Stocker de l information (T2) (*) Vérifier la C.I. ou correction des données (T3) (*) choisir une des deux options. Dans notre exemple, nous aurons besoin des trois triggers suivants et d un package implémentant une pile. -- Statement trigger before update : initialisation create trigger PERS_SAL_BUS before update of SALAIRE on PERSONNEL begin PERS_SAL_PKG.CLEAR; end; -- Row trigger after update : stocke les numpers create trigger PERS_SAL_AUR after update of SALAIRE on PERSONNEL for each row when (NEW.SALAIRE > OLD.SALAIRE) begin PERS_SAL_PKG.PUSH(:OLD.NUMPERS); end; -- Statement trigger after update : verification create trigger EMP_SAL_AUS after update of SALAIRE on EMPLOYE declare SAL, MAX integer; NUM EMPLOYE.NUMPERS%type; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.34
6. Les techniques SQL 6.7 Triggers begin select avg(salaire) * 1.5 into MAX from PERSONNEL; while PERS_SAL_PKG.MORE loop NUM := PERS_SAL_PKG.POP; select SALAIRE into SAL from PERSONNEL where NUMPERS = NUM; if (SAL > MAX) then raise MAX_SAL end if; end loop; end; Cas des delete en cascade Il n y a pas que les row triggers qui peuvent générer des erreurs de consultation de table en cours de modification. Cela peut arriver aussi pour un statement trigger si la table à laquelle il est accroché a une foreign key avec une option cascade. Exemple On désire implémenter le mode on delete set null qui n est pas repris par Oracle. Nous avons de nouveau une table du personnel mais cette fois, elle contient une colonne facultative qui indique le responsable d une personne. Il s agit d un numéro de personne. Si une personne est effacée, on désire que toutes les personnes dont il était responsable soient rendues indépendantes (mode on delete set null). PERSONNEL NUMPERS NOM DEPARTEMENT RESPONSABLE[0-1] id: NUMPERS ref: DEPARTEMENT DEPARTEMENT NUMDEP NOM LOCALISATION id: NUMDEP DB-MAIN - Techniques SQL avancées ( FUNDP) 6.35
6. Les techniques SQL 6.7 Triggers Bien qu ici l ordre des suppressions ne pose pas, d un point de vue logique, de problème, le SGBD verra quand même une table en mutation et refusera un row trigger contenant une instruction du type : update PERSONNEL set RESPONSABLE = NULL where RESPONSABLE = :OLD.NUMPERS; PERSONNEL NUMPERS NOM DEPARTEMENT RESPONSABLE 555256 Dupont R56 349545 Durant R12 458694 Josque N34 555256 894425 Knut J95 555256 547945 Goffin G56 349545 Pour implémenter la contrainte, nous avons de nouveau besoin de trois triggers : - T1 : before statement : initialisation des variables ; - T2 : before row : stocke les identifiants des lignes supprimées ; - T3 : after statement : remplace par null tous les responsables supprimés. Jusqu à présent, cette solution fonctionne parfaitement bien. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.36
6. Les techniques SQL 6.7 Triggers Supposons maintenant qu il existe une table des départements vers laquelle pointe la colonne département de la table personnel. On suppose de plus cette foreign key définie en mode delete cascade. DEPARTEMENT NUMDEP NOM LOCALISATION N24 Production Namur Z67 Administration Bruxelles R56 Marketing Gent J95 Produits de base Liège R12 Vente Gent Dès lors, si on supprime un département, on supprime tous ses employés. Les triggers assurant la contrainte d intégrité de mise à null du responsable sont donc déclenchés. On suppose que l on supprime tous les départements situés à Gent : delete from DEPARTEMENT where LOCALISATION = 'Gent'; L exécution de cette commande peut être schématisée comme suit : - Pour chaque département D localisé à Gent : - delete from PERSONNEL where DEPARTEMENT = D.NUMDEP; - Suppression du département D Si on remplace le delete par les actions effectuées, on obtient : DB-MAIN - Techniques SQL avancées ( FUNDP) 6.37
6. Les techniques SQL 6.7 Triggers - Pour chaque département D localisé à Gent : - Initialisation des variables (T1) - Pour chaque employé de département D : - Stockage de son identifiant (T2) - Suppression de la ligne de personnel - Remplacement par null de tous les responsables supprimés (T3) - Suppression du département D On remarque que pour le même statement (delete from departement ), les triggers T1 et T3 sont déclenchés autant de fois qu il y a de départements supprimés. Ils se comportent donc comme des row triggers. En effet, pour gérer le delete cascade, le SGBD génère automatiquement des sous-statements. Ces sous-statements sont malheureusement des statements à part entière (=> ils déclenchent les statement triggers). La solution présentée plus haut est donc incorrecte. Il faut prévoir le cas d un delete cascade (indicateur booléen). On rajoute deux triggers et on modifie les triggers T1 et T3 : - T0 : before statement sur département : met à vrai l indicateur et initialise les variables ; - T1 : before statement sur personnel : si l indicateur est faux alors il initialise les variables, sinon rien ; - T2 : before row sur personnel : stocke les identifiants des lignes supprimées ; - T3 : after statement sur personnel : si l indicateur est faux alors il remplace par null tous les responsables supprimés, sinon rien ; - T4 : after statement sur département : met l indicateur à faux et remplace par null tous les responsables supprimés. DB-MAIN - Techniques SQL avancées ( FUNDP) 6.38
6. Les techniques SQL 6.7 Triggers Résumé Trigger consultant la Mutation Remarques table déclenchante BEFORE INSERT STMT non BEFORE INSERT ROW possible mutation si plusieurs lignes AFTER INSERT ROW oui AFTER INSERT STMT non BEFORE UPDATE STMT non BEFORE UPDATE ROW oui AFTER UPDATE ROW oui AFTER UPDATE STMT non BEFORE DELETE STMT possible mutation si delete cascade BEFORE DELETE ROW oui AFTER DELETE ROW oui AFTER DELETE STMT possible idem Remarque : triggers stupides Le trigger suivant, émanant d un programmeur dont l esprit est entré en mutation à force de jouer avec des triggers, n est pas compilable en Informix mais s exécute sans erreur sous Oracle : create or replace trigger T_STUPID before update on T begin delete from T; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.39
6. Les techniques SQL 6.7 Triggers Triggers instead of Principe Le trigger instead of se substitue totalement au statement SQL. Actuellement, seul Oracle 8 permet ce type de trigger et uniquement sur des vues. Ce type de trigger est obligatoirement défini for each row (logique!). Exemple CLIENT NCLI... id: NCLI COMMANDE NCOM NCLI DATECOM id: NCOM ref: NCLI DETAIL NCOM NPRO QCOM id: NCOM NPRO ref: NCOM ref: NPRO PRODUIT NPRO... id: NPRO DET_COM NCOM NPRO QCOM NCLI DATECOM create view COM_DET as select C.NCOM, NCLI, DATECOM, NPRO, QCOM from COMMANDE C, DETAIL D where C.NCOM = D.NCOM; create or replace function COALESCE (a in number, b in number) return number is begin if a is not null then return a; else return b; end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.40
6. Les techniques SQL 6.7 Triggers create or replace trigger COM_DET_IUR instead of update on COM_DET begin update COMMANDE set NCOM = coalesce(:new.ncom,:old.ncom), NCLI = coalesce(:new.ncli,:old.ncli), DATECOM = coalesce(:new.datecom,:old.datecom) where NCOM = :old.ncom; update DETAIL set NCOM = coalesce(:new.ncom,:old.ncom), NPRO = coalesce(:new.npro,:old.npro), QCOM = coalesce(:new.qcom,:old.qcom) where NCOM = :old.ncom and NPRO = :old.npro; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 6.41
6. Les techniques SQL 6.7 Triggers Les trigger instead of, une solution pour les tables en mutation? En général, la réponse est non. En effet, si on considère qu un trigger instead of : - remplace un statement par un autre statement (le plus souvent) ; - est défini for each row ; alors on constate que les éventuels statement triggers définis sur la table de base risquent d être déclenchés for each row!! De plus, le problème de l ordre des modifications n est en général pas non plus éliminé. Il suffit de considérer le trigger instead of suivant qui s exécute sans problème mais donne un résultat non déterministe : T C1 C2 id: C1 TV C1 C2 create or replace trigger TV_IUR instead of update on TV declare X number; begin select avg(c2) into X from T; update T set C2 = :new.c2 * X where C1 = :old.c1; end; Remarque : Triggers et cursors : Les statement triggers sont déclenchés pour chaque update/delete positionné (via un curseur). DB-MAIN - Techniques SQL avancées ( FUNDP) 6.42
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. Gestion de l intégrité 7.1 Architectures de validation 7.2 Commentaires 7.3 Techniques natives 7.4 Prédicats 7.5 Triggers 7.6 Views with check option 7.7 Stored procedures 7.8 Modules d accès 7.9 Sections de code distribuées dans les programmes d application 7.10 Procédures de validation attachées aux écrans de saisie 7.11 Programme de validation avant chargement 7.12 Programme de validation après chargement 7.13 Comportement en cas de violation 7.14 Les objets à contraintes multiples 8. Domaines d application 9. Les interfaces ODBC et JDBC 10. Bibliographie
7. Gestion de l intégrité 7.1 Architectures de validation données brutes Programme de pré-validation données valides Programme de post-validation Chargeur Programme d'application Programme d'application Module d'accès Programme d'application Interface utilisateur Programme d'application accès protégé accès non protégé DB schema stored procedures views w. check option triggers check declared constructs DB data (les composants de validation sont indiqués en grisé) DB-MAIN - Techniques SQL avancées ( FUNDP) 7.2
7. Gestion de l intégrité 7.2 Commentaires Principe Le SGBD ne gère aucune contrainte d intégrité. Celles-ci sont présentes dans le code sous forme de commentaires constituant des directives pour l'utilisateur ou le programmeur. Exemple create table CLIENT ( NCLI char(4) not null, NOM char(12) not null, ADRESSE char(20) not null, LOCALITE char(12) not null, CAT char(2), COMPTE decimal(9,2) not null, -- contrainte non verifiee par le SGBD : -- primary key (NCLI) ); Evaluation L utilisation de commentaires pour gérer l intégrité est sans doute la plus simple à programmer mais n apporte aucune sécurité sur la validation des données. Cette technique n est recommandée que dans le cas où le programmeur est assuré que les données seront toujours valides. Avantage - technique la plus simple. Inconvénient - aucune gestion de l intégrité. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.3
7. Gestion de l intégrité Principe 7.3 Techniques natives La gestion de l intégrité se fait via les techniques natives des SGBDR (identifiants primaire et secondaire, clé étrangère, colonne obligatoire). Exemple alter table CLIENT add constraint ID_CLI primary key (NCLI); Evaluation La gestion de l intégrité est prise en charge par le SGBD lors de chaque insertion ou modification de CLIENT. A l heure actuelle, la majorité des SGBD implémentent ce type de construction. On les utilisera donc autant que possible. Avantages - efficace : les mécanismes de gestion se trouvent au cœur du SGBD ; - lisible : les contraintes peuvent être déclarées dans le code de création des tables ; - portable : standard pour (presque) tous les systèmes ; - automatique et transparent : n impose pas de discipline de programmation; - prise en charge par les outils CASE DB-MAIN - Techniques SQL avancées ( FUNDP) 7.4
7. Gestion de l intégrité 7.4 Prédicats Principe Chaque contrainte est exprimée sous la forme d'un prédicat associé à une colonne, à une table ou au schéma. Le prédicat est évalué après toute opération d'insertion et de modification de lignes de la table COMMANDE. S'il n'est pas vérifié, l'opération est annulée. Exemple alter table COMMANDE add constraint FK-COMCLI check(ncli in (select NCli from CLIENT)) create assertion FK_NCLI check (not exists (select * from COMMANDE where NCLI not in (select NCLI from CLIENT))); Evaluation La validation est prise en charge par le SGBD lors de chaque opération portant sur la table COMMANDE. En revanche, lors de la modification de lignes de CLIENT (delete par exemple), le prédicat est ignoré, ce qui peut entraîner une perte de l'intégrité. L'intégrité n'est donc que partiellement garantie. Dans certains SGBD (ORACLE, DB2), le prédicat check ne peut faire intervenir que le contenu de la ligne courante. La norme SQL-92 prévoit aussi le concept d'assertion, qui est un prédicat attaché au schéma plutôt qu'à une table particulière. Dans ce cas, toute modification qui touche les tables impliquées dans le prédicat est soumise à celui-ci. L assertion permet de maintenir l intégrité référentielle. Malheureusement, rares sont les SGBD qui implémentent ce concept. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.5
7. Gestion de l intégrité 7.4 Prédicats Avantages - efficace : au minimum pour les checks locaux ; - lisible : - les checks peuvent être déclarés lors de définitions de tables ; - permet de garder un code SQL déclaratif généralement concis (par opposition aux triggers et stored procedures) ; - portable : pour différents SGBD : - la différence de syntaxe est minime ; - il n y a pas de différence sémantique ; - automatique et transparent : n impose pas de discipline de programmation. Inconvénients - dégradation des performances : pour les assertions complexes ; - prédicats orientés : n assure pas la maintenance inverse des contraintes. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.6
7. Gestion de l intégrité Principe 7.5 Triggers Une procédure définit la réaction à adopter en cas de mise à jour (par exemple s'il y a violation de la contrainte d'intégrité). En cas de modification, si la précondition est vérifiée, la procédure est déclenchée. Exemple (simulation du mode cascade d'sql) create trigger CHECK_CLICOM1 after insert or update of NCli on COMMANDE for each row when (new.ncli not in (select NCli from CLIENT)) begin abort; end create trigger CHECK_CLICOM2 before delete on CLIENT for each row begin delete from COMMANDE where NCli = old.ncli; end create trigger CHECK_CLICOM3 after update NCli on CLIENT for each row begin update COMMANDE set NCli = new.ncli where NCli = old.ncli; end Evaluation La validation est prise en charge par le SGBD lors de chaque opération, quelle qu'en soit l'origine. L'intégrité est donc garantie tant que les triggers correspondants ne sont pas désactivés. L'approche étant essentiellement procédurale, elle est plus puissante mais plus complexe que celle des prédicats. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.7
7. Gestion de l intégrité 7.5 Triggers Application La technique des triggers est particulièrement utile dans la gestion des contraintes d'intégrité dynamique et dans la gestion de la redondance. Gestion des contraintes d'intégrité dynamique SICAV_CLIQUET Titre Emetteur Date_emission Valeur_initiale Valeur_actuelle id: Titre Les valeurs successives du champ Valeur_actuelle ne peuvent décroître. create trigger TRG_SICAV1 after update Valeur_actuelle on SICAV_CLIQUET for each row when (new.valeur_actuelle < old.valeur_actuelle) begin abort; end DB-MAIN - Techniques SQL avancées ( FUNDP) 7.8
7. Gestion de l intégrité 7.5 Triggers Gestion de la redondance COMMANDE NumCom DateCom NumCli Montant id: NumCom ref: NumCli CLIENT NumCli Nom EtatCompte id: NumCli La valeur de EtatCompte d'un CLIENT est la somme des valeurs de Montant des COMMANDEs du CLIENT. create trigger TRG_COM1 after insert on COMMANDE for each row begin update CLIENT set EtatCompte = EtatCompte + new.montant where NumCli = new.numcli; end Idem pour les événements update on COMMANDE et delete from COMMANDE. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.9
7. Gestion de l intégrité 7.5 Triggers Avantages - vers une base de données active : les données réagissent ellesmêmes aux événements ; - utilisation du langage procédural (si applicable). Inconvénients - non portable : alors que l on s attend à la standardisation des triggers et du langage procédural dans la norme SQL-3, il est fort probable que Java s impose de facto (cf. : Oracle 8i) ; - complexification du code : une BD contenant un grand nombre de triggers devient vite non maîtrisable. Une mise à jour des données peut déclencher de nombreux triggers en cascade : - effets de bords inattendus ; - dégradation des performances. Remarque L'imbrication des aspects événementiels (event), logiques (condition) et procéduraux (action) rend particulièrement délicat le développement d'un système cohérent et stable de triggers pour une base de données. On consultera par exemple la référence [Owens,1996] qui propose des éléments méthodologiques utiles. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.10
7. Gestion de l intégrité Principe 7.6 Views with check option Une vue est définie sur la table soumise aux contraintes. La clause where de cette vue est constituée des contraintes à respecter. La clause with check option spécifie que toute mise à jour des données via cette vue sera soumise à la satisfaction des contraintes. Les programmes d'application travaillent sur cette vue plutôt que sur la table de base. Exemple create view COM as select * from COMMANDE where NCli in (select NCli from CLIENT) with check option Evaluation On peut faire le même commentaire que pour les prédicats check. En effet, la vue filtrante protège la table vis à vis des modifications qui s'appliquent à ses propres lignes, mais pas de celles qui concernent la table CLIENT. Ainsi, la suppression d'une ligne de CLIENT pourrait laisser des lignes de COMMANDE orphelines sans que l'incident soit détecté. Avantages - portable Inconvénients - applicabilité réduite due aux nombreuses limitations (vue updatable, limitations logiques et particulières des SGBD) ; - force le programmeur à modifier son comportement ; - risques de complexification du code lorsqu un grand nombre de contraintes s enchaînent. - n assure pas la maintenance inverse des contraintes. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.11
7. Gestion de l intégrité 7.7 Stored procedures Principe On associe à la base de données une procédure interne pour chaque type de mise à jour. Ces procédures sont intégrées à la base de données. Chaque procédure vérifie que les contraintes d'intégrité sont satisfaites. Les programmes d'application invoquent ces procédures plutôt que les primitives SQL. Exemple create procedure CREATE_COM( NUM in integer, DATCOM in date, CLI in integer, OK out integer) as begin declare N integer; OK = 0; select count(*) into N from CLIENT where NCli = CLI; if N = 1 then insert into COMMANDE values (NUM,DATCOM,CLI); if SQLCODE = 0 then OK = 1 endif; endif; end Evaluation La validation est prise en charge par le SGBD lors de chaque opération, quelle qu'en soit l'origine. L'intégrité est donc garantie pour autant que ces procédures constituent la seule voie d'accès aux tables. L'approche purement procédurale est plus puissante mais plus complexe que celle des prédicats. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.12
7. Gestion de l intégrité 7.7 Stored procedures Avantage - utilisation de la puissance du langage procédural. Inconvénients - complexité du langage procédural ; - non portable (même remarque que pour les triggers concernant Java) ; - dépend d une discipline de programmation. On trouvera dans [Owens,1996] une description approfondie des Stored procedures. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.13
7. Gestion de l intégrité 7.8 Modules d accès Principe Toutes les mises à jour s'effectuent via des procédures centralisées dans un (ensemble de) module(s) spécifique(s). Les contraintes additionnelles y sont traduites sous la forme de séquences d'instructions vérifiant que la modification projetée respecte ces contraintes. Tout programme qui effectue des modifications des données doit invoquer ce module. Ces procédures sont externes à la base de données (écrites dans le langage de développement). Exemple procedure CREATE-COM(N:num,D:date,C:num,OK:num); var I: int; begin select count(*) into :I from CLIENT where NCLI = :C; OK := 0; if I = 1 then insert into COMMANDE values (:N,:D,:C); OK := 1; end; end;... ENREG-COMMANDE.... read(nco,dat,cli); CREATE-COM(NCO,DAT,CLI,OK); if OK = 0 then begin write('numéro de client invalide'); end;... DB-MAIN - Techniques SQL avancées ( FUNDP) 7.14
7. Gestion de l intégrité 7.8 Modules d accès Evaluation La validation est sous la responsabilité du programmeur. L'intégrité est garantie pour autant que ces procédures constituent la seule voie d'accès aux tables. Approche très puissante, mais complexe et délicate. Applicable à tous les SGD, même très primitifs. Avantages - puissance liée au langage procédural ; - toujours applicable car indépendant du SGD. Inconvénients - complexité du langage procédural ; - dépend d une discipline de programmation. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.15
7. Gestion de l intégrité 7.9 Sections de code distribuées dans les programmes d application Principe Tout programme qui désire effectuer des modifications sur les données vérifie que celles-ci n'entraîneront pas de violation des contraintes additionnelles. Cette vérification se traduit sous la forme de séquences d'instructions précédant chaque invocation d'une primitive de modification. Exemple... ENREG-COMMANDE.... read(nco,dat,cli); select count(*) into :I from CLIENT where NCLI = :CLI; if I = 1 then begin insert into COMMANDE values (:NCO,:DAT,:CLI) else write('numéro de client invalide'); end;... Evaluation Cette technique repose sur la qualité du travail de chaque programmeur à chaque instant. Bien que très utilisée, elle est très peu fiable. En outre, elle produit des programmes très difficiles à maintenir (dispersion, duplication, non standardisation), et constitue l'une des causes principales de la dégradation des programmes avec le temps. A éviter de manière absolue. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.16
7. Gestion de l intégrité 7.10 Procédures de validation attachées aux écrans de saisie Principe La vérification est effectuée par le gestionnaire de dialogue, via des procédures de validation attachées aux écrans et aux champs de saisie. Exemple SQL-FORMS d'oracle Evaluation La validation est prise en charge par le gestionnaire de l'interface utilisateur, mais pas par le SGBD. L'intégrité n'est donc garantie que pour les mises à jour qui sont demandées via les écrans auxquels les procédures de validation sont attachées. En particulier, les modifications faites par les programmes d'application échappent à cette validation. Technique peu fiable (dispersion, duplication, non standardisation), mais très utilisée avec les premiers SGBD relationnels (Oracle 6, Sybase). A éviter autant que possible. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.17
7. Gestion de l intégrité 7.11 Programme de validation avant chargement Principe La vérification est effectuée a priori par un programme d'application (en COBOL, C, Basic, etc.) qui élimine les données erronées avant leur enregistrement dans la base de données; les données reconnues correctes seront ensuite introduites dans la base par un programme de chargement. Exemple program PRE-VALIDATION-COMMANDE. var I int;... open input file ADD-COM-FILE; open output file VALID-COM-FILE; open output file ERROR-COM-FILE; read ADD-COM-FILE into COM; while record-found do begin select * into :I from CLIENT where NCLI = :COM.NCLI; if I = 1 then begin write COM to VALID-COM-FILE; else write COM to ERROR-COM-FILE; end; read ADD-COM-FILE into COM; end; close ADD-COM-FILE,VALID-COM-FILE,ERROR-COM-FILE;... Evaluation Méthode batch efficace, mais mises à jours asynchrones. L'intégrité est garantie pour autant que toutes les modifications soient soumises aux programmes de pré-validation. Applicable à tous les SGD, même très primitifs. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.18
7. Gestion de l intégrité 7.12 Programme de validation après chargement Principe La vérification est effectuée a posteriori par un programme d'application (en COBOL, C, Basic, etc.) qui analyse le contenu de la base de données et repère les données invalides; ces données sont corrigées (p.ex. interactivement), éliminées ou simplement consignées dans un fichier de diagnostic, comme dans l'exemple cidessous. Exemple program POST-VALIDATION-COMMANDE. var I int, N int, C int;... open output file ERROR-COM-FILE; declare COM cursor for select NCOM,NCLI from COMMANDE; open COM; fetch COM into :N, :C; while SQLCODE = 0 do begin select count(*) into :I from CLIENT where NCLI = :C; if I = 0 then begin write N,C to ERROR-COM-FILE; end; fetch COM into :N, :C; end; close COM; close ERROR-COM-FILE;... Evaluation Méthode batch efficace, mais les données récemment introduites ou modifiées ne sont pas validées avant l'activation des programmes de post-validation. L'intégrité est garantie pour autant que toutes les modifications soient soumises aux programmes de post-validation, et seulement pour les modifications précédant la dernière validation. Applicable à tous les SGD, même très primitifs. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.19
7. Gestion de l intégrité 7.13 Comportement en cas de violation Principes Comment le système (l'application, le système d'information, le SGBD) doit-il se comporter lors d'une demande de mise à jour qui entraîne la violation d'une contrainte d'intégrité? Principe absolu : si la BD est intègre avant la mise à jour, elle doit encore l'être après. On retient deux types de comportement. Blocage : toute opération qui va entraîner la violation d'une contrainte d'intégrité est refusée. Propagation : toute opération qui a entraîné la violation de contraintes d'intégrité est automatiquement suivie d'autres modifications jusqu'à ce que la BD retrouve un état d'intégrité. En général, plusieurs actions sont possibles. Exemple : gestion de l'intégrité référentielle dans les SGBD relationnels suite à une demande de suppression d'une ligne d'une table référencée. Blocage. Si la ligne à supprimer est référencée, la suppression est refusée ou annulée (= delete mode restrict). Propagation. 1. La ligne est supprimée. Si des lignes référençaient cette dernière, elles sont également supprimées (= delete mode cascade). 2. La ligne est supprimée. Si des lignes référençaient cette dernière, leur valeur de la clé étrangère est mise à null (= delete mode set null). Question : comment programmer ces comportements? DB-MAIN - Techniques SQL avancées ( FUNDP) 7.20
7. Gestion de l intégrité Application à l'intégrité référentielle et à la technique des triggers. (A adapter pour chaque contrainte et chaque technique de traduction) DB-MAIN - Techniques SQL avancées ( FUNDP) 7.21
7. Gestion de l intégrité Analyse 7.13 Comportement en cas de violation Comportement 1 : blocage Certaines opérations de mise à jour des données peuvent entraîner une perte d'intégrité de la base de données. Lorsqu'un tel incident se produit, l'opération litigieuse doit être annulée. Opérations critiques : insertion d'une ligne de COMMANDE, suppression d'une ligne de CLIENT, modification de NCli d'une ligne de COMMANDE, modification de NCli d'une ligne de CLIENT. Exemple de traduction pour les 2 premières opérations critiques L'insertion d'une ligne de COMMANDE L est annulée si la valeur de L.NCli ne référence aucune ligne de CLIENT. create trigger CHECK_COM1 after insert on COMMANDE for each row declare I number; begin select count(*) into :I from CLIENT where NCli = new.ncli; if I = 0 then abort endif; end La suppression d'une ligne de CLIENT L est annulée s'il existe au moins une ligne de COMMANDE qui référence L. create trigger CHECK_CLI1 after delete on CLIENT for each row declare I number; begin select count(*) into :I from COMMANDE where NCli = old.ncli; if I > 0 then abort endif; end DB-MAIN - Techniques SQL avancées ( FUNDP) 7.22
7. Gestion de l intégrité 7.13 Comportement en cas de violation Comportement 2 : propagation Analyse Certaines opérations de mise à jour des données peuvent entraîner une perte d'intégrité de la base de données. Lorsqu'un tel incident se produit, les données devenues incohérentes sont corrigées. Exemple de traduction L'insertion d'une ligne de COMMANDE L est suivie de l'insertion d'une nouvelle ligne de CLIENT si la valeur de L.NCli n'en référence aucune (dans ce cas un message est inséré dans le fichier de service NEW_CLIENTS). create trigger CHECK_COM2 after 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 values (new.ncli,'?','?'); write new.ncli to NEW_CLIENTS; endif; end La suppression d'une ligne de CLIENT L est suivie de la suppression de toutes les lignes de COMMANDE qui référencent L. create trigger CHECK_CLI2 before delete on CLIENT for each row begin delete from COMMANDE where NCli = old.ncli end DB-MAIN - Techniques SQL avancées ( FUNDP) 7.23
7. Gestion de l intégrité 7.14 Les objets à contraintes multiples Introduction En général, un objet (colonne, table) pourra être impliqué dans plusieurs contraintes. De plus, une contrainte exprimée au niveau logico-physique pourra se traduire par plusieurs constructions dans la base de donnée (ex. : plusieurs triggers). Il faut donc veiller à ce que les fragments de codes n interfèrent pas les uns avec les autres, empêchant ainsi toute mise à jour. Tout en supposant que les contraintes ne sont pas contradictoires au niveau logique, nous distinguerons deux types de problèmes : - incompatibilité au niveau physique, - enchaînement des validations. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.24
7. Gestion de l intégrité 7.14 Les objets à contraintes multiples Incompatibilités au niveau physique En fonction des limitations des SGBD, il peut arriver que certaines contraintes s interbloquent au niveau physique. Exemple : une contrainte equ (= ref + contrainte d'inclusion inverse) est difficilement implémentable de manière naturelle. ACHAT Ncli Num Montant id: Ncli Num equ: Ncli CLIENT Ncli Nom Prénom id: Ncli La contrainte equ peut se traduire comme suit : alter table ACHAT add constraint FKCLI foreign key (NCLI) references CLIENT; create assertion EQU_ACH_CLI check (not exists ( select * from CLIENT where NCLI not in (select NCLI from ACHAT)); Dans cette situation, il est impossible d insérer un client ou un achat. En effet, lors de l insertion d un achat, le SGBD vérifiera la présence du client (FK) et dans le cas de l insertion d un client, il vérifiera la présence d un achat. Pour débloquer la situation, il faut soit utiliser des mécanismes de report de vérification ou des stored procedures. Ces deux solutions sont plus lourdes à mettre en place. Remarque Ce problème persiste même si on code les contraintes sous forme de triggers ou de views with check option. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.25
7. Gestion de l intégrité 7.14 Les objets à contraintes multiples Enchaînement des validations Lors de l utilisation de views with check option ou de stored procedures, l enchaînement des validations risque de poser des problèmes. Si on désire vérifier plusieurs contraintes sur la même table via une vue/procédure, il y a deux possibilités : - regroupement de plusieurs contraintes dans une seule vue/procédure, - utilisation des vues/procédures en cascade. Ces deux procédés posent des problèmes de compréhension et de maintenance. DB-MAIN - Techniques SQL avancées ( FUNDP) 7.26
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. Gestion de l intégrité 8. Domaines d application 8.1 Gestion de l intégrité statique 8.2 Gestion de l intégrité dynamique 8.3 Gestion de la redondance 8.4 Alerteurs 8.5 Gestion de données temporelles 9. Les interfaces ODBC et JDBC 10. Bibliographie
8. Domaines d application 8.1 Gestion de l intégrité statique On désire implémenter le schéma suivant en utilisant des mécanismes garantissant l intégrité des données. On décide de traduire via les techniques natives ce qui est directement transposable (identifiants, colonnes obligatoires et foreign keys). Pour les autres contraintes, on propose successivement leur implémentation via : A. prédicats Check; B. Triggers; C. Stored procedures; D. Views with check option. CLIENT NumCli Nom Titre Adresse Compte[0-1] Montant[0-1] DateEnreg id:numcli exact-1:compte Montant TELEPHONE NumCli NumTel id:numcli NumTel equ: NumCli ACHAT NumCli DateAch Montant id: NumCli DateAch ref: NumCli Contraintes additionnelles Nombre de TELEPHONEs par CLIENT 5 La DateAch d'un ACHAT >= DateEnreg de son CLIENT domaine(client.titre) = {"M.", "Mme", "Mlle"} DB-MAIN - Techniques SQL avancées ( FUNDP) 8.2
8. Domaines d application 8.1 Gestion de l intégrité statique Définition du schéma en SQL-2 create table CLIENT ( NUMCLI number(6) not null, NOM char(10) not null, TITRE char(4) not null, ADRESSE char(20) not null, COMPTE number(9), MONTANT number(6), DATEENREG date not null, primary key(numcli)); create table TELEPHONE ( NUMCLI number(6) not null, NUMTEL number(9) not null, primary key(numcli, NUMTEL), foreign key(numcli) references CLIENT(NUMCLI) on delete cascade); create table ACHAT ( NUMCLI number(6) not null, DATEACH date not null, MONTANT number(6) not null, primary key(numcli, DATEACH), foreign key(numcli) references CLIENT(NUMCLI) on delete cascade); DB-MAIN - Techniques SQL avancées ( FUNDP) 8.3
8. Domaines d application 8.1 Gestion de l intégrité statique Traduction des contraintes On relève cinq contraintes qui ne peuvent être exprimées sous une forme structurelle explicite : C1 : CLIENT: exactly-1{compte,montant} C2 : TELEPHONE: equ{numcli} CLIENT C3 : Nombre de TELEPHONEs par CLIENT 5 C4 : La DateAch d'un ACHAT >= DateEnreg de son CLIENT C5 : domaine(client.titre) = {"M", "Mme", "Mlle"} A Contraintes additionnelles exprimées par Prédicats C1 : CLIENT: exactly-1{compte,montant} alter table CLIENT add constraint CHK_CLI_EX check ((COMPTE is null AND MONTANT is not null) or (COMPTE is not null AND MONTANT is null)); C2 : TELEPHONE: equ{numcli} CLIENT Analyse. Il s'agit d'un prédicat check multitable, que certains SGBD n'acceptent pas. On utilisera alors soit une assertion (ci-dessous), soit un trigger. Les assertions sont définies en SQL-2, mais ne sont pas disponibles dans tous les SGBD. Attention. Une telle assertion pose un problème de blocage mutuel avec la clé étrangère. En effet, une ligne de TELEPHONE doit être attachée à une ligne de CLIENT (clé étrangère), et inversement. La vérification de cette dernière contrainte doit donc être reportée à la fin de toute transaction (deferred) qui insère simultanément une ligne de CLIENT et une ligne de TELEPHONE. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.4
8. Domaines d application 8.1 Gestion de l intégrité statique create assertion EQU_TEL check(not exists( select * from CLIENT where NCLI not in (select NCLI from TELEPHONE))) initially deferred; C3 : Nombre de TELEPHONEs par CLIENT 5 create assertion NB_TEL_MAX check (not exists( select * from CLIENT where NUMCLI in (select NUMCLI from TELEPHONE group by NUMCLI having count (*) > 5))) C4 : La DateAch d'un ACHAT >= DateEnreg de son CLIENT create assertion DATE_OK check (not exists ( select * from ACHAT where DATEACH > ( select DATEENREG from CLIENT where CLIENT.NUMCLI = ACHAT.NUMCLI))); C5 : domaine(client.titre) = {"M", "Mme", "Mlle"} alter table CLIENT add constraint CHK_CLI_DOMTIT check (TITRE in ('M','Mme','Mlle')); DB-MAIN - Techniques SQL avancées ( FUNDP) 8.5
8. Domaines d application 8.1 Gestion de l intégrité statique B Contraintes additionnelles exprimées par Triggers Stratégie. La violation d'une contrainte crée une exception qui doit être détectée et traitée par la transaction qui a déclenché le trigger. En général, en cas d'exception non traitée, le SGBD provoque l'annulation de l'opération qui a déclenché le trigger. C1 : CLIENT: exactly-1{compte,montant} Analyse. Les opérations susceptibles d'entraîner la violation de la contrainte sont les suivantes : pour la table CLIENT : insert update CLIENT set COMPTE update CLIENT set MONTANT create or replace trigger CLI_MNT_BIR after insert or update of COMPTE, MONTANT on CLIENT for each row when ((NEW.COMPTE is null and NEW.MONTANT is null) or (NEW.COMPTE is not null and NEW.MONTANT is not null)) declare EXACTLY_1_not_VERIFIED exception; begin raise EXACTLY_1_not_VERIFIED; end; C2 : TELEPHONE: equ{numcli} CLIENT Analyse. En principe, un trigger associé à l'opération d'insert into CLIENT ne convient pas pour des raisons de blocage mutuel : la ligne de TELEPHONE devrait exister avant celle de CLIENT, mais la clé étrangère de TELEPHONE imposerait que la ligne de CLIENT existe avant celle de TELEPHONE. En revanche, un trigger pourrait entraîner la suppression d'un CLIENT après la disparition de son dernier TELEPHONE. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.6
8. Domaines d application 8.1 Gestion de l intégrité statique C3 : Nombre de TELEPHONEs par CLIENT 5 Analyse. Les opérations susceptibles d'entraîner la violation de la contrainte sont : pour la table TELEPHONE : insert into TELEPHONE update TELEPHONE set NumCli create or replace trigger TEL_MAX_BIR before insert or update NUMCLI on TELEPHONE for each row declare MAX_TEL exception; X NUMBER; begin select COUNT(*) into X from TELEPHONE where NUMCLI = :NEW.NUMCLI; if (X = 5) then raise MAX_TEL; end if; end; Remarque. Il est possible que le SGBD n'accepte pas l'évaluation d'une requête appliquée à une table en cours de modification (dite table en mutation selon Oracle). On adoptera alors des techniques indirectes telle que la suivante. Autre technique. Principe : on ajoute à la table CLIENT une colonne NTEL qui indique le nombre de numéros de téléphone actuellement associés à chaque client. Ce compteur est soumis à la contrainte (NTEL <=5), et est géré via des triggers associés à chaque opération applicable à TELEPHONE. En pratique, afin de ne pas modifier le schéma initial, on ajoutera une table CLI_TEL qui reprend cette colonne pour autant qu'il y ait au moins un numéro de téléphone. Cette table doit être ignorée par le programmeur. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.7
8. Domaines d application 8.1 Gestion de l intégrité statique create table CLI_TEL ( NCLI NUMBER(6) not null, NTEL NUMBER(1) not null, primary key(ncli), foreign key(ncli) references CLIENT(NUMCLI) on delete cascade); alter table CLI_TEL add constraint CHK_CLI_NTEL check (NTEL <= 5); Analyse. Les opérations qui déclenchent la mise à jour de la table CLI_TEL sont : pour la table TELEPHONE : create or replace trigger TEL_AIR after insert on TELEPHONE for each row declare N NUMBER; begin select COUNT(*) into N from CLI_TEL where NCLI = :NEW.NUMCLI; if (N > 0) then -- le CLI a déjà un TEL update CLI_TEL set NTEL = NTEL + 1 where NCLI = :NEW.NUMCLI; else -- premier TEL insert into CLI_TEL values (:NEW.NUMCLI,1); end if; end; insert into TELEPHONE delete from TELEPHONE update TELEPHONE set NumCli DB-MAIN - Techniques SQL avancées ( FUNDP) 8.8
8. Domaines d application 8.1 Gestion de l intégrité statique create or replace trigger TEL_ADR after delete on TELEPHONE for each row declare NT NUMBER; begin select NTEL into NT from CLI_TEL where NCLI = :OLD.NUMCLI; if (NT > 1) then -- CLI a au moins 2 TEL update CLI_TEL set NTEL = NTEL - 1 where NCLI = :OLD.NUMCLI; else -- CLI a 1 seul TEL delete from CLI_TEL where NCLI = :OLD.NUMCLI; end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.9
8. Domaines d application 8.1 Gestion de l intégrité statique create or replace trigger TEL_BUR before update of NUMCLI on TELEPHONE for each row declare N NUMBER; NT NUMBER; begin -- modifier le nouveau CLI select COUNT(*)into N from CLI_TEL where NCLI = :NEW.NUMCLI; if (N > 0) then -- le nouveau CLI a déjà un TEL update CLI_TEL set NTEL = NTEL + 1 where NCLI = :NEW.NUMCLI; else -- le nouveau CLI n'a pas de TEL insert into CLI_TEL values (:NEW.NUMCLI,1); end if; -- ensuite modifier l'ancien CLI select NTEL into NT from CLI_TEL where NCLI = :OLD.NUMCLI; if (NT > 1) then -- l'ancien CLI a au moins 2 TEL update CLI_TEL set NTEL = NTEL - 1 where NCLI = :OLD.NUMCLI; else -- l'ancien CLI n'a qu'un TEL delete from CLI_TEL where NCLI = :OLD.NUMCLI; end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.10
8. Domaines d application 8.1 Gestion de l intégrité statique C4 : La DateAch d'un ACHAT >= DateEnreg de son CLIENT Analyse. Les opérations susceptibles d'entraîner la violation de la contrainte sont : pour la table CLIENT : pour la table ACHAT : update CLIENT set DateEnreg insert into ACHAT update ACHAT set NumCli update ACHAT set DateAchat create or replace trigger CLI_DAT_BUR before update of DATEENREG on CLIENT for each row when (NEW.DATEENREG > OLD.DATEENREG) declare MIN_DATE DATE; INVALID_DATE exception; begin -- indique qu'il n'y a pas d'ach MIN_DATE = 31/12/2099; select MIN(DATEACH) into MIN_DATE from ACHAT where NUMCLI = :OLD.NUMCLI; if (:NEW.DATEENREG > MIN_DATE) then raise INVALID_DATE; end if; end; create or replace trigger ACH_DAT_BIR before insert or update NUMCLI, DATEACHAT on ACHAT for each row declare CDATE DATE; INVALID_DATE exception; begin select DATEENREG into CDATE from CLIENT where NUMCLI = :NEW.NUMCLI; if (:NEW.DATEACH < CDATE) then raise INVALID_DATE; end if; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.11
8. Domaines d application 8.1 Gestion de l intégrité statique C5 : domaine(client.titre) = {"M.", "Mme", "Mlle"} Analyse. Les deux opérations susceptibles d'entraîner la violation de la contrainte sont l'insert et l'update concernant la colonne Titre. create or replace trigger CLI_TIT_BIUR before insert or update of TITRE on CLIENT for each row when (NEW.TITRE not in ('M', 'Mme', 'Mlle')) declare DOM_TITRE_not_VERFIED exception; begin raise DOM_TITRE_not_VERFIED; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.12
8. Domaines d application 8.1 Gestion de l intégrité statique C Contraintes additionnelles exprimées par des Stored Procedures C1 : CLIENT: exactly-1{compte,montant} C2 : TELEPHONE: equ{numcli} CLIENT C3 : Nombre de TELEPHONEs par CLIENT 5 C4 : La DateAch d'un ACHAT >= DateEnreg de son CLIENT C5 : domaine(client.titre) = {"M", "Mme", "Mlle"} La validation des contraintes est encapsulée dans un ensemble de procédures de mise à jour des données (package d'oracle). 1. Déclaration de l interface create or replace PACKAGE INTERFACE_PKG is -- ajouter un CLIENT avec un de ses TEL procedure ADD_CLI(NC in CLIENT.NUMCLI%TYPE, NM in CLIENT.NOM%TYPE, ADR in CLIENT.ADRESSE%TYPE, TIT in CLIENT.TITRE%TYPE, CPT in CLIENT.COMPTE%TYPE, MNT in CLIENT.MONTANT%TYPE, DATREG in CLIENT.DATEENREG%TYPE, TELE in TELEPHONE.NUMTEL%TYPE); -- modifier un CLIENT procedure UPD_CLI(NC in CLIENT.NUMCLI%TYPE, NM in CLIENT.NOM%TYPE, TIT in CLIENT.TITRE%TYPE, ADR in CLIENT.ADRESSE%TYPE, CPT in CLIENT.COMPTE%TYPE, MNT in CLIENT.MONTANT%TYPE, DATREG in CLIENT.DATEENREG%TYPE); DB-MAIN - Techniques SQL avancées ( FUNDP) 8.13
8. Domaines d application 8.1 Gestion de l intégrité statique -- modifier NUMCLI de CLIENT procedure UPD_NUMCLI(OLDNUM in CLIENT.NUMCLI%TYPE, NEWNUM in CLIENT.NUMCLI%TYPE); -- ajouter un TELEPHONE procedure ADD_TEL(NC in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE); -- modifier NUMCLI d'un TELEPHONE procedure UPD_TEL(OLDNUMCLI in TELEPHONE.NUMCLI%TYPE, NEWNUMCLI in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE); -- supprimer un TELEPHONE procedure DEL_TEL(NC in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE); -- ajouter un ACHAT procedure ADD_ACH(NC in ACHAT.NUMCLI%TYPE, DATAC in ACHAT.DATEACH%TYPE, MNT in ACHAT.MONTANT%TYPE); -- modifier NUMCLI d'un ACHAT procedure UPD_ACH_NCLI( OLDNUM in ACHAT.NUMCLI%TYPE, NEWNUM in ACHAT.NUMCLI%TYPE, DATAC in ACHAT.DATEACH%TYPE); -- modifier la DATEACH d'un ACHAT procedure UPD_ACH_DATE( NC in ACHAT.NUMCLI%TYPE, OLDDATE in ACHAT.DATEACH%TYPE, NEWDATE in ACHAT.DATEACH%TYPE); end INTERFACE_PKG; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.14
8. Domaines d application 8.1 Gestion de l intégrité statique 2. Implémentation create or replace package body INTERFACE_PKG is -- variables CLI_DATA_ERR exception; -- fonctions privées function CHK_TITRE(TITRE in CLIENT.TITRE%TYPE) return BOOLEAN is begin if (TITRE not in ('M','Mme','Mlle')) then return FALSE; else return TRUE;end if; end CHK_TITRE; function CHK_EX1(COMPTE in CLIENT.COMPTE%TYPE, MONTANT in CLIENT.MONTANT%TYPE) return BOOLEAN is begin if ((MONTANT is null and COMPTE is null) or (MONTANT is not null and COMPTE is not null)) then return FALSE; else return TRUE; end if; end CHK_EX1; function CHK_DATE_ENREG( NC in CLIENT.NUMCLI%TYPE, DATENR in CLIENT.DATEENREG%TYPE) return BOOLEAN is N NUMBER; MINDATE ACHAT.DATEACH%TYPE; begin select COUNT(*) into X from ACHAT where NUMCLI = NC; if (N > 0) then select MIN(DATEACH) into MINDATE from ACHAT where NUMCLI = NC; if (MINDATE < DATENR) then return FALSE; end if; end if; return TRUE; end CHK_DATE_ENREG; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.15
8. Domaines d application 8.1 Gestion de l intégrité statique function CHK_DATE_ACH(NC in ACHAT.NUMCLI%TYPE, DACH in ACHAT.DATEACH%TYPE) return BOOLEAN is DATENR CLIENT.DATEENREG%TYPE; begin select DATEENREG into DATENR from CLIENT where NUMCLI = NC; if (DATENR > DACH) then return FALSE; else return TRUE; end if; end CHK_DATE_ACH; -- procédures publiques -- ajouter un CLIENT avec un de ses TELEPHONE procedure ADD_CLI(NC in CLIENT.NUMCLI%TYPE, NM in CLIENT.NOM%TYPE, ADR in CLIENT.ADRESSE%TYPE, TIT in CLIENT.TITRE%TYPE, CPT in CLIENT.COMPTE%TYPE, MNT in CLIENT.MONTANT%TYPE, DATREG in CLIENT.DATEENREG%TYPE, TELE in TELEPHONE.NUMTEL%TYPE) is begin -- vérification du TITRE if (not CHK_TITRE(TIT)) then raise CLI_DATA_ERR; end if; -- contrainte de coexistence if (not CHK_EX1(CPT,MNT)) then raise CLI_DATA_ERR; end if; -- création insert into CLIENT values (NC,NM,TIT,ADR,CPT,MNT,DATREG); insert into TELEPHONE values (NC,TELE); commit; end ADD_CLI; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.16
8. Domaines d application 8.1 Gestion de l intégrité statique -- modifier un CLIENT procedure UPD_CLI(NC in CLIENT.NUMCLI%TYPE, NM in CLIENT.NOM%TYPE, TIT in CLIENT.TITRE%TYPE, ADR in CLIENT.ADRESSE%TYPE, CPT in CLIENT.COMPTE%TYPE, MNT in CLIENT.MONTANT%TYPE, DATREG in CLIENT.DATEENREG%TYPE) is TMP_MNT CLIENT.MONTANT%TYPE; TMP_CPT CLIENT.COMPTE%TYPE; COEX_MOD BOOLEAN; begin -- NUMCLI est obligatoire if NC is null then raise CLI_DATA_ERR; end if; -- modification de NOM? if NM is not null then update CLIENT set NOM = NM where NUMCLI = NC; end if; -- modification de TITRE? if TIT is not null then if (not CHK_TITRE(TIT)) then raise CLI_DATA_ERR; else update CLIENT set TITRE = TIT where NUMCLI = NC; end if; end if; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.17
8. Domaines d application 8.1 Gestion de l intégrité statique -- modification de ADRESSE? if ADR is not null then update CLIENT set ADRESSE = ADR where NUMCLI = NC; end if; -- modification COMPTE et/ou MONTANT?. -- contrainte de coexistence. -- Note : une valeur nulle est représentée par -1 COEX_MOD := FALSE; if CPT is not null then COEX_MOD := TRUE; if (CPT = -1) then -- mise à null TMP_CPT := NULL; else -- valeur non nulle TMP_CPT := CPT; end if; else -- pas de changement, mais préparer vérification select COMPTE into TMP_CPT from CLIENT where NUMCLI = NC; end if; if MNT is not null then COEX_MOD := TRUE; if (MNT = -1) then -- mise à null TMP_MNT := NULL; else -- valeur non null TMP_MNT := MNT; end if; else -- pas de changement, mais préparer vérification select MONTANT into TMP_MNT from CLIENT where NUMCLI = NC; end if; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.18
8. Domaines d application 8.1 Gestion de l intégrité statique -- vérification coexistence if (COEX_MOD) then if (not CHK_EX1(TMP_CPT,TMP_MNT)) then raise CLI_DATA_ERR; end if; update CLIENT set COMPTE = TMP_CPT, MONTANT = TMP_MNT where NUMCLI = NC; end if; -- modifier DATEENREG? if DATREG is not null then if (not CHK_DATE_ENREG(NC,DATREG)) then raise CLI_DATA_ERR; else update CLIENT set DATEENREG = DATREG where NUMCLI = NC; end if; end if; commit; end UPD_CLI; -- modifier NUMCLI de CLIENT -- Remarque : ne peut être incorporé dans UPD_CLI procedure UPD_NUMCLI(OLDNUM in CLIENT.NUMCLI%TYPE, NEWNUM in CLIENT.NUMCLI%TYPE) is begin update CLIENT set NUMCLI = NEWNUM where NUMCLI = OLDNUM; commit; end UPD_NUMCLI; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.19
8. Domaines d application 8.1 Gestion de l intégrité statique -- ajouter un TELEPHONE procedure ADD_TEL(NC in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE) is N NUMBER; begin select COUNT(*) into N from TELEPHONE where NUMCLI = NC; if (N>=5) then raise CLI_DATA_ERR; end if; insert into TELEPHONE values (NC,TELE); commit; end ADD_TEL; -- modifier NUMCLI d'un TELEPHONE procedure UPD_TEL( OLDNUMCLI in TELEPHONE.NUMCLI%TYPE, NEWNUMCLI in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE) is N NUMBER; begin -- vérifier nombre maximum select COUNT(*) into N from TELEPHONE where NUMCLI = NEWNUMCLI; if (N = 5) then raise CLI_DATA_ERR; end if; -- vérifier equ select COUNT(*) into N from TELEPHONE where NUMCLI = OLDNUMCLI; if (N = 1) then raise CLI_DATA_ERR; end if; -- modifier update TELEPHONE set NUMCLI = NEWNUMCLI where NUMCLI = OLDNUMCLI; commit; end UPD_TEL; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.20
8. Domaines d application 8.1 Gestion de l intégrité statique -- supprimer un TELEPHONE procedure DEL_TEL(NC in TELEPHONE.NUMCLI%TYPE, TELE in TELEPHONE.NUMTEL%TYPE) is N NUMBER; begin -- vérifier equ select COUNT(*) into N from TELEPHONE where NUMCLI = NC; if (N = 1) then raise CLI_DATA_ERR; end if; -- supprimer delete from TELEPHONE where NUMCLI = NC and NUMTEL = TELE; commit; end DEL_TEL; -- ajouter un ACHAT procedure ADD_ACH(NC in ACHAT.NUMCLI%TYPE, DATAC in ACHAT.DATEACH%TYPE, MNT in ACHAT.MONTANT%TYPE) is begin if (not CHK_DATE_ENREG(NC,DATAC)) then raise CLI_DATA_ERR; end if; insert into ACHAT values (NC,DATAC,MNT); commit; end ADD_ACH; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.21
8. Domaines d application 8.1 Gestion de l intégrité statique -- modifier NUMCLI d'un ACHAT procedure UPD_ACH_NCLI(OLDNUM in ACHAT.NUMCLI%TYPE, NEWNUM in ACHAT.NUMCLI%TYPE, DATAC in ACHAT.DATEACH%TYPE) is begin if not CHK_DATE_ENREG(NEWNUM,DATAC) then raise CLI_DATA_ERR; end if; update ACHAT set NUMCLI = NEWNUM where NUMCLI = OLDNUM and DATEACH = DATAC; commit; end UPD_ACH_NCLI; -- modifier la DATEACH d'un ACHAT procedure UPD_ACH_DATE( NC in ACHAT.NUMCLI%TYPE, OLDDATE in ACHAT.DATEACH%TYPE, NEWDATE in ACHAT.DATEACH%TYPE) is begin if not CHK_DATE_ACH(NC,NEWDATE) then raise CLI_DATA_ERR; end if; update ACHAT set DATEACH = NEWDATE where NUMCLI = NC and DATEACH = OLDDATE; commit; end UPD_ACH_DATE; end INTERFACE_PKG; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.22
8. Domaines d application 8.1 Gestion de l intégrité statique D Contraintes additionnelles exprimées par des Views with Check option C1 : CLIENT: exactly-1{compte,montant} create or replace view VCLIENT (NUMCLI,NOM,TITRE,ADRESSE,COMPTE,MONTANT,DATEENREG) as select NUMCLI, NOM, TITRE, ADRESSE, COMPTE, MONTANT,DATEENREG from CLIENT where ((COMPTE is null and MONTANT is not null) or (COMPTE is not null and MONTANT is null)) with check option; C2 : TELEPHONE: equ{numcli} CLIENT Analyse. Situation de blocage comme pour les autres techniques. La définition ci-dessous est d'application pour les CLIENT auxquels une ligne de TELEPHONE est déjà associée. create or replace view VCLIENT (NUMCLI,NOM,TITRE,ADRESSE,COMPTE,MONTANT,DATEENREG) as select NUMCLI, NOM, TITRE, ADRESSE, COMPTE, MONTANT,DATEENREG from CLIENT where (NUMCLI in (select NUMCLI from TELEPHONE)) with check option; C3 : Nombre de TELEPHONEs par CLIENT 5 Analyse. La condition du CHECK implique un groupement (GROUP BY). On ne peut utiliser de GROUP BY dans une vue modifiable. On pourrait imaginer alors une solution utilisant une sous-requête, mais on ne peut utiliser de sous-requêtes portant sur la même table que la requête externe dans une vue modifiable. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.23
8. Domaines d application 8.1 Gestion de l intégrité statique C4 : La DateAch d'un ACHAT >= DateEnreg de son CLIENT Analyse. Il est nécessaire de définir deux vues, étant donné que la contrainte peut être violée lors de modifications s'adressant aux tables ACHAT et CLIENT. create or replace view INFOACH (NUMCLI,DATEACH,MONTANT) as select NUMCLI,DATEACH,MONTANT from ACHAT A where DATEACH >= (select DATEENREG from CLIENT where NUMCLI = A.NUMCLI) with check option; create or replace view INFOCLI (NUMCLI,NOM,TITRE,ADRESSE,COMPTE,MONTANT,DATEENREG) as select NUMCLI, NOM, TITRE, ADRESSE, COMPTE, MONTANT,DATEENREG from CLIENT C where (DATEENREG <= (select MIN(DATEACH) from ACHAT where NUMCLI = C.NUMCLI) or NUMCLI not in (select NUMCLI from ACHAT)) with check option; C5 : domaine(client.titre) = {"M", "Mme", "Mlle"} create or replace view INFOCLI (NUMCLI,NOM,TITRE,ADRESSE,COMPTE,MONTANT,DATEENREG) as select NUMCLI, NOM, TITRE, ADRESSE, COMPTE, MONTANT,DATEENREG from CLIENT C where TITRE in ('M','Mme','Mlle') with check option; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.24
8. Domaines d application 8.2 Gestion de l intégrité dynamique La modification de la colonne EtatCivil de la table PERSONNE doit respecter une table de transitions (une personne célibataire ne peut devenir veuve, etc.). Afin de garantir l intégrité des données, nous proposons de rédiger un trigger qui assurera que les transitions sont valides. PERSONNE Matricule Nom Adresse EtatCivil id: Matricule "C" "M" "M" "S","D","V" "D" "M" "V" "M" "S" "D","V","M" Il faut d'abord imposer une contrainte de domaine pour la colonne ETATCIVIL. La solution la plus simple est celle d'un prédicat CHECK local : alter table PERSONNE add( check(etatcivil in ('C','M','D','V','S'))); Le contrôle des transitions valides s'effectue par le trigger suivant : create TRIGGER PERSONNE_ETATCIVIL_BUR before update of ETATCIVIL on PERSONNE for each row when ( (OLD.ETATCIVIL in ('C','D','V') and NEW.ETATCIVIL!= 'M') or (OLD.ETATCIVIL = 'M' and NEW.ETATCIVIL not in ('S','D','V')) or (OLD.ETATCIVIL = 'S' and NEW.ETATCIVIL not in ('D','V','M'))) declare TRANS_ETAT_INVALID exception; begin raise TRANS_ETAT_INVALID; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.25
8. Domaines d application 8.3 Gestion de la redondance Introduction Les schémas physiques comportent souvent des données redondantes pour des raisons d optimisation des requêtes de consultation. Si on désire garder la base de données cohérente, il faut gérer cette redondance lors des mises à jour. La gestion de la redondance sera illustrée au moyen de trois cas : - attributs redondants, - structure non normalisée (présence de DF anormale), - attributs dérivables. Gestion des attributs redondants Pour des raisons de performance, on stocke dans chaque commande le nom du client ainsi que son adresse. On propose de gérer cette situation via un ensemble de triggers qui se chargeront de mettre à jour les données redondantes quand les données de base seront introduites ou modifiées. CLIENT NCli Nom Adresse id: NCli COMMANDE NCom Nom-Client Adresse-Client Date id: NCom 0-N passe 1-1 c COMMANDE: c.nom-client = c.passe.client.nom c.adresse-client = c.passe.client.adresse DB-MAIN - Techniques SQL avancées ( FUNDP) 8.26
8. Domaines d application 8.3 Gestion de la redondance 1. Création des tables create table CLIENT ( NCLI NUMBER(6) not null, NOM CHAR(25) not null, ADRESSE CHAR(50) not null, primary key(ncli)); create table COMMANDE ( NCOM NUMBER(6) not null, NOM_CLI CHAR(25) not null, ADR_CLI CHAR(50) not null, DATE_COM DATE not null, NCLI NUMBER(6) not null, primary key(ncom), foreign key(ncli) references CLIENT(NCLI)); Remarque : lors du passage au schéma physique, certain noms ont été mis en conformité. 2. Gestion de la redondance Analyse. Les opérations susceptibles d'altérer des colonnes redondantes (NOM, ADRESSE) de COMMANDE sont les suivantes : pour la table CLIENT : update CLIENT set NOM update CLIENT set ADRESSE pour la table COMMANDE : insert into COMMANDE update COMMANDE set NCLI update COMMANDE set NOM_CLI (refusé) update COMMANDE set ADR_CLI (refusé) DB-MAIN - Techniques SQL avancées ( FUNDP) 8.27
8. Domaines d application 8.3 Gestion de la redondance create or replace trigger CLIENT_AUR after update of NOM, ADRESSE on CLIENT for each row when (NEW.NOM!= OLD.NOM or NEW.ADRESSE!= OLD.ADRESSE) begin update COMMANDE set NOM_CLI = :NEW.NOM, ADR_CLI = :NEW.ADRESSE where NCLI = :OLD.NCLI; end; create or replace trigger COM_BIR after insert on COMMANDE for each row declare N CHAR(25); A CHAR(25); begin select NOM, ADRESSE into :N, :A from CLIENT where NCLI = :NEW.NCLI; update COMMANDE set NOM_CLI = :N, ADR_CLI = :A; where NCLI = :NEW.NCLI; end; create or replace trigger COM_NCLI_BUR before update of NCLI on COMMANDE for each row when (NEW.NCLI!= OLD.NCLI) declare N CHAR(25); A CHAR(25); begin select NOM, ADRESSE into :N, :A from CLIENT where NCLI = :NEW.NCLI; update COMMANDE set NOM_CLI = :N, ADR_CLI = :A; where NCLI = :NEW.NCLI; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.28
8. Domaines d application 8.3 Gestion de la redondance Remarque. La solution proposée suppose qu'un trigger puisse modifier à nouveau la ligne qui vient d'être modifiée. Si ce n'est pas le cas, on utilisera une technique de correction a priori (before trigger) qui consiste à modifier la ligne NEW. Exemple : create or replace trigger COM_NCLI_BUR before update of NCLI ON COMMANDE for each row when (NEW.NCLI!= OLD.NCLI) declare N NUMBER; begin select count(*) into N from CLIENT where NCLI = :NEW.NCLI; if (N = 1) then select NOM, ADRESSE into :NEW.NOM_CLI, :NEW.ADR_CLI from CLIENT where NCLI = :NEW.NCLI; end if; -- else : erreur qui sera traitée par -- le contrôle de la FK end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.29
8. Domaines d application 8.3 Gestion de la redondance Gestion des structures non normalisées La table EMPLOYE comporte des dépendances fonctionnelles anormales. On décide néanmoins de l implémenter telle quelle et de lui adjoindre des triggers qui garantiront la consistance des données. EMPLOYE NumE Nom NomDépart Localisation NomDirecteur id: NumE NomDépart Localisation NomDépart NomDirecteur Analyse. Les opérations susceptibles d'altérer des colonnes problématiques (NomDepart, Localisation, NomDirecteur) sont les suivantes : insert into EMPLOYE Il existe une ligne d'employe de même NomDepart; si les colonnes déterminées sont identiques : simple insertion, sinon insertion avec les valeurs corrigées. Il n'existe pas d' EMPLOYE de même NomDépart : simple insertion. update EMPLOYE set NomDepart idem update EMPLOYE set Localisation modifier la colonne Localisation de tous les EMPLOYEs de même NomDepart. update EMPLOYE set NomDirecteur idem DB-MAIN - Techniques SQL avancées ( FUNDP) 8.30
8. Domaines d application Insertion d'un EMPLOYE 8.3 Gestion de la redondance create or replace trigger EMP_BIR before insert on EMPLOYE for each row declare N NUMBER; begin select count(*) into X from EMPLOYE where NOMDEPART = :NEW.NOMDEPART; if (N > 0) then select distinct LOCALISATION,NOMDIRECTEUR into :NEW.LOCALISATION,:NEW.NOMDIRECTEUR from EMPLOYE where NOMDEPART = :NEW.NOMDEPART end if; end; Modification de Localisation create or replace trigger EMP_BIR after update LOCALISATION on EMPLOYE for each row when (OLD.LOCALISATION!= NEW.LOCALISATION) begin update EMPLOYE set LOCALISATION = :NEW.LOCALISATION where NOMDEPART = :old.nomdepart and LOCALISATION <> :NEW.LOCALISATION end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.31
8. Domaines d application 8.3 Gestion de la redondance Remarque. La solution proposée ci-dessus sera en général rejetée par le SGBD car le trigger se (re)déclenche lui-même. Pour certains SGBD, la table est considérée comme étant en mutation, et ne peut être modifiée par le trigger lui-même. On adoptera alors une solution telle que la suivante. A chaque modification de la localisation d'un département, on stocke dans une table persistante le couple <NOMDEPART, LOCALISATION>. Lorsque la modification déclencheuse est terminée, on modifie EMPLOYE selon les informations reprises dans cette table. Un premier trigger initialise l'index de la table, le deuxième stocke les nouvelles valeurs et le troisième modifie les lignes d EMPLOYE en cascade. ---- -- Creation des triggers ---- -- Avant l'instruction d'update : -- initialisation de la table create or replace trigger EMP_LOC_BUS before update of LOCALISATION on EMPLOYE begin EMP_table_PKG.CLEAR; end; -- Après l'update de chaque ligne : -- stocker dans la table les nom de dep -- dont la localisation est modifiee create or replace trigger EMP_LOC_AUR after update of LOCALISATION on EMPLOYE for each row when (NEW.LOCALISATION!= OLD.LOCALISATION) -- pour éviter le déclenchement -- en cascade de ce triger begin EMP_table_PKG.PUT(:OLD.NOMDEPART, :NEW.LOCALISATION); end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.32
8. Domaines d application 8.3 Gestion de la redondance -- Après l'instruction d'update : -- modifier les autres lignes -- du même département create or replace trigger EMP_LOC_AUS after update of LOCALISATION on EMPLOYE begin EMP_table_PKG.update_LOC; end; ---- -- Creation des procédures ---- -- Déclaration de l interface create or replace PACKAGE EMP_table_PKG is procedure CLEAR; procedure PUT(EMP_DEPN in EMPLOYE.NOMDEP%TYPE, EMP_LOC in EMPLOYE.LOCALISATION%TYPE); procedure update_loc; end EMP_table_PKG; -- Implementation du package create or replace PACKAGE BODY EMP_table_PKG is -- Definition des types TYPE LOC_TYPE is RECORD ( DEPN EMPLOYE.NOMDEPART%TYPE, DEPLOC EMPLOYE.LOCALISATION%TYPE); TYPE TABLE_TYPE is table of LOC_TYPE INDEX BY BINARY_INTEGER; -- Declaration des variables TAB TABLE_TYPE; IDX BINARY_INTEGER := 0; ITE BINARY_INTEGER := 0; -- Implementation -- Public procedure CLEAR is begin IDX := 0; end CLEAR; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.33
8. Domaines d application 8.3 Gestion de la redondance procedure PUT(EMP_DEPN in EMPLOYE.NOMDEPART%TYPE, EMP_LOC in EMPLOYE.LOCALISATION%TYPE)is TMP_REC LOC_TYPE; begin IDX := IDX + 1; TMP_REC.DEPN := EMP_DEPN; TMP_REC.DEPLOC := EMP_LOC; TAB(IDX) := TMP_REC; end PUT; procedure UPDATE_LOC is TMP_REC LOC_TYPE; DEPN EMPLOYE.NOMDEPART%TYPE; DLOC EMPLOYE.LOCALISATION%TYPE; begin ITE := IDX; while ITE > 0 loop TMP_REC := TAB(ITE); DEPN := TMP_REC.DEPN; DLOC := TMP_REC.DEPLOC; update EMPLOYE set LOC = DLOC where NOMDEPART = DEPN; ITE := ITE - 1; end LOOP; end UPDATE_LOC; end EMP_table_PKG; Commentaire 1. On comprend aisément les raisons pour lesquelles on préférera en général construire des tables normalisées. Commentaire 2. On trouvera un autre exemple dans le chapitre 3 des notes du séminaire SM1 (section 3.8/B). DB-MAIN - Techniques SQL avancées ( FUNDP) 8.34
8. Domaines d application 8.3 Gestion de la redondance Gestion des attributs dérivables Pour des raisons de performance, on désire que le montant des commandes soit disponible immédiatement lors de l affichage de celles-ci. Pour cela, on décide d ajouter une colonne à COMMANDE. Cette dernière doit contenir à chaque instant la somme des montants des lignes de détail. COMMANDE NCom Date Montant id: NCom 0-N de 1-1 PRODUIT NumPro Libellé Prix-Unitaire 0-N en 1-1 DETAIL Quantité id: en.produit de.commande c COMMANDE, d c.de.detail: c.montant = Σ(d.Quantité)*(d.en.PRODUIT.Prix-Unitaire) d DB-MAIN - Techniques SQL avancées ( FUNDP) 8.35
8. Domaines d application 8.3 Gestion de la redondance Analyse. Les opérations susceptibles d'entraîner une mise à jour de Montant de COMMANDE sont les suivantes (exprimées sur le schéma logique) : insert into COMMANDE initialiser Montant à 0. update COMMANDE set Montant interdit. insert into DETAIL modifier Montant. delete from DETAIL modifier Montant. update DETAIL set NCom modifier Montant update DETAIL set NumPro modifier Montant. update DETAIL set Quantite modifier Montant. delete from PRODUIT modifier Montant. update PRODUIT set Prix_Unitaire modifier Montant. On proposera quelques triggers parmi ceux qui découlent de cette nomenclature. create or replace trigger DET_AIR after insert ON DETAIL for each row declare P NUMBER; -- prix begin -- recherche le prix du produit select PRIX into P from PRODUIT where NPRO = :NEW.NPRO; -- update de la commande update COMMANDE set MONTANT = MONTANT + (:NEW.QCOM * P) where NCOM = :NEW.NCOM; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.36
8. Domaines d application 8.3 Gestion de la redondance create or replace trigger DET_ADR after delete on DETAIL for each row declare P NUMBER; -- prix begin -- recherche le prix du produit select PRIX into P from PRODUIT where NPRO = :OLD.NPRO; -- update la commande update COMMANDE set MONTANT = MONTANT - (:OLD.QCOM * P) where NCOM = :OLD.NCOM; end; create or replace trigger DET_NPRO_AUR after update of NPRO on DETAIL for each row declare OLD_P NUMBER; -- ancien prix NEW_P NUMBER; -- nouveau prix begin -- recherche le prix de l'ancien produit select PRIX into OLD_P from PRODUIT where NPRO = :OLD.NPRO; -- recherche le prix du nouveau produit select PRIX into NEW_P from PRODUIT where NPRO = :NEW.NPRO; -- update de la commande update COMMANDE set MONTANT = MONTANT - (:OLD.QCOM * OLD_P) + (:NEW.QCOM * NEW_P) where NCOM = :OLD.NCOM; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.37
8. Domaines d application 8.3 Gestion de la redondance create or replace trigger DET_NCOM_AUR after update of NCOM on DETAIL for each row declare P NUMBER; -- prix begin -- recherche le prix du produit select PRIX into P from PRODUIT where NPRO = :OLD.NPRO; -- update de l'ancienne commande update COMMANDE set MONTANT = MONTANT - (:OLD.QCOM * P) where NCOM = :OLD.NCOM; -- update de la nouvelle commande update COMMANDE set MONTANT = MONTANT + (:OLD.QCOM * P) where NCOM = :NEW.NCOM; end; create or replace trigger DET_QCOM_AUR after update of QCOM on DETAIL for each row declare P NUMBER; -- prix begin -- rechercher le prix du produit select PRIX into P from PRODUIT where NPRO = :OLD.NPRO; -- update de la commande update COMMANDE set MONTANT = MONTANT + ((:NEW.QCOM - :OLD.QCOM) * P) where NCOM = :OLD.NCOM; end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.38
8. Domaines d application 8.3 Gestion de la redondance create or replace trigger PRO_PRIX_AUS after update of PRIX on PRODUIT begin update COMMANDE C set MONTANT = ( select SUM(PRIX*QCOM) from DETAIL D, PRODUIT P where C.NCOM = D.NCOM and D.NPRO = P.NPRO where NCOM in (select NCOM from DETAIL where NPRO = :OLD.NPRO) ; end; Autres formes d'implémentation 1. Définition d'une vue incluant la colonne calculée COMMANDE.Montant 2. Ajouter un attribut Montant dans le TE DETAIL. Ceci permet de simplifier la définition de Montant de COMMANDE. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.39
8. Domaines d application 8.4 Alerteur Principe Un alerteur est un dispositif qui transmet un message à qui de droit lors de la survenance de certains événements importants affectant la base de données. Exemple On considère la table ci-dessous. ARTICLE CodeArticle Libellé NiveauStock StockMaxi StockMini id: CodeArticle Il conviendrait que le gestionnaire des stocks soit averti dès que le niveau d'un article (NiveauStock) tombe en dessous du minimum (StockMini). On pense alors à rédiger un trigger qui, lorsque l événement de mise à jour des stocks intervient et si la condition NiveauStock < StockMini est vérifiée, prend l action de prévenir le gestionnaire de la quantité à commander. Analyse Il existe plusieurs solutions à ce problème. Nous choisirons celle qui consiste à ranger dans une table de service les événements de rupture de stock. Un programme externe (ici rédigé en Java) consulte cette table, émet un message pour chaque ligne en attente, puis marque ces lignes comme étant traitées. Cette table peut également être exploitée par divers autres processus de gestion. DB-MAIN - Techniques SQL avancées ( FUNDP) 8.40
8. Domaines d application 8.4 Alerteur create table ART_LOG ( ADATE DATE not null, CODEART NUMBER(6) not null, STKALERT NUMBER(4) not null, MAILED NUMBER(1) not null, PRIMARY KEY(ADATE,CODEART)); -- creation du trigger create or replace trigger ART_QTK_AUR after update of NIVEAUSTOCK on ARTICLE for each row when (OLD.NIVEAUSTOCK > OLD.STOCKMINI and NEW.NIVEAUSTOCK <= OLD.STOCKMINI) begin insert into ART_LOG values (SYSDATE,:OLD.CODEARTICLE, :NEW.NIVEAUSTOCK,0); end; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.41
8. Domaines d application 8.4 Alerteur // Program CheckStock import java.lang.*; import java.sql.*; public class CheckStock { static String ora_login = "ora_lerter"; static String ora_pass = "*******"; static String ora_host = "vicka"; static String mail_from = "ora_lerter"; static String mail_to = "jmdurant@appro.abc.com"; static String mail_subject = "ORA-ALERT: stock insuffisant"; static String mail_host = "mailhost"; private static Connection con; private static Statement stmt,stmt2; private static ResultSet rs; public static void main(string arg[]) { String msg; try { // charger driver JDBC Class.forName( "oracle.jdbc.driver.oracledriver"); // créer connexion con = DriverManager.getConnection( "jdbc:oracle:thin:@" + ora_host+":1521:orcl", ora_login,ora_pass); // créer statement stmt = con.createstatement(); stmt2 = con.createstatement(); // examen de la table des ruptures de stock rs = stmt.executequery( "select ADATE, CODEART, LIBELLE, STOCKMAXI-STKALERT" +" from ARTICLE, ART_LOG" +" where CODEART=CODEARTICLE" +" and MAILED = 0"); DB-MAIN - Techniques SQL avancées ( FUNDP) 8.42
8. Domaines d application } } 8.4 Alerteur while (rs.next()) { // construire l'email msg = "Produit No "+rs.getint(2)+" (" + rs.getstring(3) +") atteint stock minimum à " + rs.gettimestamp(1) +".\ncommander "+rs.getint(4)+" unites"; // envoyer l'email: // (from,to,subject,body).(mailhost) new TextMessage (mail_from,mail_to,mail_subject,msg).send(mail_host); // marquage des envois stmt2.executequery("update ART_LOG " +"set MAILED = 1 " +"where CODEART = " +rs.getint(2)); } rs.close(); stmt.close(); con.close(); } catch (Exception e) { System.out.println(e);} DB-MAIN - Techniques SQL avancées ( FUNDP) 8.43
8. Domaines d application 8.5 Gestion de données temporelles Une base de données traditionnelle représente l'état courant du domaine d'application. Exemple : actuellement, il existe un client de numéro (identifiant) C400, de nom FERARD, localisé à Paris et de catégorie C1. CLIENT NCLI NOM LOCALITE CAT C400 FERARD Paris C1 On peut en outre représenter l'évolution des clients, c'est-à-dire leur historique. Exemple : le client C400 est connu depuis le 3 novembre 1998, il a changé de catégorie le 18 mai 1999 et le 7 avril 2000, et de localité le 26 décembre 1999. Il existait un client F011, actuellement supprimé. H_CLIENT NCLI debut fin NOM LOCALITE CAT C400 3-11-1998 18-05-1999 FERARD Poitiers B1 C400 18-05-1999 26-12-1999 FERARD Poitiers B2 C400 26-12-1999 7-04-2000 FERARD Paris B2 C400 7-04-2000 9-09-9999 FERARD Paris C1 F011 8-10-1997 12-03-1998 PONCELET Lille B1 F011 12-03-1998 15-06-1999 PONCELET Paris B2 F011 15-06-1999 22-02-2000 PONCELET Toulouse B1 Remarques intervalle de validité semi-ouvert à droite : état H de H_CLIENT valide pour tout T tel que H.debut T < H.fin état courant : T tel que fin = 9-09-9999 DB-MAIN - Techniques SQL avancées ( FUNDP) 8.44
8. Domaines d application 8.5 Gestion de données temporelles Gestion de données temporelles On considère que les intervalles de validité sont ceux de la présence des données dans la base de données (confusion des temps de validité et de transaction). Il alors possible de gérer de manière transparente l'historique de l'évolution des clients. Définition de la table des historiques create table H_CLIENT( NCLI char(8) not null, debut timestamp not null, fin timestamp default '1-01-3000' not null, NOM char(18) not null, LOCALITE char(20) not null, CAT char(2), primary key (NCLI,debut)); Définition de la vue des états courants (updatable) create view CLIENT(NCLI,NOM,LOCALITE,CAT) as select NCLI,NOM,LOCALITE,CAT from H_CLIENT where fin = '9-09-9999'; Evolution des clients (historique ignoré) insert into CLIENT values (:N,:NOM,:LOC,:CAT); update CLIENT set CAT = 'B2' where NCLI = :N; delete from CLIENT where NCLI = :N; DB-MAIN - Techniques SQL avancées ( FUNDP) 8.45
8. Domaines d application 8.5 Gestion de données temporelles Gestion de l'historique lors d'une insertion create trigger TRG_INSERT_CLI before insert on H_CLIENT for each row when (new.fin='1-1-3000') begin new.debut = current_timestamp; end Gestion de l'historique lors d'une insertion create trigger TRG_B_UPDATE_CLI before update on H_CLIENT on each row begin new.debut = current_timestamp; end create trigger TRG_A_UPDATE_CLI after update on H_CLIENT for each row begin insert into H_CLIENT values(old.ncli, old.debut, new.debut, old.nom, old.localite, old.cat); end Gestion de l'historique lors d'une suppression create trigger TRG_DELETE_CLI after delete on H_CLIENT on each row begin insert into H_CLIENT values (old.ncli, old.debut, current_timestamp, old.nom, old.localite, old.cat); end DB-MAIN - Techniques SQL avancées ( FUNDP) 8.46
8. Domaines d application 8.5 Gestion de données temporelles Remarque : gestion ci-dessus simpliste 1. update : vérifier que l'identifiant d'entités n'est pas modifié (sinon historique non reconstituable); 2. update : vérifier qu'au moins une colonne change de valeur (sinon deux états sucessifs identiques); 3. insert : vérifier qu'on ne réutilise pas une valeur d'identifiant d'entités déjà utilisée dans le passé (sinon confusion des historiques de deux entités distinctes); 4. foreign key temporelles : intégrité référentielle plus complexe que pour les FK classiques; 5. on a souvent besoin de deux dimensions temporelles : temps de validité et temps de transaction; 6. etc. Cfr projet TimeStamp DB-MAIN - Techniques SQL avancées ( FUNDP) 8.47
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. La gestion de l'intégrité 8. Applications 9. Interfaces ODBC et JDBC 9.1 Principes 9.2 ODBC 9.3 JDBC 9.4 Références ODBC, JDBC 10. Bibliographie
9. Interfaces ODBC et JDBC 9.1 Principes Observations 1. L'existence de plusieurs fournisseurs de SGBD entraîne de multiples divergences dans l'interprétation des normes SQL (en elles-mêmes peu strictes). 2. Les mécanismes d'interaction programme / SGBD diffèrent d'un fournisseur à l'autre. Conséquences 1. Il est difficile de développer un programme qui accède à plusieurs SGBD; 2. Il est très difficile de développer un programme qui soit indépendant du SGBD. Réactions Définitions d'interfaces permettant de neutraliser les variations des SGBD quant au langage SQL et aux protocoles d'interaction. SQL Access Group (SAG) : propose une interface unique d'accès à des SGBD SQL. Deux implémentations de ces spécifications : ODBC (Microsoft) : Open Database Connectivity IDAPI (Borland, Novell, IBM) : Integrated Database API Dans le monde Java : interface JDBC Deux normes : ODBC 2 et ODBC 3 Trois niveaux : kernel, 1 et 2 DB-MAIN - Techniques SQL avancées ( FUNDP) 9.2
9. Interfaces ODBC et JDBC 9.2 ODBC Plateformes Windows, Macintosh, Unix, mainframes IBM Architecture Application cliente + API ODBC Gestionnaire des pilotes : appelle dynamiquement les pilotes requis par l'application; utilise le répertoire ODBC.ini Pilotes spécialisés SGBD application cliente API ODBC gestionnaire des pilotes ODBC Pilote Access Pilote Oracle Pilote DB2 Access Oracle DB2 BD BD BD DB-MAIN - Techniques SQL avancées ( FUNDP) 9.3
9. Interfaces ODBC et JDBC 9.2 ODBC Structure d'un programme ODBC SQLAllocEnv: allocation descripteur environnement ODBC SQLAllocConnect: allocation descripteur connexion 1... SQLAllocConnect: allocation descripteur connexion n SQLSetConnect:définition options connexion 1 SQLConnect: ouverture connexion 1... SQLSetConnect:définition options connexion n SQLConnect: ouverture connexion n traitement des données SQLDisconnect:fermeture connexion 1... SQLDisconnect:fermeture connexion n SQLFreeConnect: désallocation descripteur connexion n... SQLFreeConnect: désallocation descripteur connexion 1 SQLFreeEnv: désallocation descripteur environnement ODBC DB-MAIN - Techniques SQL avancées ( FUNDP) 9.4
9. Interfaces ODBC et JDBC 9.2 ODBC Structure d'une sélection var_sfw = "select...from...where" SQLAllocStmt: allocation descripteur requête(var_req) SQLExecDirect: exécution de la requête(var_req,var_sfw) liaison colonnes-select / variables SQLFetch(var_REQ) tant que trouvé: exploitation résultats SQLfetch(var_REQ) Accès par ligne ou par bloc (optimisation des transferts serveur client) DB-MAIN - Techniques SQL avancées ( FUNDP) 9.5
9. Interfaces ODBC et JDBC 9.3 JDBC Architecture Application cliente + API JDBC Gestionnaire des pilotes Pilotes spécialisés / pilote convertisseur JDBC/ODBC Pilotes ODBC SGBD application cliente JAVA API JDBC gestionnaire des pilotes JDBC JDBC/ODBC Pilote Oracle Pilote DB2 Pilote ODBC Oracle DB2 Sybase BD BD BD DB-MAIN - Techniques SQL avancées ( FUNDP) 9.6
9. Interfaces ODBC et JDBC 9.3 JDBC Structure d'un programme JDBC var_sfw = "select...from...where" chargement pilote JDBC établissement connexion C création d'un objet instruction I pour C exécuter I pour la requête var_sfw, résultat dans RS while(rs.next()) {exploitation résultats} fermeture résultat RS fermeture instruction I fermeture connexion C DB-MAIN - Techniques SQL avancées ( FUNDP) 9.7
9. Interfaces ODBC et JDBC 9.4 Références ODBC, JDBC [Delmal, 1998] pour ODBC [Geiger, 1995] Geiger, K., Inside ODBC, Microsoft Press, 1995 [Hamilton, 1997] Hamilton, G., Cattel, R., Fisher, M., JDBC Database Access with java - A tutorial and annotated reference, The Java Series, Addisson-Wesley, 1997 DB-MAIN - Techniques SQL avancées ( FUNDP) 9.8
9. Interfaces ODBC et JDBC 9.5 Annexe : les API SQL Requête : afficher le numéro, le nom et l'adresse des clients dont l'utilisateur introduit les localités. 1. Embedded SQL exec SQL begin declare section end-exec; NUM char(4); NOM char(12); ADR char(20); LOC char(12); exec SQL end declare section end-exec;... exec SQL declare CURCLI cursor for select NCLI, NOM, ADRESSE from CLIENT where LOCALITE = :LOC end-exec;... LOC := ''; read(loc); while LOC <> '' do exec SQL open CURCLI end-exec; exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec; while SQLCODE = 0 do write(nom, ADR, LOC); exec SQL fetch CURCLI into :NUM,:NOM,:ADR end-exec; endwhile; exec SQL close CURCLI end-exec; endwhile;... DB-MAIN - Techniques SQL avancées ( FUNDP) 9.9
9. Interfaces ODBC et JDBC 9.5 Annexe : les API SQL 2. ODBC #include "stdinc.h" #include "common.h" #include <odbcinst.h> /* Stdinc.h contient les fonctions ODBC et les constantes pour l'utilisation des programmes ODBC */ #define MAX_DATA 300 #define MAX_ERROR_MSG 100 int WINAPI WinMain (HANDLE hinstance, HANDLE hprevinstance, LPSTR lpszcmdline, int ncmdshow) { /* Variables : */ /* *********** */ RETCODE rc; /* Code de retour pour fonctions ODBC */ HENV henv; /* Environment handle */ HDBC hdbc; /* Connection handle */ HSTMT hstmt; /* Statement handle */ char szdata[max_data];/* Variable pour récupérer résultats*/ SDWORD cbdata; /* Longueur variable résultats */ /* Variables résultats contenant Num, nom adresse du client */ char NUM[MAX_DATA+1], NOM[MAX_DATA+1], ADR[MAX_DATA+1]; /* Longueur variables résultats */ SWORD cbnum, cbnom, cbadr; char Loc[MAX_DATA+1]; /* Constantes : */ /* ************ */ /* Titre des MessageBox */ static char * SZMESSAGE_TITLE ="ODBC Message"; /* Requete de sélection */ char * szsqlselect = "select NCLI, NOM, ADRESSE \ from CLIENT where LOCALITE =?"; DB-MAIN - Techniques SQL avancées ( FUNDP) 9.10
9. Interfaces ODBC et JDBC /* Connexion au serveur : */ /* ********************** */ /* Allouer descripteur d'environnement */ SQLAllocEnv(&henv); /* Allouer un descripteur de connexion */ SQLAllocConnect(henv, &hdbc); /* Allouer un curseur */ rc=sqlsetconnectoption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC); /* Etablir une connexion avec la source de données */ rc = SQLConnect(hdbc, "Client Entry",SQL_NTS,NULL,0,NULL,0); if (rc!=sql_success) {/* Si la connexion a échoué, avertir l'utilisateur...*/ /* Déclaration des variables : */ char szsqlstate[6]; SDWORD nerr; char msg[sql_max_message_length]; SWORD cbmsg; else /* Affichage des paramètres liés à l'erreur : */ while(sqlerror(henv, hdbc, 0, szsqlstate, &nerr, msg, sizeof(msg), &cbmsg) == SQL_SUCCESS) { wsprintf(szdata, "Erreur dans la connexion\n\n SQLstate = %s\n Erreur = %ld\n Message = '%s'", szsqlstate, nerr, msg); MessageBox(NULL,szData,SZMESSAGE_TITLE,MB_OK); } goto abort; }/*fin de if (rc!=sql_success)*/ {/* On avertit l'utilisateur de l'heureux événement... */ MessageBox(NULL, "Connexion établie avec succès", SZMESSAGE_TITLE, MB_OK); }/*fin else (rc!=sql_success)*/ DB-MAIN - Techniques SQL avancées ( FUNDP) 9.11
9. Interfaces ODBC et JDBC /* Sélection */ /* ********* */ /* Instruction de sélection : */ rc = SQLAllocStmt(hdbc,&hstmt); rc = SQLSetCursorName(hstmt, "Curseur", SQL_NTS); SQLPrepare(hstmt, (UCHAR FAR*)szSQLSelect, SQL_NTS); /* demander la localité suivante (ou string vide) : */ printf("nom de localité : ");gets(loc) ; while (Loc[0]!= \n ) { SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_SQL_CHAR, 0, 0, &Loc, 12, NULL); /* Exécution de la requête : */ SQLExecute(hstmt); /* Récupération des résultats : */ SQLBindCol(hstmt,1,SQL_C_CHAR,NUM, MAX_DATA, &cbnum); SQLBindCol(hstmt,2,SQL_C_CHAR,NOM, MAX_DATA, &cbnom); SQLBindCol(hstmt,3,SQL_C_CHAR,ADR, MAX_DATA, &cbadr); rc=sqlfetch(hstmt); /*Placement du curseur*/ do { if (rc==sql_error) { /* Si erreur, avertir l'utilisateur... */ break; }/*fin du if (rc==sql_error)*/ sprintf(szdata, NUM, NOM, ADR); MessageBox(NULL, szdata, SZMESSAGE_TITLE, MB_OK); rc=sqlfetch(hstmt); } while(rc!= SQL_NO_DATA_FOUND); /*fin du do */ printf("nom de localité : ");gets(loc) ; }// fin du while */ DB-MAIN - Techniques SQL avancées ( FUNDP) 9.12
9. Interfaces ODBC et JDBC SQLFreeStmt(hstmt, SQL_DROP); /* Cloture et libération de l'espace mémoire (ABORT)*/ /* ************************************************* */ abort: /* Clôturer la connexion */ SQLDisconnect(hdbc); /* Libérer espace mémoire du descripteur de connexion */ SQLFreeConnect(hdbc); /* Libérer espace mémoire du descripteur d'environnement */ SQLFreeEnv(henv); } DB-MAIN - Techniques SQL avancées ( FUNDP) 9.13
9. Interfaces ODBC et JDBC 9.5 Annexe : les API SQL 3. JDBC import java.net.url; import java.sql.*; import java.io.* ; class client { public static void main (String args[]) { try { // Chargement du driver InterClient's // JDBC de Borland pour Interbase : Class.forName("interbase.interclient.Driver"); // Connexion à la base de données: String servername ="Maverick"; String database="client.gdb"; String url = "jdbc:interbase://" + servername + "/" + database; String username ="SYSDBA"; String password="masterkey"; String Loc ; Connection con = DriverManager.getConnection (url, username, password); // Affichage des informations: //--------------------------- String queryselect = "select NCLI, NOM, ADRESSE" +"from CLIENT where LOCALITE=?"; // Création d'un objet d'état permettant // d'exécuter la requête SQL : PreparedStatement stmt = con.preparestatement (queryselect); DB-MAIN - Techniques SQL avancées ( FUNDP) 9.14
9. Interfaces ODBC et JDBC // demander la localité suivante (ou string vide) System.out.println("Nom de localite? "); Loc = System.in.readln(); while (Loc!= "\n") { stmt.setstring(1, Loc); // Exécution d'une requête de sélection // et crétion de l'objet ResultSet ResultSet rs1 = stmt.executequery(); // Affichage des résultats : while (rsl.next()) { String Num = rs.getstring("ncli"); String Nom = rs.getstring("nom"); String Adr = rs.getstring("adresse"); System.out.println(">"+Num+" : "+Nom+ " : "+Adr); } } System.out.println("Nom de localite? "); Loc = System.out.readln(); // Destruction de l'objet résultat rs1 rs1.close(); // Fermeture de statement stmt.close(); } // Fermeture de connection con.close(); } } // Exception d'erreurs catch (SQLException ex) { // Gestion d une erreur SQL : System.out.println ("\n*** SQLException ***\n"); System.out.println ("SQLState:"+ex.getSQLState ()); System.out.println ("Message:"+ex.getMessage ()); } DB-MAIN - Techniques SQL avancées ( FUNDP) 9.15
Techniques SQL avancées 1. Rappel des notions de base de données 2. Intégrité des données 3. Transactions 4. Protection contre les incidents 5. Régulation de la concurrence 6. Les techniques SQL 7. Gestion de l intégrité 8. Domaines d application 9. Les interfaces ODBC et JDBC 10. Bibliographie
10. Bibliographie [Abdellatif,1995] Oracle 7 : Langages - Architecture - Administration Eyrolles, 1995 ISBN 2-212-08832-9 [Castano,1994] Castano, S., Fugini, M., Martella, G., Samarati, P., Database Security Addison-Wesley, 1994 ISBN 0-201-59375-0 ISBN 1-55860-396-4 [Celko,1995] Celko, J., SQL for the Smarties: Advanced SQL Programming Morgan Kaufmann, 1995 ISBN 1-55860-323-9 [Connolly,1995] Connolly, T., Begg, C., Strachan, A. Database Systems - A Practical Approach to Design, Implementation and Management Addison-Wesley, 1995 ISBN 0-201-42277-8 [Date,1985] Date, C., J., An Introduction to Database Systems - Volume II, Addison-Wesley, 1985 [Delmal,1998] Delmal, P., SQL 2 - Application à Oracle, Access et RDB, De Boeck Université, 1998 ISBN 2-8041-2995-0 DB-MAIN - Techniques SQL avancées ( FUNDP) 10.2
10. Bibliographie [Geiger, 1995] Geiger, K. Inside ODBC Microsoft Press, 1995 [Gray,1993] Gray, J., Reuter, A. Transaction Processing: Concepts and Techniques Morgan Kaufmann, 1993 ISBN 1-55860-190-2 [Hamilton, 1997] Hamilton, G., Cattel, R., Fisher, M. JDBC Database Access with java - A tutorial and annotated reference The Java Series, Addisson-Wesley, 1997 [Melton, 1998] Melton, J. Understanding SQL's Stored Procedures - A complete guide to SQL/PSM Morgan Kaufmann, 1998 ISBN 1-55860-461-8 [Miranda,1996] Miranda, S., Ruols, A. Client-Serveur - Moteurs SQL, Middleware et architectures parallèles Eyrolles, 1996 ISBN 2-212-08862-0 [Orfali,1996] Orfali, R., Harkey, D., Edwards, J., The Essential Distributed Objects Survival Guide Wiley, 1996 ISBN 0-471-12993-3 [Owens,1998] Owens, K., T., DB-MAIN - Techniques SQL avancées ( FUNDP) 10.3
10. Bibliographie Building Intelligent Databases with ORACLE PL/SQL, Triggers & Stored Procedures Prentice Hall, 1998 ISBN 0-13-443631-8 [Ozsu,1991] Özsu, M., T., Valduriez, P., Principles of Distributed Database Systems Prentice Hall, 1991 ISBN 0-13-691643-0 [Shasha,1992] Shasha, D., E. Database Tuning - A Principle Approach Prentice Hall, 1992 ISBN 0-12-205245-6 [Stonebraker,1994] Stonebraker, M., Readings in database Systems (Second Edition) Morgan Kaufmann, 1994 [Stonebraker, 1999] Stonebraker, M., Brown, P Object-Relational DBMSs Morgan Kaufmann, 1999 ISBN 1-55860-452-9 [Tate,1993] Tate, B., Malkemus, T., Gray, T. Comprehensive Database Performance for OS/2 2.0's Extended Services Van Nostrand Reinhold, 1993 ISBN 0-442-01325-6 [Widom,1995] Widom, J., Ceri, S., (Ed.) Active Database Systems Morgan Kaufmann, 1995 ISBN 1-55860-304-2 DB-MAIN - Techniques SQL avancées ( FUNDP) 10.4
10. Bibliographie DB-MAIN - Techniques SQL avancées ( FUNDP) 10.5