Vous êtes sur la page 1sur 79

Introduction au PL/SQL Oracle

Alexandre Mesl e 17 octobre 2011

Table des mati` eres


1 Notes de cours 1.1 Introduction au PL/SQL . . . . . . . . . . . . . . . . . 1.1.1 PL/SQL . . . . . . . . . . . . . . . . . . . . . . 1.1.2 Blocs . . . . . . . . . . . . . . . . . . . . . . . 1.1.3 Achage . . . . . . . . . . . . . . . . . . . . . 1.1.4 Variables . . . . . . . . . . . . . . . . . . . . . 1.1.5 Traitements conditionnels . . . . . . . . . . . . 1.1.6 Traitements r ep etitifs . . . . . . . . . . . . . . 1.2 Tableaux et structures . . . . . . . . . . . . . . . . . . 1.2.1 Tableaux . . . . . . . . . . . . . . . . . . . . . 1.2.2 Structures . . . . . . . . . . . . . . . . . . . . . 1.3 Utilisation du PL/SQL . . . . . . . . . . . . . . . . . . 1.3.1 Aectation . . . . . . . . . . . . . . . . . . . . 1.3.2 Tables et structures . . . . . . . . . . . . . . . 1.3.3 Transactions . . . . . . . . . . . . . . . . . . . 1.4 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . 1.4.1 Rattraper une exception . . . . . . . . . . . . . 1.4.2 Exceptions pr ed enies . . . . . . . . . . . . . . 1.4.3 Codes derreur . . . . . . . . . . . . . . . . . . 1.4.4 D eclarer et lancer ses propres exceptions . . . . 1.5 Sous-programmes . . . . . . . . . . . . . . . . . . . . . 1.5.1 Proc edures . . . . . . . . . . . . . . . . . . . . 1.5.2 Fonctions . . . . . . . . . . . . . . . . . . . . . 1.6 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1 Introduction . . . . . . . . . . . . . . . . . . . 1.6.2 Les curseurs . . . . . . . . . . . . . . . . . . . . 1.7 Curseurs parametr es . . . . . . . . . . . . . . . . . . . 1.7.1 Introduction . . . . . . . . . . . . . . . . . . . 1.7.2 D enition . . . . . . . . . . . . . . . . . . . . . 1.7.3 D eclaration . . . . . . . . . . . . . . . . . . . . 1.7.4 Ouverture . . . . . . . . . . . . . . . . . . . . . 1.7.5 Lecture dune ligne, fermeture . . . . . . . . . . 1.7.6 Boucle pour . . . . . . . . . . . . . . . . . . . . 1.7.7 Exemple r ecapitulatif . . . . . . . . . . . . . . 1.8 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8.1 Principe . . . . . . . . . . . . . . . . . . . . . . 1.8.2 Classication . . . . . . . . . . . . . . . . . . . 1.8.3 Cr eation . . . . . . . . . . . . . . . . . . . . . . 1.8.4 Acc` es aux lignes en cours de modication . . . 1.8.5 Contourner le probl` eme des tables en mutation 1.9 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . 1.9.1 Principe . . . . . . . . . . . . . . . . . . . . . . 1.9.2 Sp ecication . . . . . . . . . . . . . . . . . . . 1.9.3 Corps . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 3 3 3 4 4 5 5 6 8 8 8 9 10 10 11 11 11 13 13 13 15 15 15 17 17 17 17 17 17 18 18 19 19 19 19 20 22 25 25 25 25

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 Exercices 2.1 Introduction au PL/SQL . 2.2 Tableaux et Structures . . 2.3 Utilisation PL/SQL . . . 2.4 Exceptions . . . . . . . . 2.5 Sous-programmes . . . . . 2.6 Curseurs . . . . . . . . . . 2.7 Curseurs parametr es . . . 2.8 Triggers . . . . . . . . . . 2.9 Packages . . . . . . . . . . 2.10 R evisions . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

27 27 28 30 31 32 33 34 35 36 37 38 38 39 42 46 49 52 53 62 63 67 67 68 69 70 71 72 74 76 78

3 Corrig es 3.1 Introduction au PL/SQL . . . . . . . . 3.2 Tableaux et Structures . . . . . . . . . 3.3 Application du PL/SQL et Exceptions 3.4 Sous-programmes . . . . . . . . . . . . 3.5 Curseurs . . . . . . . . . . . . . . . . . 3.6 Curseurs param etr es . . . . . . . . . . 3.7 Triggers . . . . . . . . . . . . . . . . . 3.8 Packages . . . . . . . . . . . . . . . . . 3.9 R evisions . . . . . . . . . . . . . . . . A Scripts de cr eation de bases A.1 Livraisons Sans contraintes . . . . A.2 Modules et prerequis . . . . . . . . A.3 G eom etrie . . . . . . . . . . . . . . A.4 Livraisons . . . . . . . . . . . . . . A.5 Arbre g en ealogique . . . . . . . . . A.6 Comptes bancaires . . . . . . . . . A.7 Comptes bancaires avec exceptions A.8 Secr etariat p edagogique . . . . . . A.9 Mariages . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

Chapitre 1

Notes de cours
1.1
1.1.1

Introduction au PL/SQL
PL/SQL

Le PL de PL/SQL signie Procedural Language. Il sagit dune extension proc edurale du SQL permettant deectuer des traitements complexes sur une base de donn ees. Les possibilit es oertes sont les m emes quavec des langages imp eratifs (instructions en s equence) classiques. Ecrivez-le dans un editeur dont vous copierez le contenu dans SQL+. Un script ecrit en PL/SQL se termine obligatoirement par un /, sinon SQL+ ne linterpr` ete pas. Sil contient des erreurs de compilation, il est possible dacher les messages derreur avec la commande SQL+ : SHOW ERRORS.

1.1.2

Blocs

Tout code ecrit dans un langage proc edural est form e de blocs. Chaque bloc comprend une section de d eclaration de variables, et un ensemble dinstructions dans lequel les variables d eclar ees sont visibles. La syntaxe est DECLARE / d e c l a r a t i o n de v a r i a b l e s / BEGIN / i n s t r u c t i o n s a e x e c u t e r / END;

1.1.3

Achage

Pour acher le contenu dune variable, les proc edures DBMS OUTPUT.PUT() et DBMS OUTPUT.PUT LINE() prennent en argument une valeur ` a acher ou une variable dont la valeur est ` a acher. Par d efaut, les fonctions dachage sont desactiv ees. Il convient, ` a moins que vous ne vouliez rien voir sacher, de les activer avec la commande SQL+ SET SERVEROUTPUT ON.

1.1.4

Variables

Une variable se d eclare de la sorte : nom type [ : = initialisation ] ; Linitisation est optionnelle. Nous utiliserons les m emes types primitifs que dans les tables. Par exemple : SET SERVEROUTPUT ON DECLARE c varchar2 ( 1 5 ) := H e l l o World ! ; BEGIN DBMS_OUTPUT . PUT_LINE ( c ) ; END; / Les aectations se font avec la syntaxe variable := valeur ; 3

1.1.5

Traitements conditionnels

Le IF et le CASE fonctionnent de la m eme fa con que dans les autres langages imp eratifs : IF / c o n d i t i o n 1 / THEN / i n s t r u c t i o n s 1 / ELSE / i n s t r u c t i o n s 2 / END IF ; voire IF / c o n d i t i o n 1 / THEN / i n s t r u c t i o n s 1 / ELSIF / c o n d i t i o n 2 / / i n s t r u c t i o n s 2 / ELSE / i n s t r u c t i o n s 3 / END IF ; Les conditions sont les m emes quen SQL. Le switch du langage C simpl emente en PL/SQL de la fa con suivante : CASE / v a r i a b l e / W H E N / v a l e u r 1 / THEN / i n s t r u c t i o n s 1 / W H E N / v a l e u r 2 / THEN / i n s t r u c t i o n s 2 / ... W H E N / v a l e u r n / THEN / i n s t r u c t i o n s n / ELSE / i n s t r u c t i o n s par d e f a u t / END CASE;

1.1.6
LOOP

Traitements r ep etitifs

LOOP ... END LOOP ; permet dimpl ementer les boucles / i n s t r u c t i o n s / END LOOP ; Linstruction EXIT WHEN permet de quitter une boucle. LOOP / i n s t r u c t i o n s / EXIT W H E N / c o n d i t i o n / ; END LOOP ; La boucle FOR existe aussi en PL/SQL : FOR / v a r i a b l e / IN / i n f / . . / sup / LOOP / i n s t r u c t i o n s / END LOOP ; Ainsi que la boucle WHILE : WHILE / c o n d i t i o n / LOOP / i n s t r u c t i o n s / END LOOP ; Est-il possible, en bidouillant, dimpl ementer une boucle DO ... WHILE ?

1.2
1.2.1

Tableaux et structures
Tableaux

Cr eation dun type tableau Les types tableau doivent etre d enis explicitement par une d eclaration de la forme TYPE / t y p e / IS VARRAY ( / t a i l l e / ) OF / t y p e E l e m e n t s / ; type est le nom du type tableau cr ee par cette instruction taille est le nombre maximal d el ements quil est possible de placer dans le tableau. typeElements est le type des el ements qui vont etre stock es dans le tableau, il peut sagir de nimporte quel type. Par exemple, cr eons un type tableau de nombres indic e de 1 ` a 10, que nous appelerons numberTab TYPE numberTab IS VARRAY ( 1 0 ) OF N U M B E R;

D eclaration dun tableau Dor enavant, le type dun tableau peut etre utilis e au m eme titre que NUMBER ou VARCHAR2. Par exemple, d eclarons un tableau appel e t de type numberTab, DECLARE TYPE numberTab IS VARRAY ( 1 0 ) OF N U M B E R; t numberTab ; BEGIN / i n s t r u c t i o n s / END; /

Allocation dun tableau La cr eation dun type tableau met ` a disposition un constructeur du m eme nom que le type cr e e. Cette fonction r eserve de lespace m emoire pour ce tableau et retourne ladresse m emoire de la zone r eserv ee, il sagit dune sorte de malloc. Si, par exemple, un type tableau numtab a et e cr ee, la fonction numtab() retourne une tableau vide. DECLARE TYPE numberTab IS VARRAY ( 1 0 ) OF N U M B E R; t numberTab ; BEGIN t := numberTab ( ) ; / u t i l i s a t i o n du t a b l e a u / END; / Une fois cette allocation faite, il devient presque possible dutiliser le tableau... Dimensionnement dun tableau Le tableau retourn e par le constructeur est vide. Il convient ensuite de r eserver de lespace pour stocker les el ements quil va contenir. On utilise pour cela la m ethode EXTEND(). EXTEND sinvoque en utilisant la notation point ee. Par exemple, DECLARE TYPE numberTab IS VARRAY ( 1 0 ) OF N U M B E R; t numberTab ; BEGIN t := numberTab ( ) ; t . EXTEND ( 4 ) ; / u t i l i s a t i o n du t a b l e a u / END; /

Dans cet exemple, t.EXTEND(4) ; permet par la suite dutiliser les el ements du tableau t(1), t(2), t(3) et t(4). Il nest pas possible d etendre un tableau ` a une taille sup erieure ` a celle sp eci ee lors de la cr eation du type tableau associ e. Utilisation dun tableau On acc` ede, en lecture et en ecriture, au i-` eme el ement dune variable tabulaire nomm e T avec linstruction T(i). Les el ements sont indic es ` a partir de 1. Eectuons, par exemple, une permutation circulaire vers la droite des el ements du tableau t. DECLARE TYPE numberTab IS VARRAY ( 1 0 ) OF N U M B E R; t numberTab ; i number ; k number ; BEGIN t := numberTab ( ) ; t . EXTEND ( 1 0 ) ; FOR i IN 1 . . 1 0 LOOP t ( i ) := i ; END LOOP ; k := t ( 1 0 ) ; FOR i in REVERSE 2 . . 1 0 LOOP t ( i ) := t ( i 1 ) ; END LOOP ; t ( 1 ) := k ; FOR i IN 1 . . 1 0 LOOP DBMS_OUTPUT . PUT_LINE ( t ( i ) ) ; END LOOP ; END; /

1.2.2

Structures

Un structure est un type regroupant plusieurs types. Une variable de type structur e contient plusieurs variables, ces variables sappellent aussi des champs. Cr eation dun type structur e On d enit un type structur e de la sorte : TYPE / nomType / IS RECORD ( / l i s t e d e s champs / ); nomType est le nom du type structur e construit avec la syntaxe pr ec edente. La liste suit la m eme syntaxe que la liste des colonnes dune table dans un CREATE TABLE. Par exemple, construisons le type point (dans IR2 ), TYPE point IS RECORD ( abscisse N U M B E R , ordonnee N U M B E R ); Notez bien que les types servant ` a d enir un type structur e peuvent etre quelconques : variables scalaires, tableaux, structures, etc. D eclaration dune variable de type structur e point est maintenant un type, il devient donc possible de cr eer des variables de type point, la r` egle est toujours la m eme pour d eclarer des variables en PL/SQL, par exemple 6

p point ; permet de d eclarer une variable p de type point. Utilisation dune variable de type structur e Pour acc eder ` a un champ dune variable de type structur e, en lecture ou en ecriture, on utilise la notation point ee : v.c est le champ appel e c de la variable structur e appel ee v. Par exemple, DECLARE TYPE point IS RECORD ( abscisse N U M B E R , ordonnee N U M B E R ); p point ; BEGIN p . abscisse := 1 ; p . ordonnee := 3 ; DBMS_OUTPUT . PUT_LINE ( p . a b s c i s s e = | | p . abscisse | | and p . ordonnee = | | p . ordonnee ) ; END; / Le script ci-dessous cr ee le type point, puis cr ee une variable t de type point, et enn aecte aux champs abscisse et ordonnee du point p les valeurs 1 et 3.

1.3

Utilisation du PL/SQL

Ce cours est une introduction aux interactions possibles entre la base de donn ees et les scripts PL/SQL.

1.3.1

Aectation

On place dans une variable le r esultat dune requ ete en utilisant le mot-cl e INTO. Les instructions SELECT champ_1 , . . . , champ_n INTO v_1 , . . . , v_n F R O M ... aecte aux variables v 1, ..., v n les valeurs retourn ees par la requ ete. Par exemple DECLARE num N U M B E R; nom V A R C H A R 2( 3 0 ) := Poup e e Batman ; BEGIN SELECT numprod INTO num F R O M PRODUIT W H E R E nomprod = nom ; DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | | nom | | a pour num e ro | | num ) ; END; / Pr etez attention au fait que la requ ete doit retourner une et une une seule ligne, sinon, une erreur se produit ` a lex ecution.

1.3.2

Tables et structures

Si vous ne tenez pas ` a vous prendre la t ete pour choisir le type de chaque variable, demandez-vous ce que vous allez mettre dedans ! Si vous tenez ` a y mettre une valeur qui se trouve dans une colonne dune table, il est possible de vous r ef erer directement au type de cette colonne avec le type nomTable.nomColonne%type. Par exemple, DECLARE num PRODUIT . numprod%type ; nom PRODUIT . nomprod%type := Poup e e Batman ; BEGIN SELECT numprod INTO num F R O M PRODUIT W H E R E nomprod = nom ; DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | | nom | | a pour num e ro | | num ) ; END; / Pour aller plus loin, il est m eme possible de d eclarer une structure pour repr esenter une ligne dune table, le type porte alors le nom suivant : nomTable%rowtype. DECLARE nom PRODUIT . nomprod%type := Poup e e Batman ; ligne PRODUIT%rowtype ; BEGIN SELECT INTO ligne F R O M PRODUIT W H E R E nomprod = nom ; DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | | ligne . nomprod | | a pour num e ro | | ligne . numprod ) ; END; /

1.3.3

Transactions

Un des m ecanismes les plus puissants des SGBD r ecents r eside dans le syst` eme des transactions. Une transaction est un ensemble dop erations atomiques, cest-` a-dire indivisible. Nous consid ererons quun ensemble dop erations est indivisible si une ex ecution partielle de ces instructions poserait des probl` emes dint egrit e dans la base de donn ees. Par exemple, dans le cas dune base de donn ees de gestion de comptes en banque, un virement dun compte ` a un autre se fait en deux temps : cr editer un compte dune somme s, et d ebiter un autre de la m eme somme s. Si une erreur survient pendant la deuxi` eme op eration, et que la transaction est interrompue, le virement est incomplet et le patron va vous assassiner. Il convient donc de disposer dun m ecanisme permettant de se prot eger de ce genre de d esagr ement. Plut ot que se casser la t ete ` a tester les erreurs ` a chaque etape et ` a balancer des instructions permettant de revenir en arri` ere, nous allons utiliser les instructions COMMIT et ROLLBACK. Voici le squelette dun exemple : / i n s t r u c t i o n s / IF / e r r e u r / THEN ROLLBACK; ELSE C O M M I T; END; Le ROLLBACK annule toutes les modications faites depuis le d ebut de la transaction (donc depuis le pr ec edent COMMIT), COMMIT les enregistre d enitivement dans la base de donn ees. La variable denvironnement AUTOCOMMIT, qui peut etre positionn ee ` a ON ou ` a OFF permet dactiver la gestion des transactions. Si elle est positionn ee ` a ON, chaque instruction a des r epercussions imm ediates dans la base, sinon, les modications ne sont eectives quune fois quun COMMIT a et e ex ecut e.

1.4

Exceptions

Le m ecanisme des exceptions est impl ement e dans la plupart des langages r ecent, notament orient es objet. Cette fa con de programmer a quelques avantages imm ediats : obliger les programmeurs ` a traiter les erreurs : combien de fois votre prof de C a hurl e en vous suppliant de v erier les valeurs retourn ees par un malloc, ou un fopen ? La plupart des compilateurs des langages ` a exceptions (notamment java) ne compilent que si pour chaque erreur potentielle, vous avez pr epar e un bloc de code ( eventuellement vide...) pour la traiter. Le but est de vous assurer que vous navez pas oubli e derreur. Rattraper les erreurs en cours dex ecution : Si vous programmez un syst` eme de s ecurit e de centrale nucl eaire ou un pilote automatique pour laviation civile, une erreur de m emoire qui vous acherait l ecran bleu de windows, ou le message Envoyer le rapport derreur ?, ou plus simplement le fameux Segmentation fault produirait un eet des plus mauvais. Certaines erreurs d execution sont rattrapables, autrement dit, il est possible de r esoudre le probl` eme sans interrompre le programme. Ecrire le traitement des erreurs ` a part : Pour des raisons abilit e, de lisibilit e, il a et e consid er e que m elanger le code normal et le traitement des erreurs etait un style de programmation perfectible... Dans les langages ` a exception, les erreurs sont trait ees ` a part.

1.4.1

Rattraper une exception

Je vous ai menti dans le premier cours, un bloc en PL/SQL a la forme suivante : DECLARE / d e c l a r a t i o n s / BEGIN / i n s t r u c t i o n s / EXCEPTION / t r a i t e m e n t d e s e r r e u r s / END; Une exception est une erreur type, elle porte un nom, au m eme titre quune variable a une identicateur, par exemple GLUBARF. Lorsque dans les instructions, lerreur GLUBARF se produit, le code du BEGIN sinterrompt et le code de la section EXCEPTION est lanc e. On dit aussi que quand une exception est lev ee (raised) (on dit aussi jet ee (thrown)), on la rattrape (catch) dans le bloc EXCEPTION. La section EXCEPTION a la forme suivante : EXCEPTION W H E N E1 THEN / t r a i t e m e n t W H E N E2 THEN / t r a i t e m e n t W H E N E3 THEN / t r a i t e m e n t W H E N OTHERS THEN / t r a i t e m e n t END;

/ / / /

On enum` ere les erreurs les plus pertinentes en utilisant leur nom et en consacrant ` a chacune delle un traitement particulier pour rattraper (ou propager) lerreur. Quand un bloc est trait e, les WHEN suivants ne sont pas evalu es. OTHERS est lexception par d efaut, OTHERS est toujours v eri e, sauf si un cas pr ec edent a et e v eri e. Dans lexemple suivant : DECLARE / d e c l a r a t i o n s / BEGIN / i n s t r u c t i o n s / C O M M I T; EXCEPTION W H E N GLUBARF THEN ROLLBACK; DBMS_OUTPUT . PUT_LINE ( GLUBARF e x c e p t i o n r a i s e d ! ) ; W H E N OTHERS THEN DBMS_OUTPUT . PUT_LINE ( SQLCODE = | | SQLCODE ) ; DBMS_OUTPUT . PUT_LINE ( SQLERRM = | | SQLERRM ) ; 10

END; Les deux variables globales SQLCODE et SQLERRM contiennent respectivement le code derreur Oracle et un message derreur correspondant ` a la derni` ere exception lev ee. Chaque exception a donc, en plus dun nom, un code et un message.

1.4.2

Exceptions pr ed enies

Bon nombre dexceptions sont pr ed enies par Oracle, par exemple NO DATA FOUND est lev ee quand la requ ete dune instruction de la forme SELECT ... INTO ... ne retourne aucune ligne ee quand la requ ete dune instruction de la forme SELECT ... INTO ... retourne plusieurs TOO MANY ROWS est lev lignes DUP VAL ON INDEX est lev ee si une insertion (ou une modication) est refus ee ` a cause dune contrainte dunicit e. On peut enrichir notre exemple de la sorte : DECLARE num N U M B E R; nom V A R C H A R 2( 3 0 ) := Poup e e Batman ; BEGIN SELECT numprod INTO num F R O M PRODUIT W H E R E nomprod = nom ; DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | | nom | | a pour num e ro | | num ) ; EXCEPTION W H E N NO_DATA_FOUND THEN DBMS_OUTPUT . PUT_LINE ( Aucun a r t i c l e ne p o r t e l e nom | | nom ) ; W H E N TOO_MANY_ROWS THEN DBMS_OUTPUT . PUT_LINE ( P l u s i e u r s a r t i c l e s p o r t e n t l e nom | | nom ) ; W H E N OTHERS THEN DBMS_OUTPUT . PUT_LINE ( I l y a un g r o s p r o b l` eme . . . ) ; END; / SELECT numprod INTO num... l` eve une exception si la requ ete renvoie un nombre de lignes di erent de 1.

1.4.3

Codes derreur

Je vous encore menti, certaines exceptions nont pas de nom. Elle ont seulement un code derreur, il est conseill e de se reporter ` a la documentation pour les obtenir. On les traite de la fa con suivante EXCEPTION W H E N OTHERS THEN IF SQLCODE = CODE1 THEN / t r a i t e m e n t / ELSIF SQLCODE = CODE2 THEN / t r a i t e m e n t / ELSE DBMS_OUTPUT . PUT_LINE ( J v o i s pas c que ca peut et re . . . ) ; END; Cest souvent le cas lors de violation de contraintes.

1.4.4

D eclarer et lancer ses propres exceptions

Exception est un type, on d eclare donc les exceptions dans une section DECLARE. Une exception se lance avec linstruction RAISE. Par exemple,

11

DECLARE GLUBARF EXCEPTION; BEGIN RAISE GLUBARF ; EXCEPTION W H E N GLUBARF THEN DBMS_OUTPUT . PUT_LINE ( g l u b a r f r a i s e d . ) ; END; /

12

1.5
1.5.1

Sous-programmes
Proc edures

Syntaxe On d enit une proc edure de la sorte CREATE OR REPLACE PROCEDURE / nom / ( / p a r a m e t r e s / ) IS / d e c l a r a t i o n d e s v a r i a b l e s l o c a l e s / BEGIN / i n s t r u c t i o n s / END; les param` etres sont une simple liste de couples nom type. Par exemple, la procedure suivante ache un compte ` a rebours. CREATE OR REPLACE PROCEDURE compteARebours ( n N U M B E R) IS BEGIN IF n >= 0 THEN DBMS_OUTPUT . PUT_LINE ( n ) ; compteARebours ( n 1 ) ; END IF ; END;

Invocation En PL/SQL, une proc edure sinvoque tout simplement avec son nom. Mais sous SQL+, on doit utiliser le mot-cl e CALL. Par exemple, on invoque le compte ` a rebours sous SQL+ avec la commande CALL compteARebours(20). Passage de param` etres Oracle permet le passage de param` etres par r ef erence. Il existe trois types de passage de param` etres : IN : passage par valeur OUT : aucune valeur pass ee, sert de valeur de retour IN OUT : passage de param` etre par r ef erence Par d efaut, le passage de param` etre se fait de type IN. CREATE OR REPLACE PROCEDURE incr ( val IN OUT N U M B E R) IS BEGIN val := val + 1 ; END;

1.5.2
Syntaxe

Fonctions

On cr ee une nouvelle fonction de la fa con suivante : CREATE OR REPLACE FUNCTION / nom / ( / p a r a m e t r e s / ) RETURN / t y p e / IS / d e c l a r a t i o n d e s v a r i a b l e s l o c a l e s / BEGIN / i n s t r u c t i o n s / END; Linstruction RETURN sert ` a retourner une valeur. Par exemple, CREATE OR REPLACE FUNCTION module ( a N U M B E R , bN U M B E R) RETURN N U M B E R IS BEGIN IF a < b THEN RETURN a ; ELSE 13

RETURN module ( a b , b ) ; END IF ; END;

Invocation Tout comme les proc edures, linvocation des fonctions ne pose aucun probl` eme en PL/SQL, par contre, sous SQL+, cest quelque peu particulier. On passe par une pseudo-table nomm ee DUAL de la fa con suivante : SELECT module ( 2 1 , 1 2 ) F R O M DUAL ;

Passage de param` etres Les param` etres sont toujours pass es avec le type IN.

14

1.6
1.6.1

Curseurs
Introduction

Les instructions de type SELECT ... INTO ... manquent de souplesse, elles ne fontionnent que sur des requ etes retourant une et une seule valeur. Ne serait-il pas int eressant de pouvoir placer dans des variables le r esultat dune requ ete retournant plusieurs lignes ? A m editer...

1.6.2

Les curseurs

Un curseur est un objet contenant le r esultat dune requ ete (0, 1 ou plusieurs lignes). d eclaration Un curseur se d eclare dans une section DECLARE : CURSOR / nomcurseur / IS / r e q u e t e / ; Par exemple, si on tient ` a r ecup erer tous les employ es de la table EMP, on d eclare le curseur suivant. CURSOR emp_cur IS SELECT F R O M EMP ; Ouverture Lors de louverture dun curseur, la requ ete du curseur est evalu ee, et le curseur contient toutes les donn ees retourn ees par la requ ete. On ouvre un curseur dans une section BEGIN : OPEN / nomcurseur / ; Par exemmple, DECLARE CURSOR emp_cur IS SELECT F R O M EMP ; BEGIN OPEN emp_cur ; / U t i l i s a t i o n du c u r s e u r / END;

Lecture dune ligne Une fois ouvert, le curseur contient toutes les lignes du r esultat de la requ ete On les r ecup` ere une par une en utilisant le mot-cl e FETCH : FETCH / nom curseur / INTO / l i s t e v a r i a b l e s / ;

La liste de variables peut etre remplac ee par une structure de type nom curseur%ROWTYPE. Si la lecture de la ligne echoue, parce quil ny a plus de ligne ` a lire, lattribut %NOTFOUND prend la valeur vrai. DECLARE CURSOR emp_cur IS SELECT F R O M EMP ; ligne emp_cur%rowtype BEGIN OPEN emp_cur ; LOOP FETCH emp_cur INTO ligne ; EXIT W H E N emp_cur%NOTFOUND ; DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ; END LOOP ; / . . . / END;

15

Fermeture Apr` es utilisation, il convient de fermer le curseur. CLOSE / nomcurseur / ; Compl etons notre exemple, DECLARE CURSOR emp_cur IS SELECT F R O M EMP ; ligne emp_cur%rowtype ; BEGIN OPEN emp_cur ; LOOP FETCH emp_cur INTO ligne ; EXIT W H E N emp_cur%NOTFOUND ; DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ; END LOOP ; CLOSE emp_cur ; END; / Le programme ci-dessus peut aussi s ecrire DECLARE CURSOR emp_cur IS SELECT F R O M EMP ; ligne emp_cur%rowtype ; BEGIN OPEN emp_cur ; FETCH emp_cur INTO ligne ; WHILE emp_cur%FOUND LOOP DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ; FETCH emp_cur INTO ligne ; END LOOP ; CLOSE emp_cur ; END;

Boucle FOR Il existe une boucle FOR se chargeant de louverture, de la lecture des lignes du curseur et de sa fermeture, FOR ligne IN emp_cur LOOP / Traitement / END LOOP ; Par exemple, DECLARE CURSOR emp_cur IS SELECT F R O M EMP ; ligne emp_cur%rowtype ; BEGIN FOR ligne IN emp_cur LOOP DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ; END LOOP ; END; /

16

1.7
1.7.1

Curseurs parametr es
Introduction

A votre avis, le code suivant est-il valide ? DECLARE N U M B E R n := 1 4 ; BEGIN DECLARE CURSOR C IS SELECT F R O M PERSONNE W H E R E numpers >= n ; ROW C%rowType ; BEGIN FOR ROW IN C LOOP DBMS_OUTPUT . PUT_LINE ( ROW . numpers ) ; END LOOP ; END; END; / R eponse : non. La requ ete dun curseur ne peut pas contenir de variables dont les valeurs ne sont pas x ees. Pourquoi ? Parce que les valeurs des ces sont susceptibles de changer entre la d eclaration du curseur et son ouverture. Le rem` ede est un curseur param etr e.

1.7.2

D enition

Un curseur param etr e est un curseur dont la requ ete contient des variables dont les valeurs ne seront x ees qu` a louverture.

1.7.3

D eclaration

On pr ecise la liste des noms et des type des param` etres entre parenth` eses apr` es le nom du curseur : CURSOR / nom / ( / l i s t e d e s p a r a m` e t r e s / ) IS / r e q u e t e / Par exemple, cr eeons une requ ete qui, pour une personne donn ee, nous donne la liste des noms et pr enoms de ses enfants : CURSOR enfants ( numparent N U M B E R) IS SELECT F R O M PERSONNE W H E R E pere = numparent OR mere = numparent ;

1.7.4

Ouverture

On ouvre un curseur param etr e en passant en param` etre les valeurs des variables : OPEN / nom / ( / l i s t e d e s p a r a m` e t r e s / ) Par exemple, OPEN enfants ( 1 ) ;

1.7.5

Lecture dune ligne, fermeture

la lecture dune ligne suit les m emes r` egles quavec un curseur non param etr e. 17

1.7.6

Boucle pour

La boucle pour se charge de louverture, il convient donc de placer les param` etre dans lent ete de la boucle, FOR / v a r i a b l e / IN / nom / ( / l i s t e p a r a m` e t r e s / ) LOOP / i n s t r u c t i o n s / END LOOP ; Par exemple, FOR e IN enfants ( 1 ) LOOP DBMS_OUTPUT . PUT_LINE ( e . nompers | | END LOOP ; | | e . prenompers ) ;

1.7.7

Exemple r ecapitulatif
CURSOR parent IS SELECT F R O M PERSONNE ; p parent%rowtype ; CURSOR enfants ( numparent N U M B E R) IS SELECT F R O M PERSONNE W H E R E pere = numparent OR mere = numparent ; e enfants%rowtype ;

DECLARE

BEGIN FOR p IN parent LOOP DBMS_OUTPUT . PUT_LINE ( Les e n f a n t s de | | p . prenom | | | | p . nom | | s o n t : ) ; FOR e IN enfants ( p . numpers ) LOOP DBMS_OUTPUT . PUT_LINE ( | | e . prenom | | | | e . nom ); END LOOP ; END LOOP ; END; /

18

1.8
1.8.1

Triggers
Principe

Un trigger est une proc edure stock ee qui se lance automatiquement lorsquun ev enement se produit. Par ev enement, on entend dans ce cours toute modication des donn ees se trouvant dans les tables. On sen sert pour contr oler ou appliquer des contraintes quil est impossible de formuler de fa con d eclarative.

1.8.2

Classication

Type d ev enement Lors de la cr eation dun trigger, il convient de pr eciser quel est le type d ev enement qui le d eclenche. Nous r ealiserons dans ce cours des triggers pour les ev enements suivants : INSERT DELETE UPDATE Moment de l execution On pr ecise aussi si le trigger doit etre execut e avant (BEFORE) ou apr` es (AFTER) l ev enement. Ev enements non atomiques Lors que lon fait un DELETE ..., il y a une seule instruction, mais plusieurs lignes sont aect ees. Le trigger doit-il etre ex ecut e pour chaque ligne aect ee (FOR EACH ROW), ou seulement une fois pour toute linstruction (STATEMENT) ? un FOR EACH ROW TRIGGER est ex ecut e` a chaque fois quune ligne est aect ee. un STATEMENT TRIGGER est execut ee ` a chaque fois quune instruction est lanc ee.

1.8.3
Syntaxe

Cr eation

On d eclare un trigger avec linstruction suivante : CREATE OR REPLACE TRIGGER nomtrigger [ BEFORE | AFTER ] [ INSERT | DELETE | UPDATE] ON nomtable [ FOR EACH ROW | ] DECLARE / d e c l a r a t i o n s / BEGIN / i n s t r u c t i o n s / END; Par exemple, SQL> 2 3 4 5 6 CREATE OR REPLACE TRIGGER pasDeDeleteDansClient BEFORE DELETE ON CLIENT BEGIN RAISE_APPLICATION_ERROR ( 20555 , Va t e f a i r e . . . ) ; END; /

D e clencheur cr e e. SQL> SELECT C O U N T( ) 2 F R O M CLIENT ; C O U N T( ) 21 SQL> DELETE F R O M CLIENT ; 19

DELETE F R O M CLIENT ERREUR ` a la ligne 1 : ORA 20555: Va te faire . . . ORA 06512: ` a SCOTT.PASDEDELETEDANSCLIENT , ligne 2 ORA 04088: erreur lors d ex e cution du d e clencheur SCOTT.PASDEDELETEDANSCLIENT

SQL> SELECT C O U N T( ) 2 F R O M CLIENT ; C O U N T( ) 21 Linstruction RAISE APPLICATION ERROR(code, message) l` eve une exception sans nom portant un code code et un message derreur message. Vous remarquez que comme lerreur a et e lev ee avant la suppression, les donn ees sont toujours pr esentes dans la table CLIENT. Le trigger a contr ol e une r` egle, et comme elle n etait pas respect ee, il a lanc e une erreur. Combinaisons d ev enements Il est possible, en s eparant les types d ev enement par le mot-cl e OR, de d enir un trigger d eclench e par plusieurs ev enements. Les variables bool eennes INSERTING, UPDATING et DELETING permettent didentier l ev enement qui a d eclench e le trigger. CREATE OR REPLACE TRIGGER afficheEvenement BEFORE INSERT OR UPDATE OR DELETE ON CLIENT FOR EACH ROW BEGIN IF INSERTING THEN DBMS_OUTPUT . PUT_LINE ( I n s e r t i o n dans CLIENT ) ; ELSIF UPDATING THEN DBMS_OUTPUT . PUT_LINE ( Mise a j o u r dans CLIENT ) ; ELSE DBMS_OUTPUT . PUT_LINE ( S u p p r e s s i o n dans CLIENT ) ; END IF ; END;

1.8.4

Acc` es aux lignes en cours de modication

Dans les FOR EACH ROW triggers, il est possible avant la modication de chaque ligne, de lire lancienne ligne et la nouvelle ligne par linterm ediaire des deux variables structur ees :old et :new. Par exemple le trigger suivant emp eche de diminuer un salaire : CREATE OR REPLACE TRIGGER pasDeBaisseDeSalaire BEFORE UPDATE ON EMP FOR EACH ROW BEGIN IF ( : old . sal > : new . sal ) THEN RAISE_APPLICATION_ERROR ( 20567 , Pas de b a i s s e de s a l a i r e ! ) ; END IF ; END;

Tables en mutation Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la table en cours de modication.

20

SQL> 2 3 4 5 6 7 8 9

CREATE OR REPLACE TRIGGER beforeStatement BEFORE UPDATE ON CLIENT DECLARE NB N U M B E R; BEGIN SELECT C O U N T( ) INTO NB F R O M CLIENT ; END; /

D e clencheur cr e e. SQL> SQL> 2 3 4 5 6 7 8 9

CREATE OR REPLACE TRIGGER afterStatement AFTER UPDATE ON CLIENT DECLARE NB N U M B E R; BEGIN SELECT C O U N T( ) INTO NB F R O M CLIENT ; END; /

D e clencheur cr e e. SQL> SQL> UPDATE CLIENT SET nomcli = nomcli ; 21 ligne ( s ) mise ( s ) ` a jour . SQL> SQL> 2 3 4 5 6 7 8 9 10

CREATE OR REPLACE TRIGGER beforeForEachRow BEFORE UPDATE ON CLIENT FOR EACH ROW DECLARE NB N U M B E R; BEGIN SELECT C O U N T( ) INTO NB F R O M CLIENT ; END; /

D e clencheur cr e e. SQL> SQL> UPDATE CLIENT SET nomcli = nomcli ; UPDATE CLIENT SET nomcli = nomcli ERREUR ` a la ligne 1 : ORA 04091: la table SCOTT . CLIENT est en mutation ; le d e clencheur ou la fonction ne peut la voir ORA 06512: ` a SCOTT.BEFOREFOREACHROW , ligne 4 ORA 04088: erreur lors d ex e cution du d e clencheur SCOTT.BEFOREFOREACHROW

SQL> DROP TRIGGER beforeForEachRow ; D e clencheur supprim e.

21

SQL> SQL> SQL> 2 3 4 5 6 7 8 9 10

CREATE OR REPLACE TRIGGER afterForEachRow AFTER UPDATE ON CLIENT FOR EACH ROW DECLARE NB N U M B E R; BEGIN SELECT C O U N T( ) INTO NB F R O M CLIENT ; END; /

D e clencheur cr e e. SQL> SQL> UPDATE CLIENT SET nomcli = nomcli ; UPDATE CLIENT SET nomcli = nomcli ERREUR ` a la ligne 1 : ORA 04091: la table SCOTT . CLIENT est en mutation ; le d e clencheur ou la fonction ne peut la voir ORA 06512: ` a SCOTT.AFTERFOREACHROW , ligne 4 ORA 04088: erreur lors d ex e cution du d e clencheur SCOTT.AFTERFOREACHROW

1.8.5

Contourner le probl` eme des tables en mutation

Il existe plusieurs fa cons de contourner ce probl` eme : Utiliser un STATEMENT trigger. Comme on ne sait pas quelles lignes ont et e modi ees, on est oblig e de toutes les traiter. Cette approche pr esente donc un inconv enient majeur : elle nous am` ene ` a eectuer de nombreux traitements inutiles. En ayant des donn ees redondantes. Il sut que les donn ees servant ` a la v erication se trouvent dans une autre table que celle en mutation. Cette m ethode a pour inconv enient la m emoire occup ee et la quantit e de code ` a ecrire pour maintenir la coh erence des donn ees. Dans la plupart des cas, cette solution est malgr e tout la meilleure. Colonnes suppl ementaires Par exemple, si lon souhaite emp echer un client davoir plus de 10 comptes en banque, une solution est de placer dans la table client une colonne contenant le nombre de comptes. ALTER TABLE CLIENT A D D nbComptes number ; UPDATE CLIENT SET nbComptes = 0 ; Une fois cette table cr ee, il convient de sassurer que les donn ees de la colonne nbComptes contient toujours les bonnes valeurs. On le fait avec plusieurs sous-programmes : CREATE OR REPLACE TRIGGER metAJourNbComptes AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT BEGIN UPDATE CLIENT SET nbComptes = ( SELECT C O U N T( ) F R O M COMPTECLIENT CC W H E R E CC . numCli = numCli ); END; / CREATE OR REPLACE TRIGGER verifieNbComptes

22

BEFORE INSERT ON COMPTECLIENT FOR EACH ROW DECLARE nbComptes N U M B E R; BEGIN SELECT nbComptes INTO nbComptes F R O M CLIENT W H E R E numCli = : new . numcli ; IF ( nbComptes >= 1 0 ) THEN RAISE_APPLICATION_ERROR ( 20556 , Ce c l i e n t a d e j a t r o p de comptes ) ; END IF ; END; / On peut aner en rempla cant metAJourNbComptes par plusieurs sous-programmes : CREATE OR REPLACE TRIGGER initialiseNbComptes BEFORE INSERT ON CLIENT FOR EACH ROW BEGIN : new . nbComptes := 0 ; END; / CREATE OR REPLACE TRIGGER metAJourNbComptes AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT FOR EACH ROW BEGIN IF DELETING OR UPDATING THEN UPDATE CLIENT SET nbComptes = nbComptes 1 W H E R E numcli = : old . numcli ; END IF ; IF INSERTING OR UPDATING THEN UPDATE CLIENT SET nbComptes = nbComptes + 1 W H E R E numcli = : new . numcli ; END IF ; END; /

Tables suppl ementaires Si lon souhaite par exemple emp echer les circuits dans la table PERSONNE, il est n ecessaire de faire un parcours de graphe. Ce qui n ecessite des SELECT dans la table en cours de mutation. La seule solution est dans ce cas davoir une table miroir qui contient les colonnes cl es primaire et etrang` eres de cette table, et de sen servir pour d etecter les circuits. CREATE TABLE MIRRORPERSONNE ( numpers N U M B E R PRIMARY KEY, pere N U M B E R , mere N U M B E R ); Nous allons ensuite proc eder de m eme, en r epercutant chaque op eration de PERSONNE sur MIRRORPERSONNE. CREATE OR REPLACE TRIGGER miseAJourMirrorPersonne BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE FOR EACH ROW BEGIN IF DELETING OR UPDATING THEN 23

DELETE F R O M MIRRORPERSONNE W H E R E numpers = : old . numpers ; END IF ; IF INSERTING OR UPDATING THEN INSERT INTO MIRRORPERSONNE VALUES ( : new . numpers , : new . pere , : new . mere ) ; END IF ; END; / Une fois cela fait, il sut de rechercher si une personne ins er ee est une descendante delle m eme dans MIRRORPERSONNE. CREATE OR REPLACE FUNCTION trouveCircuit ( current N U M B E R , toFind N U M B E R) RETURN BOOLEAN IS numPere N U M B E R; numMere N U M B E R; BEGIN IF ( current IS NULL) THEN RETURN FALSE ; END IF ; SELECT pere , mere INTO numPere , numMere F R O M MIRRORPERSONNE W H E R E numPers = current ; RETURN ( numPere = toFind OR numMere = toFind OR trouveCircuit ( numPere , toFind ) OR trouveCircuit ( numMere , toFind ) ) ; END; / CREATE OR REPLACE TRIGGER verifieCircuit AFTER UPDATE OR INSERT ON PERSONNE FOR EACH ROW BEGIN IF ( trouveCircuit ( : new . numPers , : new . numPers ) ) THEN RAISE_APPLICATION_ERROR ( 20557 , C i r c u i t dans l a r b r e g en ealogique . ) ; END IF ; END; /

24

1.9
1.9.1

Packages
Principe

Un package est un ensemble de sous-programmes et de variables form e par Une sp ecication : d eclaration de variables et de sous-programmes Un corps : impl ementation des sous-programmes Tout ce qui se trouve dans la sp ecication doit se trouver dans le corps, mais la r eciproque est fausse. Un package satisfait les points suivants : encapsulation : certains traitements sont masqu es, seule la sp ecication du package est visible. Cela a pour avantage de simplier la t ache de celui qui va utiliser le package. modularit e : il est possible de d evelopper s epar ement les diverses parties de lapplication. le d eveloppement devient ainsi un assemblage de package. Ces deux aspects fournissent une souplesse certaine au niveau du d eveloppement : il est possible de modier le corps dun package sans changer sa sp ecication, donc sans modier le fonctionnement de lapplication.

1.9.2

Sp ecication

La syntaxe permettant de cr eer lent ete est la suivante : CREATE OR REPLACE PACKAGE nompackage IS / declarations / END nomPackage ; / Par exemple, CREATE OR REPLACE PACKAGE compteur IS procedure reset ; function nextValue return number ; END compteur ; /

1.9.3

Corps

La syntaxe permettant de cr eer le corps est la suivante : CREATE OR REPLACE PACKAGE BODY nompackage IS / implementation / END nomPackage ; / Par exemple, CREATE OR REPLACE PACKAGE BODY compteur IS cpt N U M B E R := 0 ; PROCEDURE reset IS BEGIN cpt := 0 ; END; FUNCTION nextValue RETURN N U M B E R IS BEGIN cpt := cpt + 1 ; RETURN cpt 1 ; END; END compteur ; 25

/ On peut utiliser un package depuis nimporte quel script PL/SQL : DECLARE nb N U M B E R; BEGIN FOR nb IN 4 . . 2 0 LOOP DBMS_OUTPUT . PUT_LINE ( COMPTEUR . nextValue ( ) ) ; END LOOP ; COMPTEUR . RESET ( ) ; FOR nb IN REVERSE 0 . . 1 0 LOOP DBMS_OUTPUT . PUT_LINE ( COMPTEUR . nextValue ( ) ) ; END LOOP ; END; /

26

Chapitre 2

Exercices
2.1 Introduction au PL/SQL

Exercice 1
Ecrivez un programme aectant les valeurs 1 et 2 ` a deux variables a et b, puis permutant les valeurs de ces deux variables.

Exercice 2
Ecrivez un programme pla cant la valeur 10 dans une variable a, puis achant la factorielle de a.

Exercice 3
Ecrivez un programme pla cant les valeurs 48 et 84 dans deux variables a et b puis achant le pgcd de a et b.

27

2.2

Tableaux et Structures

Exercice 1
1. Cr eez un type tableau pouvant contenir jusqu` a 50 entiers. 2. Cr eez une variable de ce type , faites une allocation dynamique et dimensionnez ce tableau ` a 20 emplacements. 3. Placez dans ce tableau la liste des 20 premiers carr es parfaits : 1, 4, 9, 16, 25, . . . 4. Inversez lordre des el ements du tableau 5. Achez le tableau.

Exercice 2
Triez le tableau pr ec edent avec la m ethode du tri ` a bulle.

Exercice 3
Recherchez, par dichotomie, si l el ement 225 se trouve dans le tableau.

Exercice 4
On impl emente des listes cha n ees avec des tableaux de la sorte, SET SERVEROUTPUT ON DECLARE -- Maillon dune liste cha^ n ee TYPE CELL IS RECORD ( -- Donn ee de chaque maillon data INTEGER, -- Indice du maillon pr ec edent de la liste, -- -1 sil ny en a pas previous INTEGER, -- Indice du maillon suivant de la liste, -- -1 sil ny en a pas next INTEGER ); -- Type tableau contenant les maillons de la liste TYPE TREE IS VARRAY (19) OF CELL; -- Tableau contenant les maillons de la liste t TREE; -- indice du premier el ement de la liste first integer; -- indice du dernier el ement de la liste last integer; BEGIN t := TREE(); t.extend(19); -- Initialisation FOR i IN 1..19 LOOP t(i).data := power(i, 5) mod 19 ; t(i).previous := i-1; t(i).next := i+1; END LOOP; first := 1; last := 19; t(first).previous := -1; t(last).next := -1;

28

-- Affichage DECLARE p integer := first; BEGIN WHILE p <> -1 LOOP DBMS_OUTPUT.PUT_LINE(( || p || , || t(p).data || , || t(p).previous || , || t(p).next || )); p := t(p).next; END LOOP; END; /* Ecrivez la suite vous-m^ eme... */ END; / Inversez lordre des el ements de la liste, sans changer les indices des maillons (seulement en modiant le cha nage).

Exercice 5
Utilisez le tri ` a bulle pour remettre les el ements dans lordre. Les indications sont les m emes : ne d eplacez pas les maillons, vous navez le droit de toucher quau cha nage. Bon courage, laspirine nest pas fournie.

29

2.3

Utilisation PL/SQL

Nous travaillerons sur les donn ees A.6 et A.5. Vous noublierez pas de placer des commit en des lieux bien choisis.

Exercice 1
Vous remarquerez que les valeurs des numpers de la table PERSONNE forment une s equence de nombres de 1 ` a 21. Utilisez une boucle dans laquelle vous placerez une requ ete pour recopier les couples nom/pr enom de la table personne dans la table CLIENT.

Exercice 2
Ecrivez un script r ecup erant le client de cl e primaire la plus elev ee, et injectant ce client dans la table PERSONNEL.

Exercice 3
Ouvrez un compte courant pour chaque personne, eectuez un d ep ot en esp` ece egal ` a numpers 100 euros.

Exercice 4
Ouvrez un livret pour chaque personne ayant un numpers pair, faites un virement de leur compte courant vers ce livret de sorte quil ne reste plus que 500 sur leur compte.

30

2.4

Exceptions

Nous utiliserons les donn ees de A.7 et A.5 Vous etes invit es ` a modier le code de la s eance pr ec edente. Chaque fois quun SELECT ... INTO ... sera eectu e, vous rattraperez les exceptions NO DATA FOUND et TOO MANY ROWS. A chaque insertion, vous ratrapperez lexception DUP VAL ON INDEX.

Exercice 1
Faites de sorte que les scripts important les donn ees des tables CLIENT ne puissent etre ex ecut es quune seule fois.

Exercice 2
Les scripts remplissant la table Operation ne fonctionneront pas aujourdhui... M eme sil fonctionnaient la derni` ere fois. Trouvez les codes derreurs des exceptions lev ees par ces scripts, rattrapez-les de la fa con la plus appropri ee qui soit.

31

2.5

Sous-programmes

Exercice 1
Ecrire une fonction r ecursive retournant bn , avec n entier positif ou nul.

Exercice 2
Am eliorer la fonction pr ec edente en utilisant le fait que bn = (b2 ) 2 si n est pair. Pour les questions suivantes, utilisez les donn ees de A.5.
n

Exercice 3
Ecrire une fonction demi-freres prenant deux num eros de personnes en param` etre et retournant vrai si et seulement si ces deux personnes ont un parent en commun.

Exercice 4
Ecrire une fonction cousins germains prenant deux num eros de personnes en param` etre et retournant vrai si et seulement si ces deux deux individus sont cousins germains.

Exercice 5
Ecrire une proc edure r ecursive achant le nom de la personne dont le num ero est pass e en param` etre et se rappellant r ecursivement sur le p` ere de cette personne. Faites de sorte ` a ne pas utiliser dexceptions.

Exercice 6
Ecrire une proc edure r ecursive achant les noms des ascendants de sexe masculin de la personne dont le num ero est pass e en param` etre.

Exercice 7
Ecrire une fonction r ecursive prenant deux num eros de personne A et B et retournant vrai si A est un ascendant de B .

Exercice 8
Ecrire une fonction prenant en param` etre deux num eros de personne A et B et retournant, si lun est un ascendant de lautre, le nombre de g en erations les s eparant, 1 si lun nest pas un ascendant de lautre.

Exercice 9
Pr eparez un verre daspirine et ecrivez une requ ete retournant le(s) couples(s) personnes s epar ees par le plus de g en erations.

Exercice 10
Reprendre le code du tp pr ec edent, le d ecouper en sous-programmes de la fa con la moins inintelligente possible. Bon courage.

32

2.6

Curseurs

Exercice 1
Refaites les exercices de 2.3 en utilisant les curseurs.

Exercice 2
En utlisant les donnees A.5, ecrivez une fonction achant toute la descendance dune personne.

33

2.7

Curseurs parametr es

Lint er et de ces exercices etant de vous familiariser avec les curseurs param etr es, vous ferez en sorte de ne pas contourner leur usage. Nous utiliserons les donn ees de A.6

Exercice 1
Ecrire une proc edure qui ache tous les clients, et pour chaque client, la liste des comptes.

Exercice 2
Ecrire une proc edure qui ache tous les clients, et pour chaque client, la liste des comptes, et pour chacun de ces comptes, lhistorique des op erations.

34

2.8

Triggers

Impl ementez les contraintes suivantes dans les donn ees de les donn ees de A.8. Vous ferez des sous-programmes tenant sur une page, et ne contenant pas plus de trois niveaux dimbrication. Vous r epertorierez les num eros derreurs que vous aecterez a ` chaque lev ee dexception. 1. Il ne doit pas etre possible de modier la note min dans la table prerequis. 2. Dans un module, il ne doit pas y avoir plus de effecMax el` eves inscrits. 3. On ne peut cr eer un examen pour un module que sil y a des el` eves inscrits dans ce module. 4. Un el` eve ne peut passer un examen que si sa date dinscription est ant erieure ` a la date de lexamen. 5. Il ne doit pas y avoir de circuit dans la table prerequis (il existe une fa con de la v erier en PL/SQL, mais comme vous ne la connaissez pas, faites un parcours en profondeur du graphe des pr e-requis) 6. Un el` eve sinscrivant ` a un module doit avoir eu au moins la note min ` a tous les modules pr e-requis. 7. Ajouter dans etudiant un champ moyenne, celui-ci contiendra la moyenne de chaque etudiant sil a pass e les examens de tous les modules dans lesquels il est inscrit. 8. Revenez sur la premi` ere contrainte : il ne doit etre possible de modier une note min dans la table prerequis que sil nexiste pas d el` eve dont une inscription serait invalid ee. 9. Il ne doit etre possible de modier effecMax que si des etudiants ne se retrouvent pas avec une inscription invalid ee. Libre ` a vous par la suite de trouver dautres contraintes et de les impl ementer.

35

2.9

Packages

Exercice 1
Lancez deux sessions simultan ement sur le m eme serveur et invoquez les sous-programmes du package compteur depuis chacune des sessions. Que remarquez-vous ?

Exercice 2
Impl ementer le corps du package suivant (utilisez les donn ees de A.5).
CREATE OR R E P L A C E P A C K A G E g e s t i o n _ a r b r e I S c i r c u i t exception ; c u r s o r f e u i l l e s r e t u r n p e r s o n n e %r o w t y p e ; p r o c e d u r e a j o u t e P e r s o n n e ( n o m p e r s o n n e . n o m%t y p e , p r e n o m p e r s o n n e . p r e n o m%t y p e , p e r e p e r s o n n e . p e r e%t y p e , m e r e p e r s o n n e . m e r e%t y p e ) ; p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . n u m p e r s%t y p e , n u m P e r e p e r s o n n e . p e r e%t y p e , n u m M e r e p e r s o n n e . m e r e%t y p e ) ;

END g e s t i o n _ a r b r e ; /

36

2.10

R evisions

Impl ementez les contraintes suivantes dans les donn ees de A.9. 1. Les parents dune m eme personne sont des personnes di erentes. 2. Larbre g en ealogique ne contient pas de circuit. 3. Les dates de divorce sont ult erieures aux dates de mariage. 4. Une m eme personne ne peut pas etre mari ee ` a plusieurs personnes simultan ement. 5. Personne ne peut etre p` ere dune personne et m` ere dune autre. 6. Un mari ne peut pas etre m` ere et une femme ne peut pas etre p` ere. 7. Deux personnes ayant du sang en commun ne peuvent se marier.

37

Chapitre 3

Corrig es
3.1
DECLARE a N U M B E R; b N U M B E R; t N U M B E R; BEGIN a := 1 ; b := 2 ; DBMS_OUTPUT DBMS_OUTPUT DBMS_OUTPUT t := a ; a := b ; b := t ; DBMS_OUTPUT DBMS_OUTPUT END; / E x e r c i c e 2 DECLARE a N U M B E R; res N U M B E R; counter N U M B E R; BEGIN a := 1 0 ; r e s := 1 ; c o u n t e r := a ; WHILE counter > 0 LOOP r e s := r e s c o u n t e r ; c o u n t e r := c o u n t e r 1 ; END L O O P ; D B M S _ O U T P U T . P U T _ L I N E ( a | | != | | r e s ) ; END; / E x e r c i c e 3 DECLARE a N U M B E R := 4 8 ; b N U M B E R := 8 4 ; amodb N U M B E R; BEGIN D B M S _ O U T P U T . P U T ( PGCD( | | a | | , | | b | | ) = ) ; WHILE b > 0 LOOP a m o d b := a ; W H I L E a m o d b >= b L O O P a m o d b := a m o d b b ; END L O O P ; a := b ; b := a m o d b ; END L O O P ; DBMS_OUTPUT . PUT_LINE ( a ) ; END; / . PUT_LINE ( a = | | a ) ; . PUT_LINE ( b = | | b ) ; . P U T _ L I N E ( Let s swap a and b . . . The r e s u l t

Introduction au PL/SQL

E x e r c i c e 1

is : );

. PUT_LINE ( a = | | a ) ; . PUT_LINE ( b = | | b ) ;

38

3.2

Tableaux et Structures

SET S E R V E R O U T P U T O N Tableaux DECLARE T Y P E m o n t a b I S V A R R A Y ( 5 0 ) O F INTEGER ; t montab ; BEGIN t := m o n t a b ( ) ; t . extend ( 2 0 ) ; I n i t i a l i s a t i o n F O R i IN 1 . . 2 0 L O O P t ( i ) := i i ; END L O O P ; I n v e r s i o n de l o r d r e d e s e l ements DECLARE temp i n t e g e r ; BEGIN F O R i IN 1 . . 1 0 L O O P t e m p := t ( i ) ; t ( i ) := t (20 i + 1 ) ; t (20 i +1) := t e m p ; END L O O P ; END; A f f i c h a g e F O R i IN 1 . . 2 0 L O O P DBMS_OUTPUT . PUT_LINE ( t ( | | i || ) = || t(i )); END L O O P ; Tri ` a bulle DECLARE temp i n t e g e r ; BEGIN F O R i IN R E V E R S E 2 . . 2 0 L O O P F O R j IN 2 . . i L O O P IF t ( j 1) > t ( j ) T H E N t e m p := t ( j ) ; t ( j ) := t ( j 1 ) ; t ( j 1) := t e m p ; END I F ; END L O O P ; END L O O P ; END; A f f i c h a g e F O R i IN 1 . . 2 0 L O O P DBMS_OUTPUT . PUT_LINE ( t ( | | i || ) = || t(i )); END L O O P ; Recherche par d i c h o t o m i e de l e l e m e n t 225 DECLARE i n f INTEGER := 1 ; s u p INTEGER := 2 0 ; m INTEGER ; X INTEGER := 4 0 0 ; BEGIN LOOP DBMS_OUTPUT . PUT_LINE ( i n f = | | inf ; sup = | | s u p ) ; m := ( i n f + s u p ) / 2 ; EXIT W H E N t ( m ) = X OR i n f = s u p ; IF t ( m ) > X T H E N s u p := m 1; ELSE i n f := m +1; END I F ; END L O O P ; IF t ( m ) = X T H E N DBMS_OUTPUT . PUT_LINE ( X | | e s t dans l e t a b l e a u ) ; ELSE DBMS_OUTPUT . PUT_LINE ( X | | n e s t pas dans l e t a b l e a u ) ; END I F ; END; END; /

||

39

S t r u c t u r e s DECLARE M a i l l o n d une l i s t e c h a n ee TYPE CELL IS RECORD ( Donn ee de chaque m a i l l o n d a t a INTEGER, I n d i c e du m a i l l o n p r e c e d e n t de l a l i s t e , 1 s i l n y en a pas p r e v i o u s INTEGER, I n d i c e du m a i l l o n s u i v a n t de l a l i s t e , 1 s i l n y en a pas next INTEGER ); Type t a b l e a u c o n t e n a n t l e s m a i l l o n s de l a l i s t e TYPE TREE IS VARRAY ( 1 9 ) OF CELL ; Tableau c o n t e n a n t l e s m a i l l o n s de l a l i s t e t TREE ; i n d i c e du premier e l e m e n t de l a l i s t e first integer ; i n d i c e du d e r n i e r e l e m e n t de l a l i s t e last integer ; BEGIN t := T R E E ( ) ; t . extend ( 1 9 ) ; I n i t i a l i s a t i o n F O R i IN 1 . . 1 9 L O O P t ( i ) . d a t a := p o w e r ( i , 5 ) m o d 19 ; t ( i ) . p r e v i o u s := i 1; t ( i ) . next := i +1; END L O O P ; f i r s t := 1 ; l a s t := 1 9 ; t ( f i r s t ) . p r e v i o u s := 1; t ( l a s t ) . next := 1; A f f i c h a g e DECLARE p i n t e g e r := f i r s t ; BEGIN W H I L E p <> 1 L O O P DBMS_OUTPUT . PUT_LINE ( ( | | p | | t ( p ) . data | | , | | t ( p ) . previous | | , | | t ( p ) . next | | ) ) ; p := t ( p ) . next ; END L O O P ; END; I n v e r s i o n de l o r d r e d e s e l ements DECLARE t e m p INTEGER ; BEGIN F O R i IN 1 . . 1 9 L O O P t e m p := t ( i ) . p r e v i o u s ; t ( i ) . p r e v i o u s := t ( i ) . next ; t ( i ) . next := t e m p ; END L O O P ; f i r s t := 1 9 ; l a s t := 1 ; END; A f f i c h a g e DECLARE p i n t e g e r := f i r s t ; BEGIN W H I L E p <> 1 L O O P DBMS_OUTPUT . PUT_LINE ( ( | | p || , || t ( p ) . data | | , | | t ( p ) . previous | | , t ( p ) . next | | ) ) ; p := t ( p ) . next ; END L O O P ; END;

||

||

Tri ` a bulle DECLARE i i n t e g e r := l a s t ; j integer ; BEGIN W H I L E t ( t ( i ) . p r e v i o u s ) . p r e v i o u s <> 1 L O O P j := f i r s t ; W H I L E i< >j L O O P I F ( t ( j ) . d a t a > t ( t ( j ) . next ) . d a t a ) T H E N

40

Echange de j e t t ( j ) . n e x t par m o d i f i c a t i o n du c h a nage DECLARE a f t e r J INTEGER := t ( j ) . next ; b e f o r e J INTEGER := t ( j ) . p r e v i o u s ; BEGIN t ( j ) . next := t ( a f t e r J ) . next ; t ( a f t e r J ) . next := j ; t ( a f t e r J ) . p r e v i o u s := b e f o r e J ; t ( j ) . p r e v i o u s := a f t e r J ; I F t ( j ) . next <> 1 T H E N t ( t ( j ) . next ) . p r e v i o u s := j ; ELSE l a s t := j ; END I F ; I F t ( a f t e r J ) . p r e v i o u s <> 1 T H E N t ( t ( a f t e r J ) . p r e v i o u s ) . next := a f t e r J ; ELSE f i r s t := a f t e r J ; END I F ; IF afterJ = i T H E N i := j ; END I F ; END; ELSE j := t ( j ) . next ; END I F ; END L O O P ; i := t ( i ) . p r e v i o u s ; END L O O P ; END; A f f i c h a g e DECLARE p i n t e g e r := f i r s t ; BEGIN W H I L E p <> 1 L O O P DBMS_OUTPUT . PUT_LINE ( ( | | p | | t ( p ) . data | | , | | t ( p ) . previous | | , | | t ( p ) . next | | ) ) ; p := t ( p ) . next ; END L O O P ; END; END; /

||

41

3.3

Application du PL/SQL et Exceptions

SET S E R V E R O U T P U T O N SET A U T O C O M M I T O F F E x e r c i c e 1 DECLARE u n C l i e n t P E R S O N N E %R O W T Y P E ; n u m C l i e n t P E R S O N N E . n u m p e r s%t y p e ; Y _ A _ E U _ U N E _ M E R D E EXCEPTION; BEGIN F O R n u m C l i e n t IN 1 . . 2 1 L O O P BEGIN SELECT INTO u n C l i e n t F R O M PERSONNE W H E R E numpers = numClient ; INSERT INTO C L I E N T ( n u m c l i , n o m c l i , p r e n o m c l i ) VALUES ( unClient . numpers , u n C l i e n t . nom , unClient . prenom ) ; EXCEPTION W H E N NO_DATA_FOUND T H E N DBMS_OUTPUT . PUT_LINE ( Personne na l i d e n t i f i a n t | | numClient ) ; W H E N TOO_MANY_ROWS T H E N DBMS_OUTPUT . PUT_LINE ( C e t t e message ne d e v r a i t j a m a i s a p p a r a tre ! ) ; W H E N DUP_VAL_ON_INDEX T H E N DBMS_OUTPUT . PUT_LINE ( C o n t r a i n t e de c l e viol e e ! Message SQL : | | SQLERRM ) ; W H E N OTHERS T H E N RAISE Y_A_EU_UNE_MERDE ; END; END L O O P ; C O M M I T; EXCEPTION W H E N Y_A_EU_UNE_MERDE T H E N D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( I l y a eu une Merde ! ) ; R O L L B A C K; END; / E x e r c i c e 2 DECLARE u n C l i e n t C L I E N T% r o w t y p e ; BEGIN SELECT INTO u n C l i e n t F R O M CLIENT W H E R E numCli = ( SELECT M A X( n u m c l i ) F R O M CLIENT ); INSERT INTO P E R S O N N E L VALUES ( 1, unClient . nomcli , unClient . prenomcli , NULL, 1254.28 ); C O M M I T; EXCEPTION W H E N NO_DATA_FOUND T H E N D B M S _ O U T P U T . P U T _ L I N E ( Aucun c l i e n t ) ; W H E N DUP_VAL_ON_INDEX T H E N DBMS_OUTPUT . PUT_LINE ( I l y a un g r o s probl` e me . . . J comprends pas c q u i s p a s s e ) ; END; / E x e r c i c e 3

DECLARE n u m C l i e n t C L I E N T . n u m c l i%T Y P E ; t C C L T Y P E C C L . n u m t y p e c c l%T Y P E ; n t o T Y P E O P E R A T I O N . n u m t y p e o p e r%T Y P E ; Y _ A _ U N _ G R O _ B L E M E EXCEPTION; BEGIN SELECT n u m t y p e o p e r INTO n t o

42

F R O M TYPEOPERATION W H E R E n o m t y p e o p e r = d ep o t e s p` eces ; SELECT n u m t y p e c c l INTO t C C L F R O M TYPECCL W H E R E n o m t y p e C C L = Compte c o u r a n t ; F O R n u m C l i e n t IN 1 . . 2 1 L O O P BEGIN INSERT INTO C O M P T E C L I E N T VALUES ( numClient , 1, tCCL , SYSDATE , 1 ); INSERT INTO O P E R A T I O N VALUES ( numClient , 1, 1, nto , SYSDATE , numClient 100 , i n a u g u r a t i o n du compte ); C O M M I T; EXCEPTION W H E N OTHERS T H E N Adaptez l e num ero du code , c h e z moi c a donne 2290 I F S Q L C O D E = 2290 T H E N DECLARE t o t a l O P E R A T I O N . m o n t a n t o p e r%T Y P E := n u m C l i e n t 1 0 0 ; t o I n s e r t O P E R A T I O N . m o n t a n t o p e r%T Y P E ; cpt N U M B E R := 1 ; BEGIN WHILE total > 0 LOOP I F t o t a l > 1000 T H E N t o I n s e r t := 1 0 0 0 ; ELSE t o I n s e r t := t o t a l ; END I F ; INSERT INTO O P E R A T I O N VALUES ( numClient , 1, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numClient A N D numccl = 1 ), nto , SYSDATE , toInsert , I n a u g u r a t i o n du compte | | c p t ); t o t a l := t o t a l t o I n s e r t ; c p t := c p t + 1 ; END L O O P ; EXCEPTION W H E N OTHERS T H E N D B M S _ O U T P U T . P U T _ L I N E ( MOD( t o t a l , 1000) = | | M O D ( t o t a l , D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; RAISE Y_A_UN_GRO_BLEME ; END; ELSE D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; R O L L B A C K; END I F ; END; END L O O P ; EXCEPTION W H E N NO_DATA_FOUND T H E N D B M S _ O U T P U T . P U T _ L I N E ( Pas de donn e es ! ) ; W H E N TOO_MANY_ROWS T H E N D B M S _ O U T P U T . P U T _ L I N E ( Trop de donn e es ! ) ; W H E N Y_A_UN_GRO_BLEME T H E N D B M S _ O U T P U T . P U T _ L I N E ( I l y a un g r o s probl` e me ! ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; W H E N OTHERS T H E N D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; END; / E x e r c i c e 4

1000));

43

DECLARE n u m C l i e n t C L I E N T . n u m c l i%T Y P E := 2 ; n u m C o m p t e L i v r e t T Y P E C C L . n u m t y p e C C L%T Y P E ; n t o T Y P E O P E R A T I O N . n u m t y p e o p e r%T Y P E ; m o n t a n t O P E R A T I O N . m o n t a n t o p e r%T Y P E ; Y _ A _ U N _ G R O _ B L E M E EXCEPTION; BEGIN SELECT n u m t y p e o p e r INTO n t o F R O M TYPEOPERATION W H E R E n o m t y p e o p e r = virement ; SELECT n u m t y p e c c l INTO n u m C o m p t e L i v r e t F R O M TYPECCL W H E R E nomtypeCcl = l i v r e t ; W H I L E n u m C l i e n t <= 21 L O O P BEGIN m o n t a n t := 100 n u m C l i e n t 5 0 0 ; INSERT INTO C O M P T E C L I E N T VALUES ( numClient , 2, numCompteLivret , SYSDATE , 1 ); INSERT INTO O P E R A T I O N VALUES ( numClient , 1, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numClient A N D numccl = 1) , nto , SYSDATE , m o n t a n t , versement l i v r e t ); INSERT INTO O P E R A T I O N VALUES ( numClient , 2, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numClient A N D numccl = 2) , nto , SYSDATE , montant , versement l i v r e t ); C O M M I T; EXCEPTION W H E N OTHERS T H E N idem I F S Q L C O D E = 2290 T H E N DECLARE t o t a l O P E R A T I O N . m o n t a n t o p e r%T Y P E := m o n t a n t ; t o M o v e O P E R A T I O N . m o n t a n t o p e r%T Y P E ; cpt N U M B E R := 1 ; BEGIN W H I L E t o t a l > 1000 L O O P I F t o t a l > 1000 T H E N t o M o v e := 1 0 0 0 ; ELSE t o m o v e := t o t a l ; END I F ; INSERT INTO O P E R A T I O N VALUES ( numClient , 1, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numClient A N D numccl = 1) , nto , SYSDATE , t o M o v e , versement l i v r e t | | c p t ); INSERT INTO O P E R A T I O N VALUES ( numClient , 2, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numClient A N D numccl = 2) , nto ,

44

SYSDATE , toMove , versement l i v r e t ); t o t a l := t o t a l t o M o v e ; c p t := c p t + 1 ; END L O O P ; C O M M I T; EXCEPTION W H E N OTHERS T H E N RAISE Y_A_UN_GRO_BLEME ; END; ELSE D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = R O L L B A C K; END I F ; END; C O M M I T; n u m C l i e n t := n u m C l i e n t + 2 ; END L O O P ; EXCEPTION W H E N NO_DATA_FOUND T H E N D B M S _ O U T P U T . P U T _ L I N E ( Pas de donn e es ! ) ; W H E N TOO_MANY_ROWS T H E N D B M S _ O U T P U T . P U T _ L I N E ( Trop de donn e es ! ) ; W H E N Y_A_UN_GRO_BLEME T H E N D B M S _ O U T P U T . P U T _ L I N E ( I l y a un g r o s probl` e me ! ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; W H E N OTHERS T H E N D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ; D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ; END; / || ||

||

cpt

SQLCODE ) ; SQLERRM ) ;

45

3.4

Sous-programmes

E x e r c i c e 1 CREATE OR R E P L A C E F U N C T I O N bad_puissance ( b N U M B E R , n N U M B E R) RETURN N U M B E R IS BEGIN IF ( n = 0) T H E N RETURN 1; ELSE RETURN b bad_puissance ( b , n 1 ) ; END I F ; END; / E x e r c i c e 2 CREATE OR R E P L A C E F U N C T I O N good_puissance ( b N U M B E R , n N U M B E R) RETURN N U M B E R IS BEGIN IF ( n = 0) T H E N RETURN 1; END I F ; IF ( MOD ( n , 2) = 0 ) T H E N RETURN good_puissance ( b b , n / 2 ) ; END I F ; RETURN b good_puissance ( b , n 1 ) ; END; / E x e r c i c e 3 CREATE OR R E P L A C E F U N C T I O N d e m i F r e r e s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN B O O L E A N IS r o w A P E R S O N N E %r o w t y p e ; r o w B P E R S O N N E %r o w t y p e ; BEGIN SELECT INTO r o w A F R O M PERSONNE W H E R E numpers = A ; SELECT INTO r o w B F R O M PERSONNE W H E R E numpers = B ; R E T U R N r o w A . p e r e = r o w B . p e r e OR r o w A . m e r e = r o w B . m e r e ; END; / E x e r c i c e 4 CREATE OR R E P L A C E F U N C T I O N f r e r e s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN B O O L E A N IS r o w A P E R S O N N E %r o w t y p e ; r o w B P E R S O N N E %r o w t y p e ; BEGIN SELECT INTO r o w A F R O M PERSONNE W H E R E numpers = A ; SELECT INTO r o w B F R O M PERSONNE W H E R E numpers = B ; RETURN rowA . pere = rowB . pere A N D rowA . mere = rowB . mere ; END; / CREATE OR R E P L A C E F U N C T I O N c o u s i n s G e r m a i n s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN B O O L E A N IS r o w A P E R S O N N E %r o w t y p e ; r o w B P E R S O N N E %r o w t y p e ; BEGIN SELECT INTO r o w A F R O M PERSONNE W H E R E numpers = A ; SELECT INTO r o w B F R O M PERSONNE W H E R E numpers = B ; RETURN freres ( rowA . pere , rowB . pere ) OR freres ( rowA . pere , rowB . mere ) OR freres ( rowA . mere , rowB . pere ) OR freres ( rowA . mere , rowB . mere ) ; END; / E x e r c i c e 5 CREATE OR R E P L A C E P R O C E D U R E a i e u l ( P P E R S O N N E . n u m p e r s%t y p e ) I S r o w P E R S O N N E%r o w t y p e ; nb N U M B E R; BEGIN SELECT count ( ) INTO N B F R O M PERSONNE

46

W H E R E numpers = P ; IF ( NB = 1) T H E N SELECT INTO r o w F R O M PERSONNE W H E R E numpers = P ; DBMS_OUTPUT . PUT_LINE ( row . nom ) ; aieul ( row . pere ) ; END I F ; END; / E x e r c i c e 6 CREATE OR R E P L A C E P R O C E D U R E m e c s ( P P E R S O N N E . n u m p e r s%t y p e ) I S r o w P E R S O N N E%r o w t y p e ; nb N U M B E R; BEGIN SELECT count ( ) INTO N B F R O M PERSONNE W H E R E numpers = P ; IF ( NB = 1) T H E N SELECT INTO r o w F R O M PERSONNE W H E R E numpers = P ; SELECT count ( ) INTO N B F R O M PERSONNE W H E R E pere = P ; IF ( NB > 0) T H E N DBMS_OUTPUT . PUT_LINE ( row . nom ) ; END I F ; mecs ( row . pere ) ; mecs ( row . mere ) ; END I F ; END; / E x e r c i c e 7 CREATE OR R E P L A C E F U N C T I O N a s c e n d a n t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN B O O L E A N IS r o w P E R S O N N E%r o w t y p e ; BEGIN SELECT INTO r o w F R O M PERSONNE W H E R E numpers = B ; I F ( r o w . p e r e = A OR r o w . m e r e = A ) T H E N R E T U R N TRUE; END I F ; RETURN ( row . pere IS N O T NULL A N D ascendant ( A , row . pere ) ) OR ( row . mere IS N O T NULL A N D ascendant ( A , row . mere ) ) ; END; / BEGIN IF ( a s c e n d a n t ( 1 , 8 ) ) T H E N D B M S _ O U T P U T . P U T _ L I N E ( OK ) ; ELSE D B M S _ O U T P U T . P U T _ L I N E ( pas OK ) ; END I F ; END; / E x e r c i c e 8 CREATE OR R E P L A C E F U N C T I O N fmax ( A N U M B E R , B N U M B E R) RETURN N U M B E R IS BEGIN IF ( A > B ) T H E N RETURN A ; ELSE RETURN B ; END I F ; END; / CREATE OR R E P L A C E F U N C T I O N e c a r t A s c e n d a n t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN N U M B E R IS r o w P E R S O N N E%r o w t y p e ; NB N U M B E R; BEGIN SELECT INTO r o w F R O M PERSONNE W H E R E numpers = B ; I F ( r o w . p e r e = A OR r o w . m e r e = A ) T H E N RETURN 1; END I F ; I F ( r o w . p e r e I S NULL) T H E N

47

N B := 1; ELSE N B := e c a r t A s c e n d a n t ( A , r o w . p e r e ) ; END I F ; I F ( r o w . m e r e I S NULL) T H E N N B := f m a x ( 1 , N B ) ; ELSE N B := f m a x ( e c a r t A s c e n d a n t ( A , r o w . p e r e ) , N B ) ; END I F ; I F ( N B <> 1) T H E N N B := N B + 1 ; END I F ; RETURN NB ; END; / CREATE OR R E P L A C E F U N C T I O N e c a r t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e ) RETURN N U M B E R IS r o w P E R S O N N E%r o w t y p e ; NB N U M B E R; BEGIN RETURN fmax ( ecartAscendant ( A , B ) , ecartAscendant ( B , A ) ) ; END; / E x e r c i c e 9 SELECT A . nom , A . p r e n o m , B . nom , B . p r e n o m F R O M PERSONNE A , PERSONNE B W H E R E ecartAscendant ( A . numpers , B . numpers ) = ( SELECT M A X( e c ) F R O M ( SELECT e c a r t ( A . n u m p e r s , B . n u m p e r s ) AS e c F R O M PERSONNE A , PERSONNE B ) ); E x e r c i c e 10

48

3.5

Curseurs

CREATE OR R E P L A C E P R O C E D U R E c o p y F r o m P e r s o n n e T o C l i e n t I S CURSOR C IS SELECT F R O M PERSONNE ; R O W C%r o w t y p e ; BEGIN F O R R O W IN C L O O P INSERT INTO C L I E N T ( numcli , nomcli , prenomcli ) VALUES ( R O W . n u m p e r s , R O W . nom , R O W . p r e n o m ) ; END L O O P ; C O M M I T; EXCEPTION W H E N DUP_VAL_ON_INDEX T H E N D B M S _ O U T P U T . P U T _ L I N E ( Copy can be done o n l y once . ) ; END; / CALL copyFromPersonneToClient ( ) ; CREATE OR R E P L A C E P R O C E D U R E t a k e C l i e n t T o P e r s o n n e l I S R o w c l i e n t% r o w t y p e ; BEGIN SELECT INTO R o w F R O M CLIENT W H E R E numcli = ( SELECT M A X( n u m c l i ) F R O M CLIENT ) ; INSERT INTO P E R S O N N E L ( numpers , nompers , prenompers ) VALUES ( Row . numcli , Row . nomcli , Row . prenomcli ) ; C O M M I T; EXCEPTION W H E N DUP_VAL_ON_INDEX T H E N D B M S _ O U T P U T . P U T _ L I N E ( This row has a l r e a d y been imported . ) ; R O L L B A C K; W H E N NO_DATA_FOUND T H E N D B M S _ O U T P U T . P U T _ L I N E ( Table CLIENT i s empty . ) ; R O L L B A C K; END; / CALL takeClientToPersonnel ( ) ; CREATE OR R E P L A C E P R O C E D U R E c r e d i t A c c o u n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value N U M B E R) I S BEGIN I F ( value > 1 0 0 ) T H E N creditAccount ( numclient , 100); c r e d i t A c c o u n t ( n u m c l i e n t , value 1 0 0 ) ; ELSE INSERT INTO O P E R A T I O N VALUES ( numclient , 1, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numclient A N D numccl = 1 ), (SELECT n u m t y p e o p e r F R O M TYPEOPERATION W H E R E n o m t y p e o p e r = virement ), sysdate , value , cadeau ! ); END I F ; EXCEPTION W H E N OTHERS T H E N I F ( S Q L C O D E = 22900) T H E N D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ; END I F ; END; / CREATE OR R E P L A C E P R O C E D U R E c r e a t e V i r e m e n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value N U M B E R) I S BEGIN INSERT INTO O P E R A T I O N VALUES ( numclient , 1, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1

49

F R O M OPERATION W H E R E numcli = numclient A N D numccl = 1 ), (SELECT n u m t y p e o p e r F R O M TYPEOPERATION W H E R E n o m t y p e o p e r = virement ), sysdate , value , cadeau ! ); INSERT INTO O P E R A T I O N VALUES ( numclient , 2, (SELECT n v l (M A X( n u m o p e r ) , 0 ) + 1 F R O M OPERATION W H E R E numcli = numclient A N D numccl = 1 ), (SELECT n u m t y p e o p e r F R O M TYPEOPERATION W H E R E n o m t y p e o p e r = virement ), sysdate , value , cadeau ! ); EXCEPTION W H E N OTHERS T H E N I F ( S Q L C O D E = 22900) T H E N D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ; END I F ; END; / CREATE OR R E P L A C E P R O C E D U R E m o v e T o L i v r e t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value N U M B E R) I S BEGIN I F ( value >= 0 ) T H E N I F ( value > 1 0 0 ) T H E N moveToLivret ( numclient , 100); m o v e T o L i v r e t ( n u m c l i e n t , value 1 0 0 ) ; ELSE c r e a t e V i r e m e n t ( n u m c l i e n t , value ) ; END I F ; END I F ; EXCEPTION W H E N OTHERS T H E N I F ( S Q L C O D E = 22900) T H E N D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ; END I F ; END; / CREATE OR R E P L A C E P R O C E D U R E o p e n A c c o u n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S BEGIN INSERT INTO C O M P T E C L I E N T VALUES ( numclient , 1, (SELECT n u m t y p e c c l F R O M TYPECCL W H E R E n o m t y p e c c l = Compte c o u r a n t ), sysdate , (SELECT n u m p e r s F R O M PERSONNEL W H E R E numpers = ( SELECT M A X( n u m c l i ) F R O M CLIENT ) ) ); INSERT INTO C O M P T E C L I E N T VALUES ( numclient , 2, (SELECT n u m t y p e c c l F R O M TYPECCL W H E R E n o m t y p e c c l = virement ), sysdate , (SELECT n u m p e r s F R O M PERSONNEL W H E R E numpers = ( SELECT M A X( n u m c l i ) F R O M CLIENT

50

) ) ); creditAccount ( numclient , numclient 100); m o v e T o L i v r e t ( n u m c l i e n t , n u m c l i e n t 100 5 0 0 ) ; EXCEPTION W H E N DUP_VAL_ON_INDEX T H E N D B M S _ O U T P U T . P U T _ L I N E ( This ac co un t has a l r e a d y been opened . ) ; END; / CREATE OR R E P L A C E P R O C E D U R E o p e n A c c o u n t s I S CURSOR C IS SELECT n u m c l i F R O M CLIENT ; R O W C%r o w t y p e ; BEGIN F O R R O W IN C L O O P openAccount ( ROW . numcli ) ; END L O O P ; C O M M I T; EXCEPTION W H E N OTHERS T H E N D B M S _ O U T P U T . P U T _ L I N E ( An e r r o r has o c c u r r e d . ) ; R O L L B A C K; END; / CALL openAccounts ( ) ; CREATE OR R E P L A C E P R O C E D U R E afficheDescendance ( numpersonne N U M B E R) I S CURSOR C IS SELECT F R O M PERSONNE W H E R E pere = numpersonne OR m e r e = n u m p e r s o n n e ; R O W C%r o w T y p e ; BEGIN F O R R O W IN C L O O P DBMS_OUTPUT . PUT_LINE ( row . nom | | | | row . prenom ) ; afficheDescendance ( ROW . numpers ) ; END L O O P ; END; /

51

3.6

Curseurs param etr es

E x e r c i c e 1 CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C l i e n t ( u n C l i e n t C L I E N T%r o w t y p e ) I S BEGIN DBMS_OUTPUT . PUT_LINE ( Client | | unClient . prenomcli | | | | END; /

unClient . nomCli ) ;

CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C o m p t e ( u n C o m p t e C O M P T E C L I E N T%r o w t y p e ) I S BEGIN D B M S _ O U T P U T . P U T _ L I N E ( Compte | | u n C o m p t e . n u m C l i | | | | u n C o m p t e . n u m c c l ) ; END; / CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C o m p t e s C l i e n t s I S CURSOR c l i e n t s IS SELECT F R O M CLIENT ; u n C l i e n t c l i e n t s%r o w t y p e ; C U R S O R c o m p t e s ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S SELECT F R O M COMPTECLIENT W H E R E numcli = numclient ; u n C o m p t e c l i e n t s%r o w t y p e ; BEGIN F O R u n C l i e n t IN c l i e n t s L O O P afficheClient ( unClient ) ; F O R u n C o m p t e IN c o m p t e s ( u n C l i e n t . n u m c l i ) L O O P afficheCompte ( unCompte ) ; END L O O P ; END L O O P ; END; / SET S E R V E R O U T P U T O N SIZE 1 00 00 0 0 call afficheComptesClients ( ) ; E x e r c i c e 2 CREATE OR R E P L A C E P R O C E D U R E a f f i c h e O p e r a t i o n ( u n e O p e r a t i o n O P E R A T I O N%r o w t y p e ) I S BEGIN D B M S _ O U T P U T . P U T _ L I N E ( Operation | | u n e O p e r a t i o n . n u m O p e r | | , montant : END; /

||

uneOperation . montantOper )

CREATE OR R E P L A C E P R O C E D U R E a f f i c h e O p e r C o m p t e s C l i e n t s I S CURSOR c l i e n t s IS SELECT F R O M CLIENT ; u n C l i e n t c l i e n t s%r o w t y p e ; C U R S O R c o m p t e s ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S SELECT F R O M COMPTECLIENT W H E R E numcli = numclient ; u n C o m p t e c l i e n t s%r o w t y p e ; CURSOR operations ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , n u m c o m p t e C O M P T E C L I E N T . n u m c c l%t y p e ) I S SELECT F R O M OPERATION W H E R E numcli = numclient A N D numccl = numcompte ; u n e O p e r a t i o n o p e r a t i o n s %r o w t y p e ; BEGIN F O R u n C l i e n t IN c l i e n t s L O O P afficheClient ( unClient ) ; F O R u n C o m p t e IN c o m p t e s ( u n C l i e n t . n u m c l i ) L O O P afficheCompte ( unCompte ) ; F O R u n e O p e r a t i o n IN o p e r a t i o n s ( u n C l i e n t . n u m c l i , u n C o m p t e . n u m c c l ) L O O P afficheOperation ( uneOperation ) ; END L O O P ; END L O O P ; END L O O P ; END; / call afficheOperComptesClients ( ) ;

52

3.7

Triggers

I l c o n v i e n t d abord de m o d i f i e r q u e l q u e peu l o r g a n i s a t i o n d e s donnees , on a j o u t e par exemple dans l a t a b l e MODULE l e nombre d e t u d i a n t s i n s c r i t s D R O P D R O P D R O P D R O P D R O P D R O P TABLE TABLE TABLE TABLE TABLE TABLE RESULTAT ; EXAMEN ; PREREQUIS ; INSCRIPTION ; MODULE ; ETUDIANT ;

CREATE TABLE E T U D I A N T ( n u m E t u d number , n o m varchar2 ( 4 0 ) , p r e n o m varchar2 ( 4 0 ) , d a t e n a i s s date , c i v i l i t e varchar2 ( 4 ) , p a t r o n y m e varchar2 ( 4 0 ) , n u m s e c u varchar2 ( 1 5 ) N O T NULL, moyenne N U M B E R DEFAULT NULL ) ; CREATE TABLE M O D U L E ( c o d M o d number , n o m M o d varchar2 ( 1 5 ) , e f f e c M a x number DEFAULT 3 0 , e f f e c number d e f a u l t 0 ) ; CREATE TABLE E X A M E N ( c o d M o d number , c o d E x a m number , dateExam date ) ; CREATE TABLE I N S C R I P T I O N ( n u m E t u d number , c o d M o d number , dateInsc date default sysdate ) ; CREATE TABLE P R E R E Q U I S ( c o d M o d number , c o d M o d P r e r e q number , n o t e M i n number ( 4 , 2 ) N O T NULL ) ; CREATE TABLE R E S U L T A T ( c o d M o d number , c o d E x a m number , n u m E t u d number , n o t e number ( 4 , 2 ) ) ; ALTER TABLE E T U D I A N T A D D CONSTRAINT p k _ e t u d i a n t P R I M A R Y KEY ( n u m E t u d ) ; ALTER TABLE M O D U L E A D D CONSTRAINT p k _ m o d u l e P R I M A R Y KEY ( c o d M o d ) ; ALTER TABLE E X A M E N A D D CONSTRAINT p k _ e x a m e n P R I M A R Y KEY ( c o d M o d , c o d E x a m ) ; ALTER TABLE P R E R E Q U I S A D D CONSTRAINT p k _ p r e r e q u i s P R I M A R Y KEY ( c o d M o d , c o d M o d P r e r e q ) ; ALTER TABLE I N S C R I P T I O N A D D CONSTRAINT p k _ i n s c r i p t i o n P R I M A R Y KEY ( c o d M o d , n u m E t u d ) ; ALTER TABLE R E S U L T A T A D D CONSTRAINT p k _ r e s u l t a t P R I M A R Y KEY ( c o d M o d , n u m E t u d , c o d E x a m ) ; ALTER TABLE I N S C R I P T I O N A D D (CONSTRAINT f k _ i n s c r i p t i o n _ e t u d i a n t FOREIGN KEY ( n u m E t u d ) REFERENCES ETUDIANT ( numEtud ) , CONSTRAINT f k _ i n s c r i p t i o n _ m o d u l e FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) ) ; ALTER TABLE P R E R E Q U I S A D D (CONSTRAINT f k _ p r e r e q u i s _ c o d m o d FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) , CONSTRAINT f k _ p r e r e q u i s _ c o d m o d p r e r e q FOREIGN KEY ( c o d M o d P r e r e q ) REFERENCES MODULE ( codMod ) ) ; ALTER TABLE E X A M E N A D D CONSTRAINT f k _ e x a m e n FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) ; ALTER TABLE R E S U L T A T A D D

53

(CONSTRAINT f k _ r e s u l t a t _ e x a m e n FOREIGN KEY ( c o d M o d , c o d E x a m ) REFERENCES EXAMEN ( codMod , codExam ) , CONSTRAINT f k _ r e s u l t a t _ i n s c r i p t i o n FOREIGN KEY ( c o d M o d , n u m E t u d ) REFERENCES INSCRIPTION ( codMod , numEtud ) ) ; ALTER TABLE E T U D I A N T A D D (CONSTRAINT c k _ c i v i l i t e C H E C K ( c i v i l i t e IN ( Mr , Mme , M l l e ) ), CONSTRAINT c k _ c i v i l i t e _ n u m s e c u C H E C K ( SUBSTR( n u m s e c u , 1 , 1 ) = 2 OR p a t r o n y m e I S NULL ), CONSTRAINT c k _ l e n g t h _ n u m s e c u C H E C K ( l e n g t h ( n u m s e c u ) = 15 ), CONSTRAINT c k _ a n n e e _ n u m s e c u C H E C K ( t o _ c h a r ( d a t e n a i s s , yy ) = substr ( n u m s e c u , 2 , 2 ) ) ); C o n t r a i n t e 1 CREATE OR R E P L A C E TRIGGER b e f o r e U p d a t e F E R P r e r e q u i s BEFORE U P D A T EO N PREREQUIS FOR EACH ROW BEGIN IF ( : new . n o t e M i n < : old . n o t e M i n ) T H E N : n e w . n o t e M i n := : o l d . n o t e M i n ; END I F ; END; / C o n t r a i n t e 2 CREATE OR R E P L A C E P R O C E D U R E i n c r E f f e c ( m o d u l e N U M B E R) I S BEGIN U P D A T E M O D U L E SET e f f e c = e f f e c + 1 W H E R E codmod = module ; END; / CREATE OR R E P L A C E P R O C E D U R E d e c r E f f e c ( m o d u l e N U M B E R) I S BEGIN U P D A T E M O D U L E SET e f f e c = e f f e c 1 W H E R E codmod = module ; END; / CREATE OR R E P L A C E TRIGGER B e f o r e I n s e r t F E R M o d u l e B E F O R E INSERT O N MODULE FOR EACH ROW BEGIN : n e w . e f f e c := 0 ; END; / CREATE OR R E P L A C E TRIGGER a f t e r I n s e r t F E R I n s c A F T E R INSERT O N INSCRIPTION FOR EACH ROW BEGIN incrEffec ( : new . codmod ) ; END; /

54

CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R I n s c A F T E R DELETE O N INSCRIPTION FOR EACH ROW BEGIN decrEffec ( : old . codmod ) ; END; / CREATE OR R E P L A C E TRIGGER a f t e r U p d a t e F E R I n s c AFTER U P D A T EO N INSCRIPTION FOR EACH ROW BEGIN decrEffec ( : old . codmod ) ; incrEffec ( : new . codmod ) ; END; / D R O P VIEW m o d u l e s D i s p o n i b l e s ; CREATE VIEW m o d u l e s D i s p o n i b l e s AS SELECT c o d m o d F R O M MODULE W H E R E effec < effecMax ; CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R I n s c B E F O R E INSERT OR U P D A T EO N INSCRIPTION FOR EACH ROW DECLARE nbLignes N U M B E R; BEGIN SELECT count ( ) INTO n b L i g n e s F R O M modulesDisponibles W H E R E codmod = : new . codmod ; IF ( n b L i g n e s = 0) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20001 , P l u s de p l a c e s d i p o n i b l e s . ) ; END I F ; END; / C o n t r a i n t e 3 D R O P VIEW e x a m e n s P o s s i b l e s ; CREATE VIEW e x a m e n s P o s s i b l e s AS SELECT c o d M o d F R O M MODULE M W H E R E ( SELECT C O U N T( ) F R O M INSCRIPTION I W H E R E I . codmod = M . codmod ) > 0 ; CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R E x a m B E F O R E INSERT OR U P D A T EO N EXAMEN FOR EACH ROW DECLARE nbLignes N U M B E R; BEGIN SELECT count ( ) INTO n b L i g n e s F R O M examensPossibles W H E R E codMod = : new . codmod ; IF ( n b L i g n e s = 0) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20002 , Pas d el` e v e dans ce module . ) ; END I F ; END; /

55

C o n t r a i n t e 4 D R O P VIEW e t u d i a n t s E x a m e n s ; CREATE VIEW e t u d i a n t s E x a m e n s AS SELECT I . n u m e t u d , E . c o d m o d , E . c o d e x a m F R O M INSCRIPTION I , EXAMEN E W H E R E I . codmod = E . codmod A N D I . dateInsc < E . dateExam ; CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R R e s u l t B E F O R E INSERT OR U P D A T EO N RESULTAT FOR EACH ROW DECLARE nbLignes N U M B E R; BEGIN SELECT count ( ) INTO n b L i g n e s F R O M etudiantsExamens W H E R E numetud = : new . numetud A N D codmod = : new . codmod A N D codexam = : new . codexam ; IF ( n b L i g n e s = 0) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20002 , Examen a n t erieur ` a l i n s c r i p t i o n dans l e module . ) ; END I F ; END; / C o n t r a i n t e 5 On c r e e une t a b l e t e m p o r a i r e c o n t e n a n t l e s m emes v a l e u r s que p r e r e q u i s , On l a met ` a j o u r AVANT l a t a b l e p r e r e q u i s pour v e r i f i e r que l i n s e r t i o n ne c o n s t r u i t pas de c i r c u i t . D R O P TABLE M I R R O R P R E R E Q ; CREATE TABLE M I R R O R P R E R E Q ( codmod N U M B E R , codmodprereq N U M B E R , noteMin N U M B E R) ;

CREATE OR R E P L A C E F U N C T I O N f i n d M o d u l e ( r o o t number , m o d u l e T o F i n d number ) RETURN BOOLEAN IS CURSOR C IS SELECT c o d m o d F R O M MIRRORPREREQ W H E R E codmodprereq = root ; S O N C%r o w t y p e ; BEGIN F O R S O N IN C L O O P IF ( s o n . c o d m o d = m o d u l e T o F i n d OR findModule ( son . codmod , moduleToFind ) ) T H E N R E T U R N TRUE; END I F ; END L O O P ; R E T U R N FALSE ; END; / CREATE OR R E P L A C E P R O C E D U R E insertMirrorPrereq ( codmodValue N U M B E R , codmodprereqValue N U M B E R , note N U M B E R) I S BEGIN INSERT INTO M I R R O R P R E R E Q ( codmod , codmodprereq , noteMin ) VALUES ( codmodValue , codmodprereqValue , note ) ; END; /

56

CREATE OR R E P L A C E P R O C E D U R E deleteMirrorPrereq ( codmodValue N U M B E R , codmodprereqValue N U M B E R) I S BEGIN DELETE F R O M MIRRORPREREQ W H E R E codmod = codmodValue A N D codmodprereq = codmodprereqValue ; END; / CREATE OR R E P L A C E P R O C E D U R E updateMirrorPrereq ( codmodValue N U M B E R , codmodNewValue N U M B E R , codmodprereqValue N U M B E R , codmodprereqNewValue N U M B E R , newNote N U M B E R) I S BEGIN U P D A T E M I R R O R P R E R E Q SET codmod = codmodNewValue , codmodprereq = codmodprereqNewValue , noteMin = newNote W H E R E codmod = codmodValue A N D codmodprereq = codmodprereqValue ; END; / CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R P r e r e q A F T E R DELETE O N PREREQUIS FOR EACH ROW BEGIN deleteMirrorPrereq ( : old . codmod , : old . codmodprereq ) ; END; / CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R P r e r e q B E F O R E INSERT OR U P D A T EO N PREREQUIS FOR EACH ROW BEGIN IF I N S E R T I N G T H E N insertMirrorPrereq ( : new . codmod , : new . codmodprereq , : new . noteMin ) ; END I F ; IF U P D A T I N G T H E N updateMirrorPrereq ( : old . codmod , : new . codmod , : old . codmodprereq , : new . codmodprereq , : new . noteMin ) ; END I F ; IF ( f i n d M o d u l e ( : new . codmod , : new . codmod ) ) T H E N IF I N S E R T I N G T H E N deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ; END I F ; IF U P D A T I N G T H E N updateMirrorPrereq ( : new . codmod , : old . codmod , : new . codmodprereq , : old . codmodprereq , : old . noteMin ) ; END I F ; R A I S E _ A P P L I C A T I O N _ E R R O R ( 20003 , C i r c u i t dans p r e r e q u i s . ) ; END I F ; END; / C o n t r a i n t e 6 CREATE OR R E P L A C E F U N C T I O N checkInscription ( etud N U M B E R , mod N U M B E R) RETURN BOOLEAN IS CURSOR prereq IS SELECT n o t e M i n , c o d m o d p r e r e q F R O M MIRRORPREREQ W H E R E codmod = mod ; p p r e r e q% r o w t y p e ; nbLignes N U M B E R; BEGIN

57

F O R p IN p r e r e q L O O P SELECT count ( ) INTO n b L i g n e s F R O M RESULTAT W H E R E codmod = p . codmodprereq A N D numetud = etud A N D note < p . noteMin ; IF ( n b L i g n e s = 0) T H E N R E T U R N FALSE ; END I F ; END L O O P ; R E T U R N TRUE; END; / CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R I n s c B E F O R E INSERT OR U P D A T EO N INSCRIPTION FOR EACH ROW DECLARE nbLignes N U M B E R; BEGIN SELECT count ( ) INTO n b L i g n e s F R O M modulesDisponibles W H E R E codmod = : new . codmod ; IF ( n b L i g n e s = 0) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20001 , P l u s de p l a c e s d i p o n i b l e s . ) ; END I F ; I F (N O T( c h e c k I n s c r i p t i o n ( : n e w . n u m e t u d , : n e w . c o d m o d ) ) ) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20004 , P r e r e q u i s non s a t i s f a i t . ) ; END I F ; END; / C o n t r a i n t e 7 La la le les a u s s i un probleme s e pose , on ne p e u t pas f a i r e de r e q u e t e s u r t a b l e r e s u l t a t , comme de p l u s , on t i e n t ` a p r e n d r e pour chaque e t u d i a n t m e i l l e u r e n o t e dans chaque module , on c r e e une t a b l e t e m p o r a i r e c o n t e n a n t n o t e s o b e t n u e s par l e s e l e v e s .

D R O P TABLE M I R R O R R E S U L T ; CREATE TABLE M I R R O R R E S U L T ( numetud N U M B E R , codmod N U M B E R , codexam N U M B E R , note N U M B E R , P R I M A R Y KEY( n u m e t u d , c o d m o d , c o d e x a m ) ); D R O P VIEW M E I L L E U R E N O T E ; CREATE VIEW M E I L L E U R E N O T E AS SELECT n u m e t u d , c o d m o d , M A X( n o t e ) AS n o t e M a x F R O M MIRRORRESULT G R O U P BY n u m e t u d , c o d m o d ; D R O P VIEW N O M B R E I N S C R I P T I O N s ; CREATE VIEW N O M B R E I N S C R I P T I O N S AS SELECT n u m e t u d , ( SELECT C O U N T( ) F R O M INSCRIPTION I W H E R E I . numetud = E . numetud ) AS n b I n s c r i p t i o n s F R O M ETUDIANT E ; D R O P VIEW N O M B R E N O T E S ; CREATE VIEW N O M B R E N O T E S AS SELECT n u m e t u d ,

58

(SELECT C O U N T( ) AS n b N o t e s F R O M MEILLEURENOTE M W H E R E M . numetud = E . numetud ) AS n b N o t e s F R O M ETUDIANT E ; CREATE OR R E P L A C E P R O C E D U R E updateMoyenne ( etud N U M B E R) IS nbNotes N U M B E R; nbInscriptions N U M B E R; BEGIN SELECT n b N o t e s INTO n b N o t e s F R O M NOMBRENOTES W H E R E numetud = etud ; SELECT n b I n s c r i p t i o n s INTO n b I N s c r i p t i o n s F R O M NOMBREINSCRIPTIONS W H E R E numetud = etud ; IF ( n b N o t e s = n b I n s c r i p t i o n s ) T H E N U P D A T E E T U D I A N T SET m o y e n n e = (SELECT A V G( n o t e M a x ) F R O M MEILLEURENOTE W H E R E numetud = etud ) W H E R E numetud = etud ; ELSE U P D A T E E T U D I A N T SET m o y e n n e = NULL W H E R E numetud = etud ; END I F ; END; / CREATE OR R E P L A C E TRIGGER a f t e r I n s e r t F E R R e s u l t A F T E R INSERT O N RESULTAT FOR EACH ROW BEGIN INSERT INTO M I R R O R R E S U L T VALUES ( : new . numetud , : new . codmod , : new . codexam , updateMoyenne ( : new . numetud ) ; END; /

: new . note ) ;

CREATE OR R E P L A C E TRIGGER a f t e r U p d a t e F E R R e s u l t AFTER U P D A T EO N RESULTAT FOR EACH ROW BEGIN U P D A T E M I R R O R R E S U L T SET numetud = : new . numetud , codmod = : new . codmod , codexam = : new . codexam , note = : new . note W H E R E numetud = : old . numetud A N D codmod = : old . codmod A N D codexam = : old . codexam ; updateMoyenne ( : new . numetud ) ; END; / CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R R e s u l t A F T E R DELETE O N RESULTAT FOR EACH ROW BEGIN DELETE F R O M MIRRORRESULT W H E R E numetud = : new . numetud A N D codmod = : new . codmod A N D codexam = : new . codexam ; updateMoyenne ( : new . numetud ) ; END; / C o n t r a i n t e 9

59

CREATE OR R E P L A C E F U N C T I O N checkAllStudents RETURN BOOLEAN IS CURSOR C IS SELECT n u m e t u d , c o d m o d F R O M INSCRIPTION ; e C%r o w t y p e ; BEGIN F O R e IN C L O O P I F (N O T( c h e c k I n s c r i p t i o n ( e . n u m e t u d , e . c o d m o d ) ) ) T H E N R E T U R N FALSE ; END I F ; END L O O P ; R E T U R N TRUE; END; / CREATE OR R E P L A C E TRIGGER B e f o r e U p d a t e F E R M o d u l e BEFORE U P D A T EO N MODULE FOR EACH ROW BEGIN IF ( : new . e f f e c m a x < : new . effec ) T H E N R A I S E _ A P P L I C A T I O N _ E R R O R ( 20005 , L e f f e c t i f ne p e u t e t r e en d e s s o u s de END I F ; END; / C o n t r a i n t e 8

||

: new . effec ) ;

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R P r e r e q B E F O R E INSERT OR U P D A T EO N PREREQUIS FOR EACH ROW BEGIN IF I N S E R T I N G T H E N insertMirrorPrereq ( : new . codmod , : new . codmodprereq , : new . noteMin ) ; END I F ; IF U P D A T I N G T H E N updateMirrorPrereq ( : old . codmod , : new . codmod , : old . codmodprereq , : new . codmodprereq , : new . noteMin ) ; END I F ; IF ( f i n d M o d u l e ( : new . codmod , : new . codmod ) ) T H E N IF I N S E R T I N G T H E N deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ; END I F ; IF U P D A T I N G T H E N updateMirrorPrereq ( : new . codmod , : old . codmod , : new . codmodprereq , : old . codmodprereq , : old . noteMin ) ; END I F ; R A I S E _ A P P L I C A T I O N _ E R R O R ( 20003 , C i r c u i t dans p r e r e q u i s . ) ; END I F ; I F (N O T( c h e c k A l l S t u d e n t s ( ) ) ) T H E N IF I N S E R T I N G T H E N deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ; END I F ; IF U P D A T I N G T H E N updateMirrorPrereq ( : new . codmod , : old . codmod , : new . codmodprereq , : old . codmodprereq , : old . noteMin ) ; END I F ; R A I S E _ A P P L I C A T I O N _ E R R O R ( 20006 , I m p o s s i b l e de diminuer c e t t e n o t e . ) ; END I F ; END; / Quelques i n s e r t i o n s pour t e s t e r INSERT INTO E T U D I A N T VALUES ( (SELECT n v l (M A X( n u m E t u d ) , 0 ) + 1 F R O M ETUDIANT ) , Fourier , Joseph , t o _ d a t e ( 21031768 , ddmmyyyy ) , Mr , NULL, 168031234567890 , NULL );

60

INSERT INTO M O D U L E ( codMod , nomMod ) VALUES ( (SELECT n v l (M A X( c o d M o d ) , 0 ) + 1 F R O M MODULE ) , Maths ); INSERT INTO I N S C R I P T I O N ( codMod , numEtud ) VALUES ( (SELECT n u m E t u d F R O M ETUDIANT W H E R E nom = Fourier ) , (SELECT c o d M o d F R O M MODULE W H E R E n o m M o d = Maths ) ); INSERT INTO E X A M E N VALUES ( (SELECT c o d M o d F R O M MODULE W H E R E n o m M o d = Maths ) , 1, t o _ d a t e ( 02012008 , ddmmyyyy ) ); INSERT INTO R E S U L T A T VALUES ( (SELECT c o d M o d F R O M MODULE W H E R E n o m M o d = Maths ) , 1, (SELECT n u m E t u d F R O M ETUDIANT W H E R E nom = Fourier ) , 19 ); U P D A T E R E S U L T A T SET n o t e = 20 wHERE n u m E t u d = (SELECT n u m E t u d F R O M ETUDIANT W H E R E nom = Fourier ) A N D c o d M o d = (SELECT c o d M o d F R O M MODULE W H E R E n o m M o d = Maths ) A N D codExam = 1; INSERT INTO M O D U L E VALUES ( 2 , Algo , 3 0 , 2 2 ) ; INSERT INTO P R E R E Q U I S VALUES (1 , 2 , 10); INSERT INTO P R E R E Q U I S VALUES (2 , 1 , 10); U P D A T E P R E R E Q U I S SET n o t e M i n = 2 ; INSERT INTO E X A M E N VALUES ( 2 , 1 , s y s d a t e ) ;

61

3.8

Packages
c u r s o r f e u i l l e s r e t u r n p e r s o n n e %r o w t y p e I S SELECT F R O M PERSONNE ; P R O C E D U R E a j o u t e P e r s o n n e ( n o m p e r s o n n e . n o m%t y p e , p r e n o m p e r s o n n e . p r e n o m%t y p e , p e r e p e r s o n n e . p e r e%t y p e , m e r e p e r s o n n e . m e r e%t y p e ) I S BEGIN INSERT INTO P E R S O N N E VALUES ( (SELECT n v l (M A X( n u m p e r s ) , 0 ) + 1 F R O M PERSONNE ) , nom , p r e n o m , p e r e , m e r e ) ; END; F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e , d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S BEGIN I F ( d e s c e n d a n t I S NULL) T H E N R E T U R N FALSE ; ELSIF ( descendant = numpers ) T H E N R E T U R N TRUE; ELSE DECLARE p e r s P E R S O N N E %r o w t y p e ; BEGIN SELECT INTO p e r s F R O M PERSONNE W H E R E numpers = descendant ; RETURN descendDe ( numpers , pers . pere ) OR d e s c e n d D e ( n u m p e r s , p e r s . m e r e ) ; END; END I F ; END; p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . n u m p e r s%t y p e , n u m P e r e p e r s o n n e . p e r e%t y p e , n u m M e r e p e r s o n n e . m e r e%t y p e ) I S BEGIN I F ( d e s c e n d D e ( p e r s , n u m P e r e ) OR d e s c e n d D e ( p e r s , n u m M e r e ) ) T H E N RAISE CIRCUIT ; END I F ; U P D A T E P E R S O N N E SET p e r e = n u m P e r e , m e r e = n u m M e r e W H E R E numPers = pers ; END;

CREATE OR R E P L A C E P A C K A G E B O D Y g e s t i o n _ a r b r e I S

END; / CALL gestion_Arbre . modifieParents (20 , 14 , 1 5 ) ;

62

3.9

R evisions

P r e p a r a t i f s . . . D R O P TABLE M I R R O R P E R S O N N E ; CREATE TABLE M I R R O R P E R S O N N E ( numpers N U M B E RP R I M A R Y KEY, pere N U M B E R , mere N U M B E R ); CREATE OR R E P L A C E TRIGGER m i s e A J o u r M i r r o r P e r s o n n e BEFORE U P D A T E OR INSERT OR DELETE O N PERSONNE FOR EACH ROW BEGIN I F D E L E T I N G OR U P D A T I N G T H E N DELETE F R O M MIRRORPERSONNE W H E R E numpers = : old . numpers ; END I F ; I F I N S E R T I N G OR U P D A T I N G T H E N INSERT INTO M I R R O R P E R S O N N E VALUES ( : new . numpers , : new . pere , : new . mere ) ; END I F ; END; / D R O P TABLE M I R R O R M A R I A G E ; CREATE TABLE M I R R O R M A R I A G E ( nummari N U M B E R , numfemme N U M B E R , d a t e m a r i a g e DATE, d a t e d i v o r c e DATE ); CREATE OR R E P L A C E TRIGGER m i s e A J o u r M i r r o r M a r i a g e BEFORE U P D A T E OR INSERT OR DELETE O N MARIAGE FOR EACH ROW BEGIN I F D E L E T I N G OR U P D A T I N G T H E N DELETE F R O M MIRRORMARIAGE W H E R E nummari = : old . nummari A N D numfemme = : old . numfemme A N D datemariage = : old . datemariage ; END I F ; I F I N S E R T I N G OR U P D A T I N G T H E N INSERT INTO M I R R O R M A R I A G E VALUES ( : new . nummari , : new . numfemme , : new . datemariage , END I F ; END; / C o n t r a i n t e 1 ALTER TABLE P E R S O N N E A D D CONSTRAINT c k _ p a r e n t s _ d i f f e r e n t s C H E C K( p e r e <> m e r e ) ; C o n t r a i n t e 2 CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e C i r c u i t I S C I R C U I T EXCEPTION; P R O C E D U R E v e r i f i e C i r c u i t ( p e r s p e r s o n n e . n u m p e r s%t y p e ) ; F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e , d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N ; END; / CREATE OR R E P L A C E TRIGGER v e r i f i e C o n t r a i n t e C i r c u i t AFTER U P D A T E OR INSERT O N PERSONNE FOR EACH ROW BEGIN contrainteCircuit . verifieCircuit ( : new . numPers ) ; END; / CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e C i r c u i t I S F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e , d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S BEGIN I F ( d e s c e n d a n t I S NULL) T H E N R E T U R N FALSE ; ELSIF ( descendant = numpers ) T H E N R E T U R N TRUE; ELSE DECLARE

: new . datedivorce ) ;

63

p e r s M I R R O R P E R S O N N E %r o w t y p e ; BEGIN SELECT INTO p e r s F R O M MIRRORPERSONNE W H E R E numpers = descendant ; RETURN descendDe ( numpers , pers . pere ) OR d e s c e n d D e ( n u m p e r s , p e r s . m e r e ) ; END; END I F ; END; P R O C E D U R E v e r i f i e C i r c u i t ( p e r s p e r s o n n e . n u m p e r s%t y p e ) I S l i g n e m i r r o r p e r s o n n e %r o w t y p e ; BEGIN SELECT INTO L I G N E F R O M mirrorpersonne W H E R E numpers = pers ; I F ( d e s c e n d D e ( p e r s , l i g n e . p e r e ) OR d e s c e n d D e ( p e r s , l i g n e . m e r e ) ) T H E N RAISE CIRCUIT ; END I F ; END; END; / C o n t r a i n t e 3 ALTER TABLE M A R I A G E A D D CONSTRAINT c k _ d a t e s _ m a r i a g e C H E C K( d a t e D i v o r c e I S NULL OR d a t e M a r i a g e <= C o n t r a i n t e 4 CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e s M a r i a g e s I S m a r i a g e s S u p e r p o s e s EXCEPTION; P R O C E D U R E v e r i f i e M a r i a g e s S u p e r p o s e s ( n o u v e a u M a r i a g e m a r i a g e%r o w t y p e ) ; END c o n t r a i n t e s M a r i a g e s ; / CREATE OR R E P L A C E TRIGGER v e r i f i e C o n t r a i n t e s M a r i a g e s BEFORE U P D A T E OR INSERT O N MARIAGE FOR EACH ROW DECLARE n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ; BEGIN n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ; n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ; n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ; n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ; contraintesMariages . verifieMariagesSuperposes ( nouveauMariage ) ; END; / CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e s M a r i a g e s I S F U N C T I O N s e S u p e r p o s e n t ( m 1 m i r r o r M a r i a g e%r o w t y p e , m 2 m i r r o r M a r i a g e%r o w t y p e ) R E T U R N B O O L E A N I S BEGIN I F ( m 1 . n u m m a r i <> m 2 . n u m m a r i OR m 1 . n u m f e m m e <> m 2 . n u m f e m m e ) T H E N R E T U R N FALSE ; END I F ; RETURN N O T( ( m2 . d a t e d i v o r c e IS N O T NULL A N D m 1 . d a t e M a r i a g e <= m 2 . d a t e D i v o r c e ) OR ( m 1 . d a t e d i v o r c e I S N O T NULL A N D m 2 . d a t e M a r i a g e <= m 1 . d a t e D i v o r c e ) ); END; P R O C E D U R E v e r i f i e M a r i a g e s S u p e r p o s e s ( n o u v e a u M a r i a g e m a r i a g e%r o w t y p e ) I S CURSOR a u t r e s M a r i a g e s IS SELECT F R O M MIRRORMARIAGE W H E R E numMari = nouveauMariage . numMari OR n u m F e m m e = n o u v e a u M a r i a g e . n u m F e m m e ; a u t r e M a r i a g e a u t r e s M a r i a g e s %R O W T Y P E ; BEGIN F O R a u t r e M a r i a g e IN a u t r e s M a r i a g e s L O O P IF ( s e S u p e r p o s e n t ( n o u v e a u M a r i a g e , a u t r e M a r i a g e ) ) T H E N RAISE mariagesSuperposes ; END I F ; END L O O P ; END; END c o n t r a i n t e s M a r i a g e s ; / C o n t r a i n t e s 5 e t 6 CREATE OR R E P L A C E p a c k a g e c o n t r a i n t e s T r a n s I S t r a n s EXCEPTION; P R O C E D U R E v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E %r o w t y p e ) ; P R O C E D U R E v e r i f i e M a r i F e m m e ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) ; dateDivorce ) ;

64

end c o n t r a i n t e s T r a n s ; / CREATE OR R E P L A C E TRIGGER p e r e M e r e AFTER U P D A T E OR INSERT O N PERSONNE FOR EACH ROW DECLARE n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E %r o w t y p e ; BEGIN n o u v e l l e P e r s o n n e . n u m p e r s := : n e w . n u m p e r s ; n o u v e l l e P e r s o n n e . p e r e := : n e w . p e r e ; n o u v e l l e P e r s o n n e . m e r e := : n e w . m e r e ; contraintesTrans . verifiePereMere ( nouvellePersonne ) ; END; / CREATE OR R E P L A C E TRIGGER m a r i F e m m e AFTER U P D A T E OR INSERT O N MARIAGE FOR EACH ROW DECLARE n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ; BEGIN n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ; n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ; n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ; n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ; contraintesTrans . verifieMariFemme ( nouveauMariage ) ; END; / CREATE OR R E P L A C E p a c k a g e B O D Y c o n t r a i n t e s T r a n s I S P R O C E D U R E v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E %r o w t y p e ) I S n b INT ; BEGIN SELECT C O U N T( ) INTO n b F R O M MIRRORPERSONNE W H E R E pere = nouvellePersonne . mere OR m e r e = n o u v e l l e P e r s o n n e . p e r e ; I F ( n b <> 0 ) T H E N RAISE TRANS ; END I F ; SELECT C O U N T( ) INTO n b F R O M MIRRORMARIAGE W H E R E numMari = nouvellePersonne . mere OR n u m F e m m e = n o u v e l l e P e r s o n n e . p e r e ; I F ( n b <> 0 ) T H E N RAISE TRANS ; END I F ; END; P R O C E D U R E v e r i f i e M a r i F e m m e ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) I S n b INT ; BEGIN SELECT C O U N T( ) INTO n b F R O M MIRRORMARIAGE W H E R E numMari = nouveauMariage . numFemme OR n u m F e m m e = n o u v e a u M a r i a g e . n u m M a r i ; I F ( n b <> 0 ) T H E N RAISE TRANS ; END I F ; SELECT C O U N T( ) INTO n b F R O M MIRRORPERSONNE W H E R E pere = nouveauMariage . numFemme OR m e r e = n o u v e a u M a r i a g e . n u m M a r i ; I F ( n b <> 0 ) T H E N RAISE TRANS ; END I F ; END;

END c o n t r a i n t e s T r a n s ; / C o n t r a i n t e 7 CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e M a r i a g e C o n s a n g u i n I S M a r i a g e C o n s a n g u i n EXCEPTION; P R O C E D U R E v e r i f i e M a r i a g e C o n s a n g u i n ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) ; END c o n t r a i n t e M a r i a g e C o n s a n g u i n ; / CREATE OR R E P L A C E TRIGGER m a r i a g e C o n s a n g u i n AFTER U P D A T E OR INSERT O N MARIAGE FOR EACH ROW DECLARE n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ; BEGIN

65

n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ; n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ; n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ; n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ; contrainteMariageConsanguin . verifieMariageConsanguin ( nouveauMariage ) ; END; / CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e M a r i a g e C o n s a n g u i n I S F U N C T I O N p e r e ( p P E R S O N N E . n u m p e r s%t y p e ) R E T U R N P E R S O N N E . n u m p e r s%t y p e I S n u m P e r e P E R S O N N E . n u m p e r s%t y p e ; BEGIN SELECT p e r e INTO n u m P e r e F R O M MIRRORPERSONNE W H E R E numpers = p ; RETURN numPere ; EXCEPTION W H E N NO_DATA_FOUND T H E N R E T U R N NULL; END; F U N C T I O N m e r e ( p P E R S O N N E . n u m p e r s%t y p e ) R E T U R N P E R S O N N E . n u m p e r s%t y p e I S n u m M e r e P E R S O N N E . n u m p e r s%t y p e ; BEGIN SELECT m e r e INTO n u m M e r e F R O M MIRRORPERSONNE W H E R E numpers = p ; RETURN numMere ; EXCEPTION W H E N NO_DATA_FOUND T H E N R E T U R N NULL; END;

F U N C T I O N r e c h e r c h e A n c e t r e C o m m u n ( a P E R S O N N E . n u m p e r s%t y p e , b P E R S O N N E . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S BEGIN I F ( a I S NULL) T H E N R E T U R N FALSE ; ELSE R E T U R N ( c o n t r a i n t e C i r c u i t . d e s c e n d D e ( a , b ) ) OR r e c h e r c h e A n c e t r e C o m m u n ( p e r e ( a ) , b ) OR r e c h e r c h e A n c e t END I F ; END; P R O C E D U R E v e r i f i e M a r i a g e C o n s a n g u i n ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) I S BEGIN IF ( r e c h e r c h e A n c e t r e C o m m u n ( n o u v e a u M a r i a g e . numMari , n o u v e a u M a r i a g e . n u m F e m m e ) ) T H E N RAISE MariageConsanguin ; END I F ; END; END c o n t r a i n t e M a r i a g e C o n s a n g u i n ; /

66

Annexe A

Scripts de cr eation de bases


A.1 Livraisons Sans contraintes

Attention : Le num ero de livraison est une cl e secondaire, cest-` a-dire un num ero unique etant donn e un fournisseur.
CREATE TABLE P R O D U I T ( n u m p r o d number , n o m p r o d varchar2 ( 3 0 ) ) ; CREATE TABLE F O U R N I S S E U R ( n u m f o u number , n o m f o u varchar2 ( 3 0 ) ) ; CREATE TABLE P R O P O S E R ( n u m f o u number , n u m p r o d number , p r i x number ) ; CREATE TABLE L I V R A I S O N ( n u m f o u number , n u m l i number , dateli date default sysdate ); CREATE TABLE D E T A I L L I V R A I S O N ( n u m f o u number , n u m l i number , n u m p r o d number , q t e number ) ;

67

A.2

Modules et prerequis

les modules sont r epertori es dans une table, et les modules pr e-requis pour sy inscrire (avec la note minimale) se trouvent dans la table prerequis. Une ligne de la table PREREQUIS nous indique que pour sinscrire dans le module num ero numMod, il faut avoir eu au moins noteMin au module numModPrereq.
CREATE TABLE M O D U L E ( n u m M o d number primary key , n o m M o d varchar2 ( 3 0 ) ); CREATE TABLE P R E R E Q U I S ( n u m M o d number r e f e r e n c e s M O D U L E ( n u m M o d ) , n u m M o d P r e r e q number r e f e r e n c e s M O D U L E ( n u m M o d ) , n o t e M i n number ( 2 ) DEFAULT 10 N O T NULL , P R I M A R Y KEY( n u m M o d , n u m M o d P r e r e q ) ); INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO MODULE MODULE MODULE MODULE MODULE MODULE MODULE MODULE VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (1 , (2 , (3 , (4 , (5 , (6 , (7 , (8 , Oracle ) ; C ++ ) ; C ) ; Algo ) ; Merise ) ; PL/SQL O r a c l e ) ; mySQL ) ; c e ); Algo avancA , numModPrereq ) , numModPrereq ) (6 , 1 , 12); , numModPrereq ) , numModPrereq ) , numModPrereq ) VALUES ( 1 , VALUES ( 2 , VALUES ( 6 , VALUES ( 8 , VALUES ( 7 , 5); 3); 5); 5); 5);

PREREQUIS PREREQUIS PREREQUIS PREREQUIS PREREQUIS PREREQUIS

( numMod ( numMod VALUES ( numMod ( numMod ( numMod

68

A.3

G eom etrie

La table INTERVALLE contient des intervalles sp eci es par leurs bornes inf erieure et sup erieure. Supprimer de la table intervalle tous les intervalles qui nen sont pas avec une seule instruction.
CREATE TABLE I N T E R V A L L E ( borneInf N U M B E R , borneSup N U M B E R , P R I M A R Y KEY ( b o r n e I n f , b o r n e S u p ) ) ; CREATE TABLE R E C T A N G L E ( xHautGauche N U M B E R , yHautGauche N U M B E R , xBasDroit N U M B E R , yBasDroit N U M B E R , P R I M A R Y KEY ( x H a u t G a u c h e , y H a u t G a u c h e , x B a s D r o i t , INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE INTERVALLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE RECTANGLE VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (2 , (12 , (2 , (12 , (8 , (34 , (5 , (7 , (0 , (21 , 56); 30); 3); 3); 27); 26); 10); 32); 30); 8);

yBasDroit ) ) ;

VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES

(2 , 12 , 5 , 7 ) ; (2 , 12 , 1 , 1 3 ) ; (10 , 13 , 1 , 1 1 ) ; (10 , 13 , 10 , 1 1 ) ; (2 , 7 , 5 , 13); (21 , 73 , 15 , 2 2 ) ; (1 , 2 , 3 , 4); (1 , 5 , 3 , 2); (1 , 6 , 3 , 6); (4 , 2 , 1 , 4); (2 , 3 , 4 , 0); (5 , 4 , 2 , 1);

69

A.4

Livraisons

CREATE TABLE P R O D U I T ( n u m p r o d number , n o m p r o d varchar2 ( 3 0 ) ) ; CREATE TABLE F O U R N I S S E U R ( n u m f o u number , n o m f o u varchar2 ( 3 0 ) ) ; CREATE TABLE P R O P O S E R ( n u m f o u number , n u m p r o d number , p r i x number N O T NULL ) ; CREATE TABLE L I V R A I S O N ( n u m f o u number , n u m l i number , dateli date default sysdate ); CREATE TABLE D E T A I L L I V R A I S O N ( n u m f o u number , n u m l i number , n u m p r o d number , q t e number N O T NULL ) ; a l t e r table P R I M A R Y KEY a l t e r table P R I M A R Y KEY a l t e r table P R I M A R Y KEY a l t e r table P R I M A R Y KEY a l t e r table P R I M A R Y KEY a l t e r table FOREIGN KEY a l t e r table FOREIGN KEY a l t e r table FOREIGN KEY a l t e r table FOREIGN KEY a l t e r table FOREIGN KEY INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO p r o d u i t add c o n s t r a i n t p k _ p r o d u i t ( numprod ) ; f o u r n i s s e u r add c o n s t r a i n t p k _ f o u r n i s s e u r ( numfou ) ; p r o p o s e r add c o n s t r a i n t p k _ p r o p o s e r ( numfou , numprod ) ; l i v r a i s o n add c o n s t r a i n t p k _ l i v r a i s o n ( numfou , numli ) ; d e t a i l l i v r a i s o n add c o n s t r a i n t p k _ d e t a i l _ l i v r a i s o n ( numfou , numli , numprod ) ; p r o p o s e r add c o n s t r a i n t f k _ p r o p o s e r _ f o u r n i s s e u r ( numfou ) REFERENCES fournisseur ( numfou ) ; p r o p o s e r add c o n s t r a i n t f k _ p r o p o s e r _ p r o d u i t ( numprod ) REFERENCES produit ( numprod ) ; l i v r a i s o n add c o n s t r a i n t f k _ l i v r a i s o n ( numfou ) REFERENCES fournisseur ( numfou ) ; d e t a i l l i v r a i s o n add c o n s t r a i n t f k _ d e t a i l _ l i v r a i s o n ( numfou , numli ) REFERENCES livraison ( numfou , numli ) ; d e t a i l l i v r a i s o n add c o n s t r a i n t f k _ d e t a i l _ l i v r a i s o n _ p r o p o s e r ( numfou , numprod ) REFERENCES proposer ( numfou , numprod ) ; PRODUIT PRODUIT PRODUIT PRODUIT values values values values (1 , (2 , (3 , (4 , Roue de s e c o u r s ) ; c e Batman ) ; PoupA Cotons t i g e s ) ; Cornichons ) ; (1 , (2 , (3 , (4 , 1, 2, 2, 3, f1 f2 f3 f4 ); ); ); );

FOURNISSEUR FOURNISSEUR FOURNISSEUR FOURNISSEUR PROPOSER PROPOSER PROPOSER PROPOSER

values values values values (1 , (1 , (2 , (3 ,

values values values values

200); 15); 1); 2); 1); 2); 1);

INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 1 , INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 1 , INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 3 , INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO DETAILLIVRAISON DETAILLIVRAISON DETAILLIVRAISON DETAILLIVRAISON DETAILLIVRAISON values values values values values (3 , (1 , (1 , (1 , (1 , 1, 1, 1, 2, 2, 3, 1, 2, 1, 2, 10); 25); 20); 15); 17);

70

A.5

Arbre g en ealogique

La table PERSONNE, le champ pere contient le num ero du p` ere de la personne, le champ mere contient le num ero de la m` ere de la personne.
CREATE TABLE P E R S O N N E ( n u m p e r s number P R I M A R Y KEY, n o m varchar2 ( 3 0 ) N O T NULL, p r e n o m varchar2 ( 3 0 ) , pere REFERENCES PERSONNE ( numpers ) , mere REFERENCES PERSONNE ( numpers ) ); INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE PERSONNE VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (1 , (16 , (2 , (3 , (4 , (13 , (5 , (12 , (6 , (7 , (8 , (9 , (10 , (17 , (11 , (15 , (19 , (20 , (21 , (14 , (18 , de Montmirail , d i t l e Hardi , Godefroy , NULL, NULL ) ; ET , NULL, NULL, NULL ) ; Le Croquant , Jacqou , 1 , 1 6 ) ; La F r i p o u i l l e , J a c q o u i l l e , 1 , 1 6 ) ; Bush , Kate , NULL, NULL ) ; Granger , Hermione , NULL, NULL ) ; c mur , MA c dor , 3 , 4 ) ; Du FA Kobalevska Aa , S o f i a , NULL, NULL ) ; c , NULL, NULL ) ; Rieu , AndrA Bontoutou , Rex , 6 , 4 ) ; D i j k s t r a , Edvard , 2 , 1 3 ) ; L e i b n i z , G o t t f r i e 1 d Wilhem , 8 , 1 2 ) ; Bach , Johann S e b a s t i e n , 5 , 1 2 ) ; Mathieu , M i r e i l l e , NULL, NULL ) ; Lemarchal , Gregory , 1 0 , 1 7 ) ; S o c r a t e , NULL, 3 , 1 3 ) ; Leroy , Nolwen , NULL, NULL ) ; Bartoli , Jennifer , 9 , 19); Fabian , Lara , 1 0 , 1 7 ) ; Stone , Sharon , 1 5 , 2 0 ) ; Frege , E l o d i e , 7 , 1 3 ) ;

71

A.6
D R O P D R O P D R O P D R O P D R O P D R O P

Comptes bancaires
OPERATION ; TYPEOPERATION ; COMPTECLIENT ; TYPECCL ; PERSONNEL ; CLIENT ;

TABLE TABLE TABLE TABLE TABLE TABLE

CREATE TABLE C L I E N T ( n u m c l i number , n o m c l i varchar2 ( 3 0 ) , p r e n o m c l i varchar2 ( 3 0 ) , a d r e s s e varchar2 ( 6 0 ) , tel varchar (10) ); CREATE TABLE P E R S O N N E L ( n u m p e r s number , n o m p e r s varchar2 ( 3 0 ) , p r e n o m p e r s varchar2 ( 3 0 ) , m a n a g e r number , s a l a i r e number ); CREATE TABLE T Y P E C C L ( n u m t y p e c c l number , n o m t y p e c c l varchar2 ( 3 0 ) ); CREATE TABLE C O M P T E C L I E N T ( n u m c l i number , n u m c c l number , n u m t y p e c c l number , d a t e c c l d a t e d e f a u l t s y s d a t e not null , n u m p e r s number ); CREATE TABLE T Y P E O P E R A T I O N ( n u m t y p e o p e r number , n o m t y p e o p e r varchar2 ( 3 0 ) ); CREATE TABLE O P E R A T I O N ( n u m c l i number , n u m c c l number , n u m o p e r number , n u m t y p e o p e r number , d a t e o p e r d a t e d e f a u l t s y s d a t e not null , m o n t a n t o p e r number not null , l i b e l o p e r varchar2 ( 3 0 ) ); ALTER TABLE C L I E N T A D D ( CONSTRAINT p k _ c l i e n t P R I M A R Y KEY ( n u m c l i ) , CONSTRAINT c k _ t e l e p h o n e C H E C K( L E N G T H ( t e l )=10) ); ALTER TABLE P E R S O N N E L A D D ( CONSTRAINT p k _ p e r s o n n e l P R I M A R Y KEY ( n u m p e r s ) , CONSTRAINT c k _ s a l a i r e C H E C K( S A L A I R E >= 1 2 5 4 . 2 8 ) ); ALTER TABLE T Y P E C C L A D D CONSTRAINT p k _ t y p e c c l P R I M A R Y KEY ( n u m t y p e c c l ) ; ALTER TABLE T Y P E O P E R A T I O N A D D CONSTRAINT p k _ t y p e o p e r a t i o n P R I M A R Y KEY ( n u m t y p e o p e r ) ; ALTER TABLE C O M P T E C L I E N T A D D ( CONSTRAINT p k _ c o m p t e c l i e n t P R I M A R Y KEY ( n u m c l i , n u m c c l ) , CONSTRAINT f k _ c c l _ t y p e c c l FOREIGN KEY ( n u m t y p e c c l ) REFERENCES TYPECCL ( numtypeccl ) , CONSTRAINT f k _ c c l _ c l i e n t FOREIGN KEY ( n u m c l i ) REFERENCES CLIENT ( numcli ) , CONSTRAINT f k _ c c l _ p e r s o n n e l FOREIGN KEY ( n u m p e r s ) REFERENCES PERSONNEL ( numpers ) ); ALTER TABLE O P E R A T I O N A D D (

72

CONSTRAINT p k _ o p e r a t i o n P R I M A R Y KEY ( n u m c l i , n u m c c l , n u m o p e r ) , CONSTRAINT f k _ o p e r _ c c l FOREIGN KEY ( n u m c l i , n u m o p e r ) REFERENCES COMPTECLIENT ( numcli , numccl ) , CONSTRAINT f k _ o p e r _ c o d e o p e r FOREIGN KEY ( n u m t y p e o p e r ) REFERENCES typeoperation ( numtypeoper ) , CONSTRAINT m o n t a n t _ o p e r a t i o n C H E C K( m o n t a n t o p e r <> 0 ) ); INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), Compte c o u r a n t ) ; INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), livret ); INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), PEL ) ; INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), c pAt dA esp Aces ); INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), c lAvement prA ); INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), virement ) ; INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), retrait );

73

A.7
D R O P D R O P D R O P D R O P D R O P D R O P

Comptes bancaires avec exceptions


OPERATION ; COMPTECLIENT ; TYPECCL ; TYPEOPERATION ; PERSONNEL ; CLIENT ;

TABLE TABLE TABLE TABLE TABLE TABLE

CREATE TABLE C L I E N T ( n u m c l i number , n o m c l i varchar2 ( 3 0 ) , p r e n o m c l i varchar2 ( 3 0 ) , a d r e s s e varchar2 ( 6 0 ) , tel varchar (10) ); CREATE TABLE P E R S O N N E L ( n u m p e r s number , n o m p e r s varchar2 ( 3 0 ) , p r e n o m p e r s varchar2 ( 3 0 ) , m a n a g e r number , s a l a i r e number ); CREATE TABLE T Y P E C C L ( n u m t y p e c c l number , n o m t y p e c c l varchar2 ( 3 0 ) ); CREATE TABLE C O M P T E C L I E N T ( n u m c l i number , n u m c c l number , n u m t y p e c c l number , d a t e c c l d a t e d e f a u l t s y s d a t e not null , n u m p e r s number ); CREATE TABLE T Y P E O P E R A T I O N ( n u m t y p e o p e r number , n o m t y p e o p e r varchar2 ( 3 0 ) ); CREATE TABLE O P E R A T I O N ( n u m c l i number , n u m c c l number , n u m o p e r number , n u m t y p e o p e r number , d a t e o p e r d a t e d e f a u l t s y s d a t e not null , m o n t a n t o p e r number not null , l i b e l o p e r varchar2 ( 3 0 ) ); ALTER TABLE C L I E N T A D D ( CONSTRAINT p k _ c l i e n t P R I M A R Y KEY ( n u m c l i ) , CONSTRAINT c k _ t e l e p h o n e C H E C K( L E N G T H ( t e l )=10) ); ALTER TABLE P E R S O N N E L A D D ( CONSTRAINT p k _ p e r s o n n e l P R I M A R Y KEY ( n u m p e r s ) , CONSTRAINT c k _ s a l a i r e C H E C K( S A L A I R E >= 1 2 5 4 . 2 8 ) ); ALTER TABLE T Y P E C C L A D D CONSTRAINT p k _ t y p e c c l P R I M A R Y KEY ( n u m t y p e c c l ) ; ALTER TABLE T Y P E O P E R A T I O N A D D CONSTRAINT p k _ t y p e o p e r a t i o n P R I M A R Y KEY ( n u m t y p e o p e r ) ; ALTER TABLE C O M P T E C L I E N T A D D ( CONSTRAINT p k _ c o m p t e c l i e n t P R I M A R Y KEY ( n u m c l i , n u m c c l ) , CONSTRAINT f k _ c c l _ t y p e c c l FOREIGN KEY ( n u m t y p e c c l ) REFERENCES TYPECCL ( numtypeccl ) , CONSTRAINT f k _ c c l _ c l i e n t FOREIGN KEY ( n u m c l i ) REFERENCES CLIENT ( numcli ) , CONSTRAINT f k _ c c l _ p e r s o n n e l FOREIGN KEY ( n u m p e r s ) REFERENCES PERSONNEL ( numpers ) ); ALTER TABLE O P E R A T I O N A D D (

74

CONSTRAINT p k _ o p e r a t i o n P R I M A R Y KEY ( n u m c l i , n u m c c l , n u m o p e r ) , CONSTRAINT f k _ o p e r _ c c l FOREIGN KEY ( n u m c l i , n u m o p e r ) REFERENCES COMPTECLIENT ( numcli , numccl ) , CONSTRAINT f k _ o p e r _ c o d e o p e r FOREIGN KEY ( n u m t y p e o p e r ) REFERENCES typeoperation ( numtypeoper ) , CONSTRAINT m o n t a n t _ o p e r a t i o n C H E C K( m o n t a n t o p e r <> 0 A N D m o n t a n t o p e r >= 1000 A N D m o n t a n t o p e r <= 1 0 0 0 ) ); INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), Compte c o u r a n t ) ; INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), livret ); INSERT INTO T Y P E C C L VALUES ( (SELECT n v l (M A X( n u m t y p e c c l ) , 0 ) + 1 F R O M TYPECCL ), PEL ) ; INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), c pAt dA esp Aces ); INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), c lAvement prA ); INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), virement ) ; INSERT INTO T Y P E O P E R A T I O N VALUES ( (SELECT n v l (M A X( n u m t y p e o p e r ) , 0 ) + 1 F R O M TYPEOPERATION ), retrait );

75

A.8
D R O P D R O P D R O P D R O P D R O P D R O P

Secr etariat p edagogique


RESULTAT ; EXAMEN ; PREREQUIS ; INSCRIPTION ; MODULE ; ETUDIANT ;

TABLE TABLE TABLE TABLE TABLE TABLE

CREATE TABLE E T U D I A N T ( n u m E t u d number , n o m varchar2 ( 4 0 ) , p r e n o m varchar2 ( 4 0 ) , d a t e n a i s s date , c i v i l i t e varchar2 ( 4 ) , p a t r o n y m e varchar2 ( 4 0 ) , n u m s e c u varchar2 ( 1 5 ) N O T NULL ) ; CREATE TABLE M O D U L E ( c o d M o d number , n o m M o d varchar2 ( 1 5 ) , e f f e c M a x number DEFAULT 3 0 ) ; CREATE TABLE E X A M E N ( c o d M o d number , c o d E x a m number , dateExam date ) ; CREATE TABLE I N S C R I P T I O N ( n u m E t u d number , c o d M o d number , dateInsc date default sysdate ) ; CREATE TABLE P R E R E Q U I S ( c o d M o d number , c o d M o d P r e r e q number , n o t e M i n number ( 4 , 2 ) N O T NULL ) ; CREATE TABLE R E S U L T A T ( c o d M o d number , c o d E x a m number , n u m E t u d number , n o t e number ( 4 , 2 ) ) ; ALTER TABLE E T U D I A N T A D D CONSTRAINT p k _ e t u d i a n t P R I M A R Y KEY ( n u m E t u d ) ; ALTER TABLE M O D U L E A D D CONSTRAINT p k _ m o d u l e P R I M A R Y KEY ( c o d M o d ) ; ALTER TABLE E X A M E N A D D CONSTRAINT p k _ e x a m e n P R I M A R Y KEY ( c o d M o d , c o d E x a m ) ; ALTER TABLE P R E R E Q U I S A D D CONSTRAINT p k _ p r e r e q u i s P R I M A R Y KEY ( c o d M o d , c o d M o d P r e r e q ) ; ALTER TABLE I N S C R I P T I O N A D D CONSTRAINT p k _ i n s c r i p t i o n P R I M A R Y KEY ( c o d M o d , n u m E t u d ) ; ALTER TABLE R E S U L T A T A D D CONSTRAINT p k _ r e s u l t a t P R I M A R Y KEY ( c o d M o d , n u m E t u d , c o d E x a m ) ; ALTER TABLE I N S C R I P T I O N A D D (CONSTRAINT f k _ i n s c r i p t i o n _ e t u d i a n t FOREIGN KEY ( n u m E t u d ) REFERENCES ETUDIANT ( numEtud ) , CONSTRAINT f k _ i n s c r i p t i o n _ m o d u l e FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) ) ; ALTER TABLE P R E R E Q U I S A D D (CONSTRAINT f k _ p r e r e q u i s _ c o d m o d FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) , CONSTRAINT f k _ p r e r e q u i s _ c o d m o d p r e r e q FOREIGN KEY ( c o d M o d P r e r e q ) REFERENCES MODULE ( codMod ) ) ; ALTER TABLE E X A M E N A D D CONSTRAINT f k _ e x a m e n FOREIGN KEY ( c o d M o d ) REFERENCES MODULE ( codMod ) ; ALTER TABLE R E S U L T A T A D D (CONSTRAINT f k _ r e s u l t a t _ e x a m e n FOREIGN KEY ( c o d M o d , c o d E x a m ) REFERENCES EXAMEN ( codMod , codExam ) , CONSTRAINT f k _ r e s u l t a t _ i n s c r i p t i o n FOREIGN KEY ( c o d M o d , n u m E t u d ) REFERENCES INSCRIPTION ( codMod , numEtud ) ) ;

76

ALTER TABLE E T U D I A N T A D D (CONSTRAINT c k _ c i v i l i t e C H E C K ( c i v i l i t e IN ( Mr , Mme , M l l e ) ), CONSTRAINT c k _ c i v i l i t e _ n u m s e c u C H E C K ( SUBSTR( n u m s e c u , 1 , 1 ) = 2 OR p a t r o n y m e I S NULL ), CONSTRAINT c k _ l e n g t h _ n u m s e c u C H E C K ( l e n g t h ( n u m s e c u ) = 15 ), CONSTRAINT c k _ a n n e e _ n u m s e c u C H E C K ( t o _ c h a r ( d a t e n a i s s , yy ) = substr ( n u m s e c u , 2 , 2 ) ) );

77

A.9

Mariages

CREATE TABLE P E R S O N N E ( n u m p e r s number P R I M A R Y KEY, n o m varchar2 ( 3 0 ) N O T NULL, p r e n o m varchar2 ( 3 0 ) , pere REFERENCES PERSONNE ( numpers ) , mere REFERENCES PERSONNE ( numpers ) ); CREATE TABLE M A R I A G E ( nummari N U M B E R REFERENCES PERSONNE ( numpers ) , numfemme N U M B E R REFERENCES PERSONNE ( numpers ) , d a t e m a r i a g e DATE DEFAULT S Y S D A T E , d a t e d i v o r c e DATE DEFAULT NULL, P R I M A R Y KEY( n u m m a r i , n u m f e m m e , d a t e M a r i a g e ) );

78

Vous aimerez peut-être aussi