PL/SQL Programming and Concepts

Database Programming (PL/SQL) · lab

Voir tous les documents en bases de données

PL/SQL

Mehdi HAJJI [email protected]

SGBD – II2

Plan du cours

 Introduction  Structure d’un programme  Les variables  Les structures de contrôles  Interactions simples avec une Base de données  Les curseurs  Les exceptions  Les procédures et les fonctions  Les triggers  Les packages

PL/SQL

-M. HAJJI-

2

Introduction

 SQL est un langage non procédural  Les traitements complexes sont parfois difficiles à écrire si on ne peut utiliser des variables et les structures de programmation comme les boucles

 On ressent vite le besoin d’un langage procédural pour

lier plusieurs requêtes SQL avec des variables et dans les structures de programmation habituelles (les boucles et les alternatives)

 Extension de SQL : des requêtes SQL cohabitent avec les structures de contrôle habituelles de la programmation structurée (blocs, alternatives, boucles)

PL/SQL

-M. HAJJI-

3

Introduction

 Un programme est constitué de procédures et de

fonctions

 Des variables permettent l’échange d’information entre

les requêtes SQL et le reste du programme

PL/SQL

-M. HAJJI-

4

Structure d’un programme

 Blocs

 Un programme est structuré en blocs d’instructions de 3

types:  procédures anonymes  procédures nommées  fonctions nommées

 Un bloc peut contenir d’autres blocs

PL/SQL

-M. HAJJI-

5

Structure d’un programme

 Structure d’un bloc

DECLARE

-- définitions de variables

BEGIN

END; /

-- Les instructions à exécuter EXCEPTION

-- La récupération des erreurs

PL/SQL

-M. HAJJI-

6

Les variables

7

PL/SQL

-M. HAJJI-

Variables

 Identificateur Oracle:  30 caractères au plus  Commence par une lettre  Peut contenir chiffres, lettres, _, $ et #

 Pas sensible à la casse  Portée habituelle des langages à blocs  Doivent être déclarées avant d’être utilisées

PL/SQL

-M. HAJJI-

8

Commentaires

 -- pour une fin de ligne  /* pour plusieurs

lignes */

PL/SQL

-M. HAJJI-

9

Déclaration d’une variable

identifiant [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr];

Declare

v_hiredate DATE; v_deptno NUMBER(2) NOT NULL := 10; v_location VARCHAR2(13) := 'Atlanta'; v_deptno NUMBER(2) NOT NULL := 10; v_location VARCHAR2(13) := 'Atlanta'; c_comm CONSTANT NUMBER := 1400; c_comm CONSTANT NUMBER := 1400;

 Déclarations multiples interdites :

i, j integer;

PL/SQL

-M. HAJJI-

10

Variables: L’attribut %TYPE

 Déclarer une variable à partir de :

 la définition d’une colonne de la base de données  la définition d’une variable précédemment déclarée

 Préfixer %TYPE avec :

 La table et la colonne de la base  Le nom de la variable précédemment déclarée

... v_ename emp.ename%TYPE; v_balance NUMBER(7,2); v_min_balance v_balance%TYPE := 10; ...

PL/SQL

-M. HAJJI-

11

Variables: L’attribut %ROWTYPE

 Une variable peut contenir toutes les colonnes d’une

ligne d’une table

... employe emp%ROWTYPE; ...

 déclare que la variable employe contiendra une ligne de la

table emp

PL/SQL

-M. HAJJI-

12

Entrée/Sortie

 Une alternative pour l’affichage de données à partir d’un

bloc PL/SQL

DBMS_OUTPUT.PUT_LINE

dbms_output.put_line('nb = ' || nb);

 Doit être autorisée sous SQL*Plus à l’aide de :

SET SERVEROUTPUT ON

 Pour saisir des données

Accept

Accept nom_variable PROMPT ‘Saisir variable : ‘;

PL/SQL

-M. HAJJI-

13

Entrée/Sortie

 Exemple

set serveroutput on

accept vstring prompt "Please enter your name: ";

declare

v_line varchar2(40);

begin

v_line := 'Hello '||'&vstring'; dbms_output.put_line(v_line);

end; /

PL/SQL

-M. HAJJI-

14

Exemple

employe emp%ROWTYPE; nom emp.nome%TYPE; … SELECT * INTO employe

FROM emp WHERE matr = 900;

nom := employe.nome; employe.dept := 20; … INSERT INTO emp VALUES employe;

PL/SQL

-M. HAJJI-

15

Type RECORD

 Equivalent à struct du langage C

TYPE nomRecord IS RECORD ( champ1 type1, champ2 type2,

…);

 Exemple

TYPE emp2 IS RECORD (

matr integer, nom varchar(30));

employe emp2; employe.matr := 500;

PL/SQL

-M. HAJJI-

16

Affectation

 Plusieurs façons de donner une valeur à une variable :

 n :=  n par la directive INTO de la requête SELECT

 Exemples :

dateNaissance := ‘10/10/2004’;

SELECT nome INTO nom FROM emp WHERE matr = 509;

PL/SQL

-M. HAJJI-

17

Exercices

 Ecrire un programme PL/SQL qui permet d’afficher les

données d’un joueur dont le numéro est saisi par l’utilisateur.

 Ecrire un programme PL/SQL qui permet d’afficher les

informations d’un joueur, la prime et le sponsor pour un numéro, un tournoi et une année saisis.

PL/SQL

-M. HAJJI-

18

Les structures de contrôles

19

PL/SQL

-M. HAJJI-

Structures conditionnelles

IF condition THEN

instructions;

END IF;

IF condition THEN

instructions1;

ELSE

END IF;

instructions2;

IF condition1 THEN

instructions1;

ELSEIF condition2 THEN

instructions2;

ELSEIF … … ELSE

instructionsN;

END IF;

PL/SQL

-M. HAJJI-

20

Structure à choix multiples

CASE expression WHEN expr1 THEN instructions1; WHEN expr2 THEN instructions2; … ELSE instructionsN; END CASE;

PL/SQL

-M. HAJJI-

21

Structures répétitives

 Boucle « Tant que » WHILE condition LOOP

instructions;

END LOOP;

 Boucle générale LOOP

instructions;

EXIT [WHEN condition];

instructions;

END LOOP;  Boucle « pour »

FOR compteur IN [REVERSE] inf..sup LOOP

FOR i IN 1..100 LOOP

instructions;

END LOOP;

somme := somme + i;

END LOOP;

PL/SQL

-M. HAJJI-

22

Interactions simples avec une Base de données

23

PL/SQL

-M. HAJJI-

Interactions avec la base de données

 select expr1, expr2,… into var1, var2,… met des valeurs

de la BD dans une ou plusieurs variables

 Le select ne doit renvoyer qu’une seule ligne  Avec Oracle il n’est pas possible d’inclure un select sans «

into » dans une procédure ;

PL/SQL

-M. HAJJI-

24

Exemple

DECLARE

BEGIN

v_nom emp.nome%TYPE; v_emp emp%ROWTYPE;

SELECT nome INTO v_nom FROM emp WHERE matr = 500; SELECT * INTO v_emp FROM emp WHERE matr = 500;

PL/SQL

-M. HAJJI-

25

Modification de données

 Les requêtes SQL (insert, update, delete,…) peuvent

utiliser les variables PL/SQL

 Les commit et rollback doivent être explicites ; aucun n’est effectué automatiquement à la sortie d’un bloc

 Plus de détails pour l’insertion de données:

PL/SQL

-M. HAJJI-

Publicité

26

Exemple

DECLARE

v_emp emp%ROWTYPE; v_nom emp.nome%TYPE;

BEGIN

v_nom := 'Dupond'; insert into emp (matr, nome) values (600, v_nom); v_emp.matr := 610; v_emp.nome := 'Durand'; insert into emp (matr, nome) values (v_emp.matr, v_emp.nome); commit;

END;

PL/SQL

-M. HAJJI-

27

Exemple

DECLARE

v_emp emp%rowtype;

BEGIN

SELECT * INTO v_emp FROM emp WHERE nome = 'LEROY'; v_emp.matr := v_emp.matr + 5; v_emp.nome := 'Toto'; INSERT INTO emp VALUES v_emp;

END;

PL/SQL

-M. HAJJI-

28

Extraction des données: Erreurs

 Si le select renvoie plus d’une ligne, une exception « TOO_MANY_ROWS » (ORA-01422) est levée.  Si le select ne renvoie aucune ligne, une exception « NO_DATA_FOUND » (ORA-01403) est levée.

PL/SQL

-M. HAJJI-

29

Les curseurs

30

PL/SQL

-M. HAJJI-

Fonctionnalités

 Toutes les requêtes SQL sont associées à un curseur  Ce curseur représente la zone mémoire utilisée pour

parser et exécuter la requête

 Le curseur peut être implicite (pas déclaré par

l’utilisateur) ou explicite

 Les curseurs explicites servent à retourner plusieurs

lignes avec un select

PL/SQL

-M. HAJJI-

31

Attributs des curseurs

 Tous les curseurs ont des attributs que l’utilisateur peut

utiliser  %ROWCOUNT : nombre de lignes traitées par le curseur  %FOUND : vrai si au moins une ligne a été traitée par la

requête ou le dernier fetch

 %NOTFOUND : vrai si aucune ligne n’a été traitée par la

requête ou le dernier fetch

 %ISOPEN : vrai si le curseur est ouvert (utile seulement pour

les curseurs explicites)

PL/SQL

-M. HAJJI-

32

Curseurs implicites

 Les curseurs implicites sont tous nommés SQL

DECLARE

nb_lignes integer;

BEGIN

DELETE FROM emp WHERE dept = 10; nb_lignes := SQL%ROWCOUNT; . . .

PL/SQL

-M. HAJJI-

33

Curseurs explicites

 Pour traiter les select qui renvoient plusieurs lignes  Ils doivent être déclarés  Le code doit les utiliser explicitement avec les ordres

OPEN, FETCH et CLOSE

 Le plus souvent on les utilise dans une boucle dont on sort quand l’attribut NOTFOUND du curseur est vrai

PL/SQL

-M. HAJJI-

34

Curseurs explicites

DECLARE

CURSOR salaires IS

SELECT sal FROM emp WHERE dept = 10;

salaire numeric(8, 2); total numeric(10, 2) := 0; BEGIN

OPEN salaires; LOOP

FETCH salaires INTO salaire; EXIT WHEN salaires%NOTFOUND;

IF salaire IS NOT NULL THEN

total := total + salaire; DBMS_OUTPUT.put_line(total);

END IF; END LOOP; CLOSE salaires; -- Ne pas oublier DBMS_OUTPUT.put_line(total);

END;

PL/SQL

-M. HAJJI-

35

Curseurs explicites

 On peut déclarer un type « row » associé à un curseur

DECLARE

CURSOR c IS SELECT matr, nome, sal FROM emp; employe c%ROWTYPE;

BEGIN OPEN c; FETCH c INTO employe; IF employe.sal IS NULL THEN …

PL/SQL

-M. HAJJI-

36

Curseurs explicites

 Elle simplifie la programmation car elle évite d’utiliser explicitement les instruction OPEN, FETCH, CLOSE

 En plus elle déclare implicitement une variable de type «

row » associée au curseur

DECLARE

CURSOR c IS

SELECT dept, nome FROM emp WHERE dept = 10;

BEGIN

FOR employe IN c LOOP

dbms_output.put_line(employe.nome);

END LOOP;

END;

PL/SQL

-M. HAJJI-

37

Curseurs paramétrés

 Un curseur paramétré peut servir plusieurs fois avec des

valeurs des paramètres différentes

 On doit fermer le curseur entre chaque utilisation de

paramètres différents (sauf si on utilise « FOR » qui ferme automatiquement le curseur )

DECLARE

CURSOR c(p_dept integer) IS

SELECT dept, nome FROM emp WHERE dept = p_dept;

BEGIN

FOR employe in c(10) LOOP

dbms_output.put_line(employe.nome);

END LOOP; FOR employe in c(20) LOOP

dbms_output.put_line(employe.nome);

END LOOP;

END;

PL/SQL

-M. HAJJI-

38

Ligne courante d’un curseur

 La ligne courante d’un curseur est déplacée à chaque

appel de l’instruction FETCH

 On est parfois amené à modifier la ligne courante

pendant le parcours du curseur

 Pour cela on peut utiliser la clause « WHERE CURRENT OF » pour désigner cette ligne courante dans un ordre LMD (insert, update, delete)

 Il est nécessaire d’avoir déclaré le curseur avec la clause

FOR UPDATE pour que le bloc compile

PL/SQL

-M. HAJJI-

39

La clause FOR UPDATE

 FOR UPDATE [OF col1, col2,…]  Cette clause bloque toute la ligne ou seulement les

colonnes spécifiées

 Les autres transactions ne pourront modifier les valeurs

tant que le curseur n’aura pas quitté cette ligne

PL/SQL

-M. HAJJI-

40

La clause FOR UPDATE

 Exemple

DECLARE

CURSOR c IS

SELECT matr, nome, sal FROM emp WHERE dept = 10 FOR UPDATE OF emp.sal;

… IF salaire IS NOT NULL THEN total := total + salaire; ELSE -- met 0 à la place de null UPDATE emp SET sal = 0 WHERE CURRENT of c; END IF;

PL/SQL

-M. HAJJI-

41

Les exceptions

42

PL/SQL

-M. HAJJI-

Introduction

 Une exception est une erreur qui survient durant une

exécution

 2 types d’exception :  prédéfinie par Oracle  définie par le programmeur

 Structure d’un bloc:

DECLARE

-- définitions de variables

BEGIN

-- Les instructions à exécuter

EXCEPTION

-- La récupération des erreurs

END;

PL/SQL

-M. HAJJI-

43

Saisi des exceptions

 Une exception ne provoque pas nécessairement l’arrêt du programme si elle est saisie par un bloc (dans la partie « EXCEPTION »)

 Une exception non saisie remonte dans la procédure

appelante (où elle peut être saisie)

 Exceptions prédéfinies  NO_DATA_FOUND  TOO_MANY_ROWS  VALUE_ERROR (erreur arithmétique)  ZERO_DIVIDE  …

PL/SQL

-M. HAJJI-

44

Traitement des exceptions

BEGIN …

EXCEPTION

WHEN NO_DATA_FOUND THEN . . . WHEN TOO_MANY_ROWS THEN . . . WHEN OTHERS THEN -- optionnel

. . . END;

PL/SQL

-M. HAJJI-

45

Exception utilisateur

 Elles doivent être déclarées avec le type EXCEPTION  On les lève avec l’instruction RAISE

DECLARE

salaire numeric(8,2); salaire_trop_bas EXCEPTION;

BEGIN

SELECT sal INTO salaire FROM emp WHERE matr = 50; IF salaire < 300 THEN

raise salaire_trop_bas;

END IF; -- suite du bloc EXCEPTION

WHEN salaire_trop_bas THEN . . .; WHEN OTHERS THEN

dbms_output.put_line(SQLERRM);

END;

PL/SQL

-M. HAJJI-

46

Exercices  Ecrire un bloc PL/SQL qui permet d’afficher les joueurs nais

après 1970.

 Ecrire un bloc PL/SQL qui permet d’afficher toutes les

rencontres qui se sont déroulées à Roland Garros en 1992. L’affichage doit se faire sous la forme:

« Gagnant » VS « Perdant »

 Ecrire un bloc PL/SQL qui permet d’afficher la moyenne des

gains pour chaque tournoi.

 Ecrire un bloc PL/SQL « sponsorJoueurs.sql » qui permet

d’afficher les joueurs de chaque Sponsor.

 Ecrire un bloc PL/SQL qui permet d’insérer dans une Table

« primeTournoi » le total des primes pour chaque tournoi et chaque année.

PL/SQL

-M. HAJJI-

47

Exercices

 Ecrire un bloc PL/SQL qui permet d’insérer dans une table « palmares » le numéro, nom et prénom d’un joueur, le nombre de match joué dans sa carrière, le nombre de match gagné, le nombre de match perdu et le total de ses gains.

 Ecrire un bloc PL/SQL qui permet de mettre à jour les

informations nombre de match joués, nombre de matchs gagnés, nombre de matchs perdus et total des gains.

PL/SQL

-M. HAJJI-

48

Les procédures et les fonctions

Publicité

49

PL/SQL

-M. HAJJI-

Bloc anonyme ou nommé

 Un bloc anonyme PL/SQL est un bloc «DECLARE –

BEGIN –END» comme dans les exemples précédents  Dans SQL*PLUS on peut exécuter directement un bloc

PL/SQL anonyme en tapant sa définition

 Le plus souvent, on crée plutôt une procédure ou une

fonction nommée pour réutiliser le code

PL/SQL

-M. HAJJI-

50

Création d’une procédure

CREATE OR Replace PROCEDURE(<liste params>) IS -- déclaration des variables BEGIN -- code de la procédure END;

 Pas de DECLARE ; les variables sont déclarées entre IS et

BEGIN

 Si la procédure ne nécessite aucune déclaration, le code

est précédé de « IS BEGIN »

PL/SQL

-M. HAJJI-

51

Création d’une fonction

CREATE OR Replace FUNCTION(<liste params>) RETURN <type retour> IS -- déclaration des variables BEGIN -- code de la procédure END;

PL/SQL

-M. HAJJI-

52

Passage de paramètres

 Dans la définition d’une procédure on indique le type de

passage que l’on veut pour les paramètres :  IN pour le passage par valeur  IN OUT pour le passage par référence  OUT pour le passage par référence mais pour un paramètre

dont la valeur n’est pas utilisée en entrée

 Pour les fonctions, seul le passage par valeur (IN) est

autorisé

PL/SQL

-M. HAJJI-

53

Utilisation des procédures et fonctions

 Sous SQL*PLUS, il faut taper une dernière ligne contenant

« / » pour compiler une procédure ou une fonction  Les procédures et fonctions peuvent être utilisées dans d’autres procédures ou fonctions ou dans des blocs PL/SQL anonymes

 Les fonctions peuvent aussi être utilisées dans les

requêtes SQL

 Exemple CREATE OR REPLACE FUNCTION euro_to_fr(somme IN number) RETURN number IS

taux CONSTANT NUMBER := 6.55957;

BEGIN

return somme * taux;

END;

PL/SQL

-M. HAJJI-

54

Utilisation des procédures et fonctions

 Dans un bloc anonyme

DECLARE

CURSOR c(p_dept integer) IS

SELECT dept, nome, sal FROM emp WHERE dept = p_dept;

BEGIN

FOR employe IN c(10) LOOP

dbms_output.put_line(employe.nome

|| ' gagne ' || euro_to_fr(employe.sal) || ' francs'); END LOOP;

END;

 Dans une requête

SELECT nome, sal, euro_to_fr(sal) FROM emp;

PL/SQL

-M. HAJJI-

55

Exécution d’une procédure

 Sous SQL*PLUS on exécute une procédure PL/SQL avec

la commande EXECUTE : EXECUTE nomProcédure(param1, …);

 Sous SQL*PLUS on exécute une fonction PL/SQL avec la

commande select: SELECT nomFonction(param1, …) FROM dual;

PL/SQL

-M. HAJJI-

56

Exercices

 Ecrire une fonction MaxPS qui permet de retourner le

maximum entre deux valeurs « a » et « b ».

 Exécuter la fonction MaxPS directement sous SQL*PLUS,

en définissant les paramètres.

 Dans un programme principal, afficher pour un tournoi et une année donnés, le Nom et Prénom du joueur ayant eu la plus haute prime, en faisant appel à la fonction MaxPS.  Dans un programme principal, afficher le Nom et Prénom du joueur ayant eu le cumul le plus important durant une année donnée, en utilisant la fonction MaxPS.

PL/SQL

-M. HAJJI-

57

Exercices

 Ecrire une fonction RatePS qui permet de calculer le pourcentage d’une valeur par rapport à une valeur globale.

 Dans un programme principal, afficher pour un tournoi et une année donnés, le Nom, Prénom et le pourcentage de la prime de chaque joueur par rapport à la prime globale.

 Dans un programme principal, afficher le Nom et le

Prénom du joueur, ainsi que le pourcentage de sa prime par rapport au cumul de toutes les primes dans une année donnée, pour le joueur ayant eu le plus important pourcentage. On utilisera les fonctions RatePS et MaxPS.

 Exécuter la fonction RatePS sous SQL*Plus.

PL/SQL

-M. HAJJI-

58

Exercices

 Ecrire une procédure WinnersPS qui prend en paramètre le nom d’un tournoi, et qui affiche la liste des vainqueurs de ce tournoi (Nom et Prénom) ainsi que l’année.

 Exécuter la procédure WinnersPS à partir de SQL*Plus.  Dans un programme PL/SQL, faire appel à la procédure

WinnersPS pour afficher la liste des vainqueurs des tournois qui se sont passés dans un intervalle de dates donné.

 Ecrire une procédure UpdatePalmPS qui permet de mettre à jour les champs nombre de match joué, nombre de match gagné, nombre de match perdu et total des gains de la table « palmares » (TP précèdent). Les valeurs sont passées en paramètres.

PL/SQL

-M. HAJJI-

59

Les Triggers

60

PL/SQL

-M. HAJJI-

Introduction  Un trigger est un programme qui se déclenche

automatiquement suite à un évènement  A la différence d’une procédure stockée, on ne peut pas appeler un trigger explicitement.

 En base de données, l’évènement est une instruction du DML

qui modifie la base.(INSERT, DELETE, UPDATE)

 Ces triggers font partie du schéma de la base. Leur code

compilé est conservé (comme pour les programmes stockés)  Les triggers peuvent servir à vérifier des contraintes que l’on

ne peut pas définir de façon déclarative

 Ils peuvent aussi gérer de la redondance d’information.  Ils peuvent aussi servir à collecter des informations sur les

mises-à-jour de la base

PL/SQL

-M. HAJJI-

61

Syntaxe

CREATE [ OR REPLACE ] TRIGGER <nom_trigger>

<instant> <liste_evts>

ON <nom_table> [ FOR EACH ROW ]

[ WHEN ( <condition> ) ]

<corps>

PL/SQL

-M. HAJJI-

62

Entête du trigger

 On définit  La table  Les instructions qui déclenchent le trigger  Le moment où le trigger va se déclencher par rapport à

l’instruction (avant ou après)

 Si le trigger se déclenche

 une seule fois pour toute l’instruction (i.e. trigger instruction ou

trigger de table)

 ou une fois pour chaque ligne modifiée/insérée/supprimée (i.e. trigger

ligne, avec l’option FOR EACH ROW)

 Et éventuellement une condition supplémentaire de

déclenchement (clause WHEN) pour les triggers ligne.

PL/SQL

-M. HAJJI-

63

Conditions d’un trigger

 Le trigger se déclenche lorsqu’un événement précis survient : BEFORE UPDATE, AFTER DELETE, AFTER INSERT, …

 Ces événements sont importants car ils définissent le

moment d’exécution du trigger.

 Ainsi, lorsqu’un trigger BEFORE INSERT est programmé, il sera exécuté juste avant l’insertion d’un nouvel élément dans la table.

PL/SQL

-M. HAJJI-

64

Conditions d’un trigger

 Si le trigger doit déterminer si l’instruction est autorisée :

utiliser BEFORE

 Si le trigger doit ”fabriquer” la valeur d’une colonne pour pouvoir ensuite la mettre dans la table : utiliser BEFORE.  Par exemple : trigger ligne qui fabrique la valeur de clef

primaire à partir d’une séquence.

 Si on a besoin que l’instruction soit terminée pour

exécuter le corps du trigger : utiliser AFTER

 pour des triggers lignes, il se peut que l’utilisation de

Before ou After n’ait aucune importance.

PL/SQL

-M. HAJJI-

65

Code du trigger  Le trigger Oracle doit être écrit en PL/SQL.  La forme d’un trigger est encore très dépendante du SGBD utilisé.

CREATE OR REPLACE TRIGGER Print_salary_changes BEFORE UPDATE ON Emp_tab FOR EACH ROW WHEN (new.Empno > 0) DECLARE sal_diff number; BEGIN sal_diff := :new.sal - :old.sal; dbms_output.put(' Old : ' || :old.sal || 'New : ' || :new.sal || 'Difference : ' || sal_diff); END ;

 Ce trigger est déclenché lorsque la table Emp_tab est mise à jour.

 Pour chaque modification (lignes mises à jour), le trigger va calculer puis afficher respectivement l’ancien salaire, le nouveau salaire et la différence entre ces deux salaires.

 La condition précisée (WHEN new.Empno > 0) restreint le

déclenchement du trigger (exécuté uniquement si new.Empno > 0)

PL/SQL

-M. HAJJI-

66

Les types de triggers

 Il existe deux types de triggers différents : les triggers de

table (STATEMENT) et les triggers de ligne (ROW).

 Les triggers de table sont exécutés une seule fois lorsque des modifications surviennent sur une table (même si ces modifications concernent plusieurs lignes de la table).  Ils sont utiles si des opérations de groupe doivent être

réalisées (comme le calcul d’une moyenne, d’une somme totale, d’un compteur, …).

 Pour des raisons de performance, il est préférable

d’employer ces triggers plutôt que les triggers lignes.

PL/SQL

-M. HAJJI-

67

Les types de triggers  Exemple

CREATE TRIGGER log AFTER INSERT OR UPDATE ON Emp_tab BEGIN

INSERT INTO log(table, date, username, action) VALUES ('Emp_tab', sysdate, sys_context('USERENV',

'CURRENT_USER'), 'INSERT/UPDATE on Emp_tab') ; END ;

 Ce trigger table enregistre dans une table log la trace de la

modification de la table Emp_tab.

 On mémorise ici le moment de la modification et l’utilisateur

qui l’a provoqué.

 Il n’est donc exécuté qu’une seule fois par modification de la

table Emp_tab.

PL/SQL

-M. HAJJI-

68

Les types de triggers  Les triggers lignes sont exécutés « séparément » pour chaque

ligne modifiée dans la table.

 Ils sont très utiles s’il faut mesurer une évolution pour

certaines valeurs, effectuer des opérations pour chaque ligne en question.

 Lors de la création de triggers lignes, il est possible d’avoir

accès à la valeur ancienne et la valeur nouvelle grâce aux mots clés OLD et NEW.  Il faut préfixer ces qualificatifs de deux points (:) dans tout

ordre SQL ou PL/SQL les utilisant.

 Il ne faut pas utiliser de préfixe deux points (:) quand les qualificatifs

sont utilisés dans la condition de restriction WHEN

 Il n’est pas possible d’avoir accès à ces valeurs dans les triggers

de table.

PL/SQL

-M. HAJJI-

69

Les types de triggers

 Exemple

CREATE OR REPLACE TRIGGER totalSalaire AFTER UPDATE OF salaire ON emp REFERENCING OLD AS ancien, NEW AS nouveau FOR EACH ROW

update cumul set augmentation = augmentation + nouveau.salaire - ancien.salaire where matricule = ancien.matricule

PL/SQL

-M. HAJJI-

70

Les types de triggers

 :OLD et :NEW

CREATE OR REPLACE TRIGGER totalSalaire AFTER UPDATE OF salaire ON emp FOR EACH ROW

UPDATE cumul SET augmentation = augmentation + :NEW.salaire - :OLD.salaire WHERE matricule = :OLD.matricule

 La clause WHEN

CREATE OR REPLACE TRIGGER modifsalaire BEFORE UPDATE OF sal ON emp FOR EACH ROW WHEN (new.sal < old.sal) BEGIN

raise_application_error(-20001,'Interdit de baisser le salaire ! ('

|| :old.nome || ')'); END;

PL/SQL

-M. HAJJI-

71

Publicité

Les types de trigger

 Trigger de table :

 Le trigger est exécuté une fois pour l’ensemble de l’instruction

 pas de notion de ligne courante.

 Trigger ligne :

 notion de ligne courante, :old désigne la ligne avant

modification et :new désigne la ligne après modification.

Insert

Delete

Update

PL/SQL

:old

null

:new

Valeur insérée

Valeur supprimée

Null

Valeur avant modification

Valeur après modification

-M. HAJJI-

72

Ordre d’exécution es triggers

 Pour une instruction du DML sur une table de la base, il peut y avoir 4 sortes de triggers possibles selon l’instant (before, after) et le type (instruction ou ligne).  Ces triggers se déclenchent dans l’ordre suivant :

 Trigger(s) instruction BEFORE  Pour chaque ligne concernée

 Trigger(s) ligne BEFORE  Trigger(s) ligne AFTER

 Trigger(s) instruction AFTER

PL/SQL

-M. HAJJI-

73

Activation / Désactivation des triggers

 Lorsqu’un trigger est créé, il est automatiquement activé  Désactiver un trigger :

ALTER TRIGGER trigger_name DISABLE

 Activer un trigger :

ALTER TRIGGER trigger_name ENABLE

 Activer ou désactiver tous les triggers d’une table :

ALTER TABLE table_name DISABLE | ENABLE ALL TRIGGERS

PL/SQL

-M. HAJJI-

74

Remarques

 Recompiler un trigger:

ALTER TRIGGER trigger_name COMPILE  le trigger est recompilé sans perdre sa validité (actif) ou son

invalidité(non actif).

 Afficher les erreurs de compilation : SHOW ERRORS

 Supprimer un trigger :

DROP TRIGGER nomTrigger

 Ordres interdits

 Les ordres COMMIT et ROLLBACK sont interdits dans un

trigger

PL/SQL

-M. HAJJI-

75

Remarques  Lorsque l’on veut appeler une procédure depuis un

trigger on utilise la commande CALL :

CREATE TRIGGER TEST3 BEFORE INSERT ON EMP CALL AFFICHER /

 Nom des triggers et leurs propriétaires SELECT owner, object_name FROM all_objects WHERE object_type = ‘TRIGGER' ORDER BY owner, object_name;

PL/SQL

-M. HAJJI-

76

Exercices

 Ecrire un trigger qui permet de mettre à jour la table

palmares à chaque nouvelle rencontre jouée.

 Ecrire un trigger qui contrôle les primes des joueurs. Si un joueur participe à un tournoi, il doit obligatoirement avoir une prime. Dans le cas contraire, la prime doit être égale à 10000€.

 Ecrire un trigger qui contrôle le minimum de prime pour

les joueurs perdant dans les tournoi.

 Ecrire un trigger qui contrôle le maximum de prime pour

les joueurs vainqueurs de tournois.

PL/SQL

-M. HAJJI-

77

Exercices

 Ecrire un trigger qui se déclenche avant l'insertion d'un tuple dans la table Gain, et qui transforme la valeur de la prime en euro si la date du tournoi est antérieure à 2001.  Taux de conversion : 1 franc = 0,152 €

 Ecrire un trigger qui se déclenche avant l’insertion d’un tuple dans la table gain, et qui vérifie si au moins une rencontre a été enregistrée pour le joueur en question dans le tournoi et l’année considéré.

PL/SQL

-M. HAJJI-

78

Les Packages

79

PL/SQL

-M. HAJJI-

Introduction  Un package est similaire à la notion de classe dans

l’orienté objet.

 Il regroupe des procédures, des fonctions, des variables,

des constantes, des curseurs et des traitements d’exceptions qui ont un lien logique entre eux, sous une seule entité.

 Les procédures et les fonctions peuvent être:

 Publiques: PUBLIC: c’est à dire appelées depuis l’extérieur

du package.

 Privées: PRIVATE: qui sont invisibles à l’extérieur et accessibles uniquement à des procédures du même package.

PL/SQL

-M. HAJJI-

80

Organisation d’un Package  Un paquetage est organisé en deux parties distinctes  Une partie spécification

 Permet de spécifier à la fois les fonctions et procédures publiques ainsi que les déclarations des types, variables, constantes, exceptions et curseurs utilisés dans le paquetage et visibles par le programme appelant.

 Une partie corps

 Contient les blocs et les spécifications de tous les objets

publics listés dans la partie spécification.

 Cette partie peut inclure des objets qui ne sont pas listés dans

la partie spécification, et sont donc privés.

 Cette partie peut également contenir du code qui sera exécuté

à chaque invocation du paquetage par l'utilisateur

PL/SQL

-M. HAJJI-

81

Organisation d’un Package

 La déclaration de la partie spécification d'un paquetage

s'effectue avec l'instruction

CREATE [OR REPLACE] PACKAGE

 Celle de la partie corps avec l'instruction

CREATE [OR REPLACE] PACKAGE BODY

PL/SQL

-M. HAJJI-

82

Exemple: Spécification d’un package

CREATE OR REPLACE PACKAGE Pkg_Finance IS

-- Variables globales et publiques GN_Salaire EMP.sal%Type ;

-- Fonctions publiques FUNCTION F_Test_Augmentation (

PN_Numemp IN EMP.empno%Type ,PN_Pourcent IN NUMBER

) Return NUMBER ;

-- Procédures publiques PROCEDURE Test_Augmentation (

PN$Numemp IN EMP.empno%Type -- numéro de l'employé ,PN$Pourcent IN OUT NUMBER -- pourcentage d'augmentation

) ;

End Pkg_Finance ; /

PL/SQL

-M. HAJJI-

83

Exemple : Corps d’un package

CREATE OR REPLACE PACKAGE BODY Pkg_Finance IS

-- Variables globales privées GR_Emp EMP%Rowtype ;

-- Procédure privées PROCEDURE Affiche_Salaires IS

CURSOR C_EMP IS select * from EMP ; BEGIN

OPEN C_EMP ; Loop

FETCH C_EMP Into GR_Emp ; Exit when C_EMP%NOTFOUND ;

dbms_output.put_line( 'Employé ' || GR_Emp.ename || ' --> ' ||

Lpad( To_char( GR_Emp.sal ), 10 ) ) ;

End loop ; CLOSE C_EMP ; END Affiche_Salaires ;

PL/SQL

-M. HAJJI-

84

Exemple : Corps d’un package

-- Fonctions publiques FUNCTION F_Test_Augmentation (PN_Numemp IN EMP.empno%Type,

PN_Pourcent IN NUMBER 25 )

Return NUMBER IS

LN_Salaire EMP.sal%Type ; BEGIN

Select sal Into LN_Salaire From EMP Where empno = PN_Numemp ; -- augmentation virtuelle de l'employé 31 LN_Salaire := LN_Salaire *

PN_Pourcent ;

-- Affectation de la variable globale publique GN_Salaire := LN_Salaire ; Return( LN_Salaire ) ; -- retour de la valeur

END F_Test_Augmentation;

PL/SQL

-M. HAJJI-

85

Exemple : Corps d’un package

-- Procédures publiques PROCEDURE Test_Augmentation ( PN_Numemp IN EMP.empno%Type,

PN_Pourcent IN OUT NUMBER)

IS

LN_Salaire EMP.sal%Type ; BEGIN

Select sal Into LN_Salaire From EMP Where empno = PN_Numemp ;

-- augmentation virtuelle de l'employé PN_Pourcent := LN_Salaire * PN_Pourcent ;

-- appel procédure privée Affiche_Salaires ; END Test_Augmentation;

END Pkg_Finance; /

PL/SQL

-M. HAJJI-

86

Organisation d’un Package  La spécification du paquetage est créée avec  une variable globale et publique : GN_Salaire  une procédure publique : PROCEDURE Test_Augmentation  une fonction publique : FUNCTION F_Test_Augmentation qui sont visibles depuis l'extérieur (le programme appelant)

 Le corps du paquetage est créé avec une procédure privée :

 PROCEDURE Affiche_Salaires qui n'est visible que dans le corps du

paquetage

 Le corps définit également une variable globale au corps du

paquetage :  GR_Emp utilisée par la procédure privée

PL/SQL

-M. HAJJI-

87

Accès/Suppression

 L'accès à un objet d'un paquetage est réalisé avec la

syntaxe suivante : nom_paquetage.nom_objet[(liste paramètres)]  L'exécution d'une procédure d'un package s'effectue par

la commande

EXECUTE nom_package.nom_procédure(liste_paramètres effectifs) ;

 Suppression d’un Package

 DROP PACKAGE package_name;  DROP PACKAGE BODY package_name;

PL/SQL

-M. HAJJI-

88

Accès

 Appel de la fonction F_Test_Augmentation du paquetage

Declare

Begin

End ; /

LN_Salaire emp.sal%Type ;

Select sal Into LN_Salaire From EMP Where empno = 7369 ; dbms_output.put_line( 'Salaire de 7369 avant augmentation ‘

|| To_char( LN_Salaire ) ) ;

dbms_output.put_line( 'Salaire de 7369 après augmentation ‘

|| To_char( Pkg_Finance.F_Test_Augmentation( 7369, 1.1 ) ) ) ;

PL/SQL

-M. HAJJI-

89

Accès

 Appel de la procédure Test_Augmentation du paquetage

Declare

Begin

LN_Pourcent NUMBER := 1.1 ;

Pkg_Finance.Test_Augmentation( 7369, LN_Pourcent ) ; dbms_output.put_line( 'Employé 7369 après augmentation : ' || To_char(

LN_Pourcent ) ) ; End ; /

PL/SQL

-M. HAJJI-

90

Accès

 Interrogation de la variable globale publique : GN_Salaire

Begin

End ; /

dbms_output.put_line( 'Valeur salaire du package : '

|| To_char( Pkg_Finance.GN_Salaire ) ) ;

PL/SQL

-M. HAJJI-

91

Merci…

PL/SQL

-M. HAJJI-

92