Académique Documents
Professionnel Documents
Culture Documents
Chap4 PL SQL Cursor Fonction Proc Trigger
Chap4 PL SQL Cursor Fonction Proc Trigger
Principales caractéristiques
▴
Langage PL/SQL
Utilisation de PL/SQL
PL/SQL peut être utilise pour l’écriture des procédures stockées et des
triggers.
PL/SQL convient aussi pour écrire des fonctions utilisateurs qui peuvent être
utilisées dans les requêtes SQL (en plus des fonctions prédéfinies).
▴
Langage PL/SQL
1
un bloc de code, exécuté comme une unique commande SQL, via un
interpréteur standard (SQLplus ou iSQL*PLus)
2
▴
Langage PL/SQL
Blocs
fonctions nommées.
DECLARE
−- d e f i n i t i o n d e s v a r i a b l
Seuls BEGIN et END
es
sont
BEGIN
−− c o d e du
obligatoires
programme
Les blocs se terminent par un ;
EXCEPTION
−− c o d e de g e s t i o n d es
erreurs
END ;
Commentaires
-- Pour une fin de ligne
/* Pour
plusieurs
lignes */
Langage PL/SQL
Identificateurs Oracle :
30 caractères au plus,
Déclaration et initialisation
Syntaxe : Nom_variable type_variable := valeur;
Initialisation
Nom_variable := valeur;
age integer;
nom varchar(30);
dateNaissance date;
ok boolean := true;
▴
Langage PL/SQL
Exemples
dateNaissance := to_date(’10/10/2004’,’DD/MM/YYYY’);
V_sal:= 4000
Attention
Pour eviler les conflits de nommage, préfixer les variables PL/SQL par v_
Langage PL/SQL
Instruction :
SELECT expr1,expr2, ...INTO var1, var2, ...
Met des valeurs de la BD dans une ou plusieurs variables var1, var2, ...
Avec Oracle il n’est pas possible d’inclure un SELECT sans INTO dans un programme
PL/SQL.
Pour retourner plusieurs lignes, voir la suite du cours sur les curseurs.
▴
Langage PL/SQL
Types de variables
VARCHAR2
Longueur maximale : 32767 octets ;
Exemples :
name VARCHAR2(30);
name VARCHAR2(30) := ’toto’ ;
NUMBER(long,dec)
Long : longueur maximale ;
Dec : longueur de la partie décimale ;
Exemples.
Num_tel number(10);
Salaire number(5,2):=142.12 ;
▴
Langage PL/SQL
Types de variables (suite)
DATE
Fonction TO DATE ;
Exemples :
Start_date := to_date(’29-SEP-2003’,’DD-MON-YYYY’);
La vraible sttart date est evaluée et analysée par oracle par 2 chiffre pour le jour, trois
letters pour le mois et l’année sur 4 chirffrer separées par un tiret (-)
start_date := to _date(’29-SEP-2003:13:01’,’DD-MON-YYYY:HH24:MI’) ;
Ici La vraible start_date est evaluée et analysée par oracle par 2 chiffre pour le jour,
trois letters pour le mois et l’année sur 4 chirffrer separées par un tiret (-). Avec aussi
l’heurs et les minutes
BOOLEAN
TRUE
FALSE
NULL
▴
Langage PL/SQL
Déclaration %TYPE et %ROWTYPE
V_nom emp.nom.%TYPE;
Une variable peut contenir toutes les colonnes d’un tuple d’une
table
(la variable v_employe contiendra une ligne de la table emp).
Important pour la robustesse du code
▴
Langage PL/SQL
Déclaration %TYPE et %ROWTYPE
-Exemple
DECLARE
v_employe EMPLOYEES%ROWTYPE;
v_nom EMPLOYEES.FIRST_NAME%TYPE;
BEGIN
SELECT * INTO v_employe FROM EMPLOYEES
WHERE employee_id=100 ;
v_nom :=v_employe.FIRST_NAME;
v_employe.department_id:=20; Vérifier à bien retourner un seul tuple
v_employe.employee_id:=7777; avec la reqête SELECT ...INTO ...
v_employe.EMAIL:='changyah';
INSERT into employees VALUES v_employe;
dbms_output.put_line ('ttt '|| v_employe.employee_id);
END;
▴
Exercice :
a- Créer un bloc PL/SQL pour insérer un nouveau département dans la table
DEPARTEMENTS (DEPT_ID, DEPT_NAME, LOCATION_ID)
- Utiliser la séquence DEPT_ID_SEQ pour générer un numéro de département
(DEPT_ID).
- Créer un paramètre pour lire le nom du département du clavier.
- Laisser le numéro de LOCATION_ID à NULL.
- Afficher le numéro de département qu »on vient d’inseré
b- enregistrer le code dans le fichier scipt1.sql , donner la commande de
exécution de scipt1.sql .
Solution
set serveroutput ON
ACCEPT p_dept_nom PROMPT ‘Entrer un nom de département : ‘
Declare
Numd number;
BEGIN
INSERT INTO departments VALUES (dept_id_seq.NEXTVAL, '&p_dept_nom', NULL,null);
COMMIT;
Select dept_id_seq.CURRVAL into Numd from dual;
dbms_output.put_line ('num depart inseré est '|| Numd);
END;
/
Execution ( le code est enregistré dans le fichier script1.sql
SQL> start script1.sql
Ou
SQL> @ script1.sql
Exercice 2
Créer un bloc PL/SQL pour supprimer le département créé
précédemment en
-Créant r un paramètre pour le numéro de département à
supprimer ,
-A ffichant le nombre de département avant et après la suppression
Langage PL/SQL : Commandes
La commande GOTO
Affichage dbms_output.put_line ()
et retour chariot chr(10)
Langage PL/SQL : Commandes
Test conditionnel
IF-THEN
END I
F;
IF-THEN-ELSE
END I F ;
▴
Langage PL/SQL : Commandes
Test conditionnel(2)
IF-THEN-ELSIF
END I F ;
▴
Langage PL/SQL : Commandes
CASE CASE renvoie une valeur qui
vaut resultat1 ou resultat2 ou . . . ou
resultat par défaut
CASE selection
WHEN expression1 THEN resultat1 ou instruction 1
.
WHEN expression2 THEN resultat2 ou instruction 2
ELSE autre resultat ou autre instruction
END ;
Exemple de Case Dans une requette SQL
Declare
LN$Num integer := 0 ;
Begin
LN$Num := '&entre' ;
CASE LN$Num
WHEN 1 Then dbms_output.put_line( ' premier' ) ;
WHEN 2 Then dbms_output.put_line( 'deuxieme' ) ;
WHEN 3 Then dbms_output.put_line( 'troisiem' ) ;
ELSE dbms_output.put_line( 'rang supérieur' ) ;
END CASE ;
End ;
/
Langage PL/SQL : Commandes
CASE : Exemple dans un bloc PL/SQL
Case de recherche
DECLARE
v_prix_vente NUMBER(9,2);
v_Value NUMBER(9,2) := &v_prix_vente;
v_taux_Commission NUMBER(3,2);
BEGIN
CASE
WHEN v_Value <= 100 THEN v_taux_Commission := 0.03;
WHEN v_Value <= 250 THEN v_taux_Commission := 0.05;
WHEN v_Value <= 1000 THEN v_taux_Commission := 0.08;
ELSE v_taux_Commission := 0.10;
END CASE;
DBMS_OUTPUT.PUT_LINE('Montant de la Commission est : '
|| TO_CHAR(v_taux_Commission * v_Value) || 'Dirhames');
END;
declare
...
V_Date DATE;
V_compteur NUMBER( 2 ) := 1 ;
BEGIN
...
V_Date := SYSDATE;
LOOP
INSERT INTO article ( Artno , ADate )
VALUES ( v_compteur , v_Date ) ;
V_compteur := V_compteur + 1 ;
EXIT WHEN V_compteur > 1 0;
END LOOP;
...
END;/
Langage PL/SQL : Commandes
Les boucles : FOR
FOR indice IN [ REVERSE ] debut . . fin
LOOP Ne pas déclarer indice,
instructions ; il est d´eclaré implicitement.
END LOOP ;
La variable de boucle prend successivement les valeurs de
debut, debut + 1, debut + 2, . . ., jusqu’à la valeur fin .
On pourra également utiliser un curseur dans la clause IN
▴
Langage PL/SQL : Commandes
GOTO
GOTO <libelé>;
Langage PL/SQL : Commandes
GOTO
DECLARE
v_compteur NUMBER(2) := 1;
BEGIN
LOOP
v_compteur := v_compteur + 1;
IF v_compteur > 5 THEN
GOTO stop_processing;
END IF;
DBMS_OUTPUT.PUT_LINE('v_compteur est : '
|| v_compteur);
END LOOP;
<<stop_processing>>
DBMS_OUTPUT.PUT_LINE(' la valeur finale de
v_compteur final est ' || v_compteur );
END;
Langage PL/SQL : Commandes
Affichage
Activer le retour écran : set serveroutput on size 10000
Sortie standard : dbms_output.put_line (chaıne);
Concaténation de chaînes : opérateur ||
Exemple
Si on veut un retour chariot
on place le caractére suivant:
DECLARE chr(10)
i number (2);
BEGIN
FOR i IN 1 .. 5 LOOP ’
dbms_output.put_line('Nombre: ‘|| i );
END LOOP;
END ;
/
▴
Langage PL/SQL : Commandes
Affichage
Exemple bis
DECLARE
compteur number(3);
i number(3);
BEGIN
SELECT COUNT( ∗ ) INTO compteur
FROM Etudiant ;
FOR i IN 1.. compteur LOOP
dbms_output.put_line(‘Nombre : ‘|| i);
END LOOP ;
END ;
Gestion des Erreurs
Section Exception
Anomalie programmeur
Erreur Oracle
Section Exception
Types d’erreurs:
Règles à respecter
Syntaxe
EXCEPTION
DECLARE
.....
nom_erreur EXCEPTION;
BEGIN
.....
IF anomalie THEN RAISE nom_erreur ;
.....
EXCEPTION
WHEN nom_erreur THEN traitement;
END;
Gestion d’une erreur : exemple
DECLARE
sal_nul EXCEPTION;
sal employees.salary%TYPE;
BEGIN
SELECT MAX(salary) INTO sal FROM employees;
IF sal > 100000
THEN RAISE sal_nul;
Else
dnms_output.put_line(‘vous pouvez augmenter le salaire de vos
employés’);
END IF;
EXCEPTION
WHEN sal_nul THEN
dnms_output.put_line(‘plafond dépassé’)
END;
Exceptions Prédéfinies
• DUP_VAL_ON_INDEX
– Lorsqu’une instruction SQL tente de créer une valeur dupliquée dans une
colonne sur laquelle un index unique a été défini
• INVALID_NUMBER
– Lorsqu’une instruction SQL spécifie un nombre invalide (conversion d’un
caractère à un entité
ex: select * from employees where employee_id=‘Chaine_de_caractère‘
- lors d’une insertion
• NO_DATA_FOUND
– Lorsqu’une instruction Select ne retourne aucune ligne
• TOO_MANY_ROWS
– Une instruction Select ne peut pas renvoyer plus d’une ligne sans provoquer
l’exception TOO_MANY_ROWS
• VALUE_ERROR
– Provoquée dans des situations d’erreur résultant de valeurs tronquées ou
converties ( exp: taille de la variable petite que le nombre à affecter)
• ZERO_DIVIDE: au cas ou il y a une instruction qui effectue une division par Zéro
Exemple
Declare emp_Rec employees%ROWTYPE;
Begin
select *
into emp_Rec
from employees
where employee_ID = 777;
Exception
when No_Data_Found then
dbms_output.put_line(‘Aucune donnée retournée’);
when other then null;
End;
/
Aucune donnée retournée
Procedure PL/SQL terminé avec succès.
Déclaration d’une Exception
Declare
pas_comm EXCEPTION;
salaire employees.salary%TYPE;
commi employees.commition%TYPE;
numero employees.employee_id%TYPE;
Begin
Select salary, commition, employee_id into salaire, commi, numero
from employees where employee_id := &num_emp;
If commi = 0 or commi is null
then raise pas_comm
else traitement …
end if;
Exception When pas_comm then
dbms_output.put_line(‘ Pas de commission pour l’employé ID: ’|| numero);
End;
Exemple 1:
Declare
Begin
dbms_output.enable; // equivalente à set serveroutput on
dbms_output.put_line(‘SQLCODE: ‘ || to_char(SQLCODE));
dbms_output.put_line(‘SQLERRM: ‘ || SQLERRM);
End;
/
SQLCODE: 0
SQLERRM: ORA-0000: exécution normale, terminé avec succès
Test d’exécution avec SQLCODE et SQLERRM
Exemple 2:
Declare
v number;
Begin
select salary into v from employees;
dbms_output.enable; -- equivalente à set serveroutput on
Exception
when TOO_MANY_ROWS then
dbms_output.put_line('SQLCODE:'|| to_char(SQLCODE));
dbms_output.put_line('SQLERRM:' || SQLERRM);
End;
Test d’exécution avec SQLCODE et SQLERRM
Exemple 3: complet
Declare
pas_err EXCEPTION;
v number;
Begin
select salary into v from employees where employee_id=100;
if(SQLCODE=0) then raise pas_err;
end if;
Exception
when TOO_MANY_ROWS then
dbms_output.put_line('SQLCODE:'|| to_char(SQLCODE));
dbms_output.put_line('SQLERRM:' || SQLERRM);
when NO_DATA_FOUND OR TOO_MANY_ROWS then
dbms_output.put_line('SQLCODE:'|| to_char(SQLCODE));
dbms_output.put_line('SQLERRM:' || SQLERRM);
WHEN pas_err THEN
dbms_output.put_line('C''est corecte ');
End;
Les curseur
• Définition
Declare
cursor dept_10 is select first_name , salary From
employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
…
End;
Ouverture d’un curseur : Open
• L’ouverture:
– Allocation de mémoire pour le lignes du curseur
– L’analyse syntaxique et sémantique du select
– Le positionnement de verrous éventuels
• L’ouverture se fait dans la section Begin
• Syntaxe: OPEN nom_curseur;
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
Begin
…;
open dept_10;
…;
End;
Traitement des lignes : Fetch
Syntaxe:
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
Open dept_10;
Loop
Fetch dept_10 into nom, salaire;
If salaire > 2500
then insert into résultat values (nom,salaire);
end if;
exit when salaire >= 5000;
end loop;
…
End;
Fermeture : close
• Syntaxe: Close nom_curseur;
• Action: libère la place de mémoire
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
Open dept_10;
Loop
Fetch dept_10 into nom, salaire;
If salaire > 2500 then
insert into résultat values (nom,salaire);
end if;
exit when salaire >= 5000;
end loop;
close dept_10;
End;
Exemple : close
Declare
Cursor c1 is select first_name, salary from employees order by
sal desc;
v_ename employees. first_name %TYPE;
v_sal employees.salary%TYPE;
Begin
open c1;
loop
fetch c1 into v_ename, v_sal;
insert into resultat values (v_sal, v_ename);
end loop;
close c1
End;
Les attributs d’un curseur
%NOTFOUND: nom_curseur%NOTFOUND
TRUE: le dénier FETCH n’a pas ramené de ligne
%ISOPEN: nom_curseur%ISOPEN
TRUE: le curseur est ouvert
%ROWCOUNT: nom_curseur%rowcount
Nbre de lignes ramenées par le Fetch
Utilisation des attribut du curseur
Pour manipuler les attribut d’un curseur implicite on utilise
SQL%Attribut
Exemples :
SQL%FOUND ,
SQL% ROWCOUNT
nom_curseur%Attribut
Exemples :
nom_curseur%FOUND ,
nom_curseur % ROWCOUNT)
Utilisation des attribut du curseur
Curseur Implicite : utilisation de l’attribut par SQL%Attribut
DECLARE
e_DeptNumber employees.Department_id%TYPE :=9;
BEGIN
DELETE FROM temp_Employee9
WHERE Department_id <> e_DeptNumber;
IF SQL%FOUND THEN – Il y a des enregistrement
supprimmée
DBMS_OUTPUT.PUT_LINE('Nombre des enregistrement
supprimés: ‘ || TO_CHAR(SQL%ROWCOUNT));
ELSE
DBMS_OUTPUT.PUT_LINE('AUCUN enregistrement
n''supprimés ');
END IF;
END;
Exemple - %FOUND
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
Open dept_10;
Fetch dept_10 into nom, salaire;
While dept_10%FOUND Loop
If salaire > 2500 then insert into résultat values (nom,salaire);
end if;
Fetch dept_10 into nom, salaire;
end loop;
close dept_10;
End;
Exemple - %NOTFOUND
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
Open dept_10;
Loop
Fetch dept_10 into nom, salaire;
Exit when dept_10%NOTFOUND;
If salaire > 2500 then
bdms_output.put_line( nom ||’ ,’ ||salaire);
end if;
end loop;
close dept_10;
End;
Exemple - %ISOPEN
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
If not(dept_10%ISOPEN) then
Open dept_10;
end if;
Loop
Fetch dept_10 into nom, salaire;
Exit when dept_10%NOTFOUND;
If salaire > 2500 then
insert into résultat values (nom,salaire);
end if;
end loop;
close dept_10;
End;
Exemple - %ROWCOUNT
Declare
cursor dept_10 is select first_name , salary From employees
where department_id= 10 order by salary;
nom employees .first_name%TYPE;
salaire employees . salary%TYPE;
Begin
Open dept_10;
Loop
Fetch dept_10 into nom, salaire;
Exit when dept_10%NOTFOUND or dept_10%ROWCOUNT > 15;
If salaire > 2500
then insert into résultat values (nom,salaire);
end if;
end loop;
close dept_10;
End;
Boucle LOOP Exit when pour un curseur
END LOOP;
CLOSE c;
end;
Boucle WHILE pour un curseur
declare
cursor c is select department_id, Utiliser WHILE élimine le
first_name from employees besoin de l’instruction EXIT
where department_id = 10; WHEN en intégrant l'utilisation
Name employees.first_name%type; de l'attribut % FOUND.
Dept employees.department_id%type;
Begin 2 instructions FETCH (Une
Open c; juste avant le while et l’autre
FETCH c into dept, name ; avant le END LOOP)
while c%FOUND loop
dbms_output.put_line(name);
FETCH c into dept, name ;
End loop;
CLOSE c;
end;
Boucle FOR pour un curseur
Elle simplifie la programmation car elle évite d’utiliser explicitement
les instruction open, fetch, close, exit
En plus elle déclare implicitement une variable de type « row »
associée au curseur
declare
cursor c is
select department_id, first_name from employees
where department_id = 10;
begin
FOR emp IN c LOOP
dbms_output.put_line(emp.first_name);
END LOOP;
end;
Mise à jour d’une table -La clause WHERE CURRENT OF
DECLARE
DECLARE
CURSOR moncurseur IS SELECT Employee_ID , salary CURSOR moncurseur IS SELECT
FROM employees FOR UPDATE; Employee_ID FROM employees FOR
e_Record moncurseur%ROWTYPE; UPDATE;
BEGIN BEGIN
OPEN moncurseur;
FOR c_tmp IN moncurseur LOOP
LOOP
IF c_tmp.Employee_ID = ‘102' THEN
FETCH moncurseur INTO e_Record;
EXIT WHEN moncurseur %NOTFOUND; UPDATE employees SET
IF e_Record.salary > 40000 THEN salary= salary + 350
DELETE FROM Employees WHERE CURRENT OF moncurseur;
WHERE CURRENT OF moncurseur; END IF;
END IF;
END LOOP;
END LOOP;
COMMIT;
CLOSE moncurseur;
END; END;
/
Curseur avec des paramètres
A votre avis, le code suivant est-il valide ?
declare
n NUMBER := 14;
CURSOR C IS SELECT * FROM EMPLOYEES WHERE employee_id>= n ;
ROW C%rowType ;
BEGIN
FOR CUR IN C LOOP
DBMS_OUTPUT.PUT_LINE ( CUR.FIRST_NAME) ;
END LOOP ;
END ;
/
Non. La requête d’un curseur ne peut pas contenir de variables dont les
valeurs ne sont pas fixées.
Pourquoi ? Parce que les valeurs des ces sont susceptibles de changer entre
la déclaration du curseur et son ouverture.
Le remède est un curseur paramétré.
Curseur avec des paramètres
Ouverture
On ouvre un curseur paramétré en passant en paramètre
les valeurs des variables :
OPEN Nom_curseur ( liste de sparamètres )
Exemple Recapitulatif
Declare
CURSOR mycursor (param1 number, param2 number) is select Employee_ID ,
salary
from employees where employee_id between param1 and param2;
e_Record mycursor%rowtype;
BEGIN
OPEN mycursor('102','110');
FETCH mycursor INTO e_Record;
loop
DBMS_OUTPUT.PUT_LINE('Salare de ' || e_Record.Employee_ID || ': ' ||
e_Record.Salary ||' $');
FETCH mycursor INTO e_Record;
exit when mycursor%notfound;
end loop;
CLOSE mycursor;
/
Exercices :
Objectifs:
et fonctions
Vous pouvez appeler ces procédures par les autres blocs de code,
ou directement à partir de SQL * Plus (ou par un autre programme
client).
Avant de créer des procédure il vous faut avoir les droits
nécessaire
Appel de la procédure
CREATE OR REPLACE
PROCEDURE nom_procedure ( paramètres IN , OUT ) IS
BEGIN
Corps_de_la_procedure
END;
CREATE OR REPLACE
PROCEDURE HELLOWORLD IS
BEGIN
DBMS_OUTPUT.PUT_LINE(’Hello World!’);
END;
CREATE OR REPLACE
PROCEDURE DISPN (N INT) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(‘N est : ‘ || N);
END;
SQL>call DISPN(555)
N est : 555
Procédures stockées
Plusieurs paramètres: Exemple
CREATE OR REPLACE
PROCEDURE DISP_AB (A INT, B INT) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(’A + B = ’ || (A + B));
DBMS_OUTPUT.PUT_LINE(’A * B = ’ || (A * B));
END;
CREATE OR REPLACE
PROCEDURE DISP_NAME (NAME VARCHAR) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(’Hi ’ || NAME || ’!’);
END;
IN OUT: pour des paramètre qui sont à la fois des IN et des
OUT
Procédures stockées
Options : IN, OUT, IN OUT: exemple
CREATE OR REPLACE
PROCEDURE SUM_AB (A INT, B INT, C OUT INT) IS
BEGIN
C := A + B;
END;
Faites appel à la procédure dans un bloc PL/SQL !
DECLARE
R INT;
BEGIN
SUM_AB(23,29,R);
DBMS_OUTPUT.PUT_LINE(’SUM IS: ’ || R);
END;
Procédures stockées
Exemple avec : IN OUT
CREATE OR REPLACE
PROCEDURE DOUBLEN (N IN OUT INT) IS
BEGIN
N := N * 2;
END;
Une fonction est un bloc PL/SQL nommé qui peut accepter des
paramètres et être appelé.
En règle générale, vous utilisez une fonction pour calculer une
valeur
Remarque:
- La section de traitement des exceptions peut également
contenir une instruction RETURN.
Fonctions stockées
SQL> Declare
A employees.employee_id%type;
S number
BEGIN
A := &Numero_de_employe; --lire à partir du clavier
S :=get_sal (A);
dbms_output.put__line(S );
END ;
/
Fonctions stockées
Appel d'une procédure ou fonction (suite)
Exemple 2
-Créer une fonction TAX qui sera appelée à partir d'une instruction SELECT.
- La fonction accepte un paramètre NUMBER et renvoie la taxe après avoir
multiplié la valeur du paramètre par 0,08.
Create or replace function tax( p_value in number) Return number is
Begin
Return (p_value * 0.08);
End tax;
/
CREATE OR REPLACE
Que signifie CREATE OR REPLACE ?
Declare
Variables
Begin
…..
Declare
Variables
Begin
….
End;
…..
End;
Les sous-blocs
Exemple
Declare
a number; b varchar2(30); c number;
Begin
a:=10; b:='Imagination'; c:= 20;
Declare
a number; b varchar2(30); d number;
Begin
d:=c+5;
a:=40 ;b:='programmation';
End;
b:=b||' Esprit'; a:=a+d;
dbms_output..put__line(a||'' ''||b||'' ''||c));
End;
PACKAGES DANS PL/SQL
Procédures, fonctions
Curseurs, variables, des constantes
tableaux
Exceptions
Applications Package
Variables globales et publique Base données
Spec
BODY
La modularité,
Meilleure performance.
Avantages de Package
La modularité:
Les Package vous permettent d'encapsuler des types logiquement liés,
des éléments et des sous-programmes dans un module PL / SQL
nommée. Chaque package est facile à comprendre, et les interfaces
entre les packages sont simples, clairs et bien définis. Ceci facilite le
développement d'applications.
Avantages de Package
La conception plus facile d'application:
Lors de la conception d'une application, Vous n’avez besoin
initialement que de l'information sur d'interface des spécifications
du package . Vous pouvez coder et compiler une spécification sans
son corps (body). Puis, les sous-programmes référençant le
package peuvent être compilées ainsi au fur et à mesure . Vous
n’êtes pas obligés de définir immediatement tout les organes du
package même s’il sont déclarer dans la partie spécification
Avantages de Package
Encapsulation des données et méthodes
Avec les packages, vous pouvez spécifier quels sont les types, les
éléments et les sous-programmes publiques (visibles et accessibles)
ou ceux privés (cachés et inaccessibles).
Par exemple, si un package contient 4 sous-programmes, 3 public et
1 privé. Le package cache la mise en œuvre du sous-programme
privé de sorte que seul le package (et non toute l’ application) est
affecté en cas de changement de sa mise en œuvre. Cela simplifie la
maintenance et l'amélioration.
- Ils permettent le over loading : déclaration du plusieurs fonctions
et procédure avec le même nom et paramètres différents
Avantages de Package
Meilleure performance.
Lorsque vous appelez un sous-programme de package pour la
première fois, l'ensemble du package est chargé en mémoire(SGA).
Ainsi, les appels plus tard des autre sous-programmes de package
ne nécessitent aucune E/S disque.
En outre, les package stoppent les dépendances en cascade en
évitant toute recompilation inutile. Par exemple, si vous changez la
mise en œuvre d'une fonction du package , Oracle n'a pas besoin de
recompiler touts les autres sous-programmes même ceux qui lui
font appel, car ils sont indépendant de corps(body) du package .
Les Déclencheurs (Triggers) DANS PL/SQL
Type de Triggers
….
….
BEFORE (avant) le trigger ligne
Événement de trigger :
Corps de triggers :
trigger SECURE_EMP
Rapport d'erreur -
Erreur SQL : ORA-20500: Vous ne pouvez inserer dans la table
employes que durant les heures de travail
ORA-06512: at "HR.SECURE_EMP", line 4
ORA-04088: error during execution of trigger 'HR.SECURE_EMP'
Les Déclencheurs (Triggers) DANS PL/SQL
Utilisation de prédicats conditionnels
CREATE OR REPLACE TRIGGER secure_emp BEFORE
INSERT OR UPDATE OR DELETE ON employees
BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAM.','DIM.')) OR (TO_CHAR(SYSDATE,'HH24') NOT BETWEEN '08'
AND '18') THEN
IF DELETING THEN RAISE_APPLICATION_ERROR(-20502, 'Vous ne pouvezSupprimer dans la table
employes que
durant les heures de travail');
Faisons un test ensemble!: insert into commandes values ( 111 , 555 , 100);
Question : Que ce que va se passer si le client a changé la quantité commandée
d’un produit ?
Les Déclencheurs (Triggers) DANS PL/SQL
Trigger ligne avec OLD et New (2/4)
Réponse : on tombe dans une incohérence,
il faut donc créer un trigger de mise à jour ( UPDATE) ?
Réponse:
Application
INSERT INTO ma_view . . .;
INSERT
Trigger de type TABLE1
INSTEAD OF
UPDATE
TABLE2
MA_VIEW
Les Déclencheurs (Triggers) DANS PL/SQL
Exemple de Le Trigger INSTEAD OF
create view nom_emp as select employee_id,last_name,job_id
from employees;
Triggers Procedures/Fonctions
Définit par CREATE TRIGGER Defined with CREATE PROCEDURE
Le dictionnaire de données contient Le dictionnaire de données contient le
le code source dans USER_TRIGGERS. code source dans USER_SOURCE.
Implicitement invoqué explicitement invoqué
Les COMMIT, SAVEPOINT, et COMMIT, SAVEPOINT, et ROLLBACK sont
ROLLBACK ne sont pas autorisés. autorisés
Les Déclencheurs (Triggers) DANS PL/SQL
NB: Tout les triggers d’une table sont supprimés une fois table est
supprimée.