1. Le langage PL-SQL
Contenu du cours
• Objectifs du PL/SQL
• Variables, structures de contrôle
• Curseurs, interaction avec la base
• Sous-programmes, paquetages
• Exceptions
• Déclencheurs (triggers)
PL /SQL est un langage procédural propriétaire d’Oracle qui intègre des ordres SQL. Il permet l’utilisation des
blocs SQL et d’exprimer des règles de gestion complexes sous forme de procédures stockées et de triggers.
Structure d’un bloc PL/SQL
Programme PL/SQL = bloc (procédure anonyme, procédure nommée, fonction nommée) :
PL/SQL n’interprète pas une commande, mais un ensemble de commandes contenues dans un bloc PL/SQL. Ce
bloc peut comporter plusieurs sous blocs.
DECLARE
-- section de déclarations
-- section optionnelle …
BEGIN
-- traitement, avec d’éventuelles directives SQL
-- section obligatoire …
EXCEPTION
-- gestion des erreurs
-- section optionnelle …
END;
Blocs imbriqués :
-- BLOC A
DECLARE
BEGIN
-- BLOC B
DECLARE
BEGIN
-- BLOC C
DECLARE
BEGIN
-- BLOC D
DECLARE
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
2. BEGIN
-- BLOC E
DECLARE
BEGIN
EXCEPTION
END;
EXCEPTION
END;
EXCEPTION
END;
EXCEPTION
END;
EXCEPTION
END;
Portée d’un identificateur :
Le bloc E peut accéder aux identificateurs déclarés dans les blocs D, C, B et A. L’inverse n’est pas vrai.
Identificateurs, commentaires
Un identificateur (variable, curseur, exception, etc.) :
- Commence par une lettre
- Peut contenir : lettres, chiffres, $, #, _
- Interdits : &, -, /, espace
- Jusqu’à 30 caractères
- Insensible à la casse !
On peut documenter un code PL/SQL. Les différentes façons d’introduire des commentaires :
- -- Commentaire sur une seule ligne
- /* Commentaire sur plusieurs
lignes */
Les variables PL/SQL
PL/SQL permet de déclarer et de manipuler des variables.
Types de variables PL/SQL :
Scalaires : par exemple NUMBER (5,2), VARCHAR2, DATE, BOOLEAN, CHAR…
Composites : %ROWTYPE, RECORD, TABLE
Toute variable PL/SQL doit obligatoirement être déclarée avant utilisation. Cette déclaration s’effectue dans la
zone DECLRAE.
Exemple :
vNumero NUMBER(5) ;
vNom VARCHAR2(12) ;
vDateNaissance DATE ;
vPoids NUMBER(5,2) ;
vSexe CHAR(1) ;
Déclaration %TYPE
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
3. PL/SQL permet de déclarer des variables faisant références à la colonne d’une table, il permet de récupérer
automatiquement le type de la donnée tel qu’il est défini dans le dictionnaire de la base. Cette propagation du
type permet de réduire le nombre de changements à apporter au code PL/SQL en cas de modification des types
de certaines colonnes.
Exemple :
Soit la table SALARIES suivante :
SALARIES
salnumero
salnom
salprenom
saladresse
salsalaire
salcomm
create table salaries (
salnumero number not null,
salnom varchar (15),
salprenom varchar (15),
saladresse varchar (40),
salsalaire number (7, 2),
salcomm number (7, 2),
constraint pk_salaries primary key (salnumero)
);
DECLARE
vNomClient salaries.salnom%TYPE;
vSalClient salaries.salsalaire%TYPE;
BEGIN
SELECT salnom, salsalaire
INTO vNomClient, vSalClient
FROM salaries
WHERE salnumero = 1000;
END;
Déclaration %ROWTYPE
PL/SQL permet de déclarer une variable composite de même type que les tuples d’une table.
vEnreg salaries%ROWTYPE;
Les composantes de la variable composite, identifiées par vEnreg.nomColonne, sont du même type que les
colonnes correspondantes de la table.
Exemple :
DECLARE
vEenregSalaries salaries%ROWTYPE;
BEGIN
vEenregSalaries.salnumero = 1200;
vEenregSalaries.salnom = 'VAUDAN';
vEenregSalaries.salprenom = 'STEPHANE';
vEenregSalaries.saladresse = '37, RUE PIERRE AVIA PARIS';
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
4. vEenregSalaries.salcomm = 120;
INSERT INTO salaries vEenregSalaries ;
END;
Affectation des valeurs aux variables PL/SQL
On peut affecter des valeurs aux variables PL/SQL soit :
- En utilisant l’opérateur d’assignation :=
vAge := SYSDATE – vDateNaissance ;
vNomSalarie := UPPER ('Nom') ;
- A partir d’un ordre SELECT
…
SELECT salnom, saladresse
INTO vNom, vAdresse
FROM salaries
WHERE salnumero = 1200 ;
…
Remarque:
L’ordre SELECT doit retourner une seule ligne, dans le cas contraire une erreur est générée.
Structures de contrôle
Traitement conditionnelle
Syntaxe:
IF condition_1 THEN
Instructions_1;
ELSIF condition_2
Instructions_2;
ELSE
Instructions_3;
END IF;
Les opérateurs relationnels sont: =, <, >, !=, >=, <=, IS NULL, IS NOT NULL, BETWEEN, LIKE, AND, OR
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
5. Exemple :
DECLARE
vSalaire salsalaire.salaries%TYPE;
BEGIN
SELECT salsalaire
INTO vSalaire
FROM salaries
WHERE salnumero = 1200;
IF vSalaire < 1000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.1
WHERE salnumero = 1200;
ELSIF vSalaire BETWEEN 1000 AND 3000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.05
WHERE salnumero = 1200;
ELSE
UPDATE salaries
SET salcomm = salcomm + 100
WHERE salnumero = 1200;
END IF;
END;
Structures répétitives : la boucle de base
PL/SQL permet d’effectuer des traitements répétitifs grâce à la clause LOOP.
BEGIN
…
LOOP
Instructions
END LOOP;
…
END;
Remarque :
La boucle ci-dessus s’exécute indéfiniment, l’instruction EXIT permet de stopper l’exécution de la boucle
LOOP.
BEGIN BEGIN
… …
LOOP LOOP
Instructions Instructions
EXIT WHEN condition; IF condition THEN
END LOOP; EXIT;
… END IF;
END; END LOOP;
…
END;
Structures répétitives : la boucle FOR
Syntaxe :
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
6. FOR compteur IN val_1..val_2
LOOP
instructions;
END LOOP;
Structures répétitives : la boucle WHILE
WHILE condition
LOOP
instructions;
END LOOP;
La condition est vérifiée au début de chaque itération ; tant que la condition est vérifiée, les instructions sont
exécutées.
Les curseurs
Un curseur est une zone mémoire de taille fixe capable de stocker plusieurs enregistrements et de gérer l’accès à
ces enregistrements.
Types de curseurs :
- Curseurs implicites :
Déclarés implicitement et manipulés par SQL pour toute requête SQL et pour les interrogations qui
retournent un seul enregistrement
- Curseurs explicites :
Déclarés et manipulés par l’utilisateur pour les interrogations qui retournent plus d’un enregistrement
Etapes d’utilisation d’un curseur :
- Déclaration
- Ouverture
- Traitement des lignes
- Fermeture
Déclaration d’un curseur
Syntaxe :
CURSOR nom_curseur IS requête ;
Cette déclaration se fait dans la section DECLARE.
Exemple :
DECLARE
CURSOR c_salaries IS
SELECT salnumero, salnom, salsalaire
FROM salaries;
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
7. BEGIN
…
END;
L’ensemble de lignes renvoyées par une interrogation multi lignes s’appelle un result set (jeu de résultats).
ResultSet
Curseur 1100 VAUDAN 20000
1200 HOMEYER 30000
1300 BUELLET 40000
Ouverture d’un curseur
Elle permet :
- L’allocation mémoire du curseur,
- L’analyse syntaxique et sémantique de la requête,
- Elle se fait dans la section BEGIN.
Syntaxe :
OPEN c_salaries ;
Exemple :
DECLARE
CURSOR c_salaries IS
SELECT salnumero, salnom, salsalaire
FROM salaries;
BEGIN
OPEN c_salaries;
…
END;
Traitement des lignes
Les lignes retournées par l’ordre SELECT sont traitées une par une. La valeur de chaque colonne doit être
stockée dans une variable réceptrice.
Syntaxe :
FETCH c_salaries INTO variables_receptrices ;
La clause FETCH ne récupère qu’un seul enregistrement. Pour accéder à l’ensemble des lignes de l’ordre
SELECT, il faut prévoir une boucle.
Le traitement des lignes se fait dans le corps du bloc PL/SQL.
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
8. Exemple :
DECLARE
vNumero salnumero.salaries%TYPE;
vSalaire salsalaire.salaries%TYPE;
-- Déclaration du curseur
CURSOR c_salaries IS
SELECT salnumero, salsalaire
FROM salaries
ORDER BY salsalaire;
BEGIN
OPEN c_salaries;
LOOP
FETCH c_salaries
INTO vNumero, vSalaire;
IF vSalaire < 1000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.1
WHERE salnumero = vNumero;
ELSIF vSalaire BETWEEN 1000 AND 3000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.05
WHERE salnumero = vNumero;
END IF;
EXIT WHEN vSalaire > 3000
END LOOP;
END;
Fermeture d’un curseur
Syntaxe :
CLOSE c_salaries;
Libération de la place mémoire allouée.
Attributs d’un curseur:
Les attributs permettent de connaître l’état d’un curseur.
%FOUND et %NOTFOUND déterminent si toutes les lignes retournées par le curseur ont étés traitées.
%ISOPEN précise si le curseur est ouvert.
%ROWCOUNT indique le nombre de lignes déjà traitées.
Curseurs explicites paramétrés
Objectif : paramétrer la requête associée à un curseur pour éviter de multiplier les curseurs similaires dans le
même bloc PL/SQL.
Syntaxe :
CURSOR nom_curseur (param1 type1, param2 type2, …]) IS …;
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
9. Les valeurs des paramètres sont transmises à l’ouverture du curseur :
OPEN nom_curseur (valeurPar1, valeurPar2, …);
Il faut évidemment fermer le curseur avant de l’appeler avec d’autres valeurs pour les paramètres.
Simplification d’écriture des curseurs
Exemple :
DECLARE
CURSOR c_salaries IS
SELECT salnumero, salsalaire
FROM salaries
ORDER BY salsalaire;
--Déclaration d’une structure
enreg_salaries c_salaries%ROWTYPE;
BEGIN
OPEN c_salaries;
LOOP
FETCH c_salaries INTO enreg_salaries;
IF enreg_salaries.salsalaire < 1000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.1
WHERE salnumero = enreg_salaries.salnumero;
ELSIF enreg_salaries.salsalaire BETWEEN 1000 AND 3000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.05
WHERE salnumero = enreg_salaries.salnumero;
END IF;
EXIT WHEN c_salaries%NOTFOUND ;
END LOOP;
CLOSE c_salaries;
END;
Simplification d’écriture des curseurs : utilisation de la boucle FOR..IN
DECLARE
BEGIN
FOR enreg_salaries IN ( SELECT salnumero, salsalaire
FROM salaries
ORDER BY salsalaire
)
LOOP
IF enreg_salaries.salsalaire < 1000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.1
WHERE salnumero = enreg_salaries.salnumero;
ELSIF enreg_salaries.salsalaire BETWEEN 1000 AND 3000 THEN
UPDATE salaries
SET salsalaire = salsalaire*1.05
WHERE salnumero = enreg_salaries.salnumero;
END IF;
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
10. END LOOP;
END;
Procédures et fonctions
Ce sont les sous programmes hébergés par la base de données : ils peuvent être appelés à partir d’une autre
procédure, fonction ou encore depuis un programme exécutable extérieur à la base de données.
Un sous programme est un bloc PL/SQL nommé qui peut accepter des paramètres et être appelé.
Procédures
Syntaxe :
PROCEDURE laProcedure (param1 IN | OUT | IN type 1, param2…) IS
BEGIN
…
EXCEPTION
END;
Une procédure se termine à la fin du bloc ou par une instruction RETURN.
Fonctions
Syntaxe :
FUNCTION laFonction (param1 IN | OUT | IN type 1, param2…)RETURN type_variable IS
BEGIN
…
EXCEPTION
END;
Une fonction se termine par l’instruction RETURN qui doit renvoyer un résultat.
Remarque :
Comme tout objet SQL, une procédure ou une fonction peut être créée, modifiée ou supprimée.
Création
CREATE PROCEDURE…
CREATE FUNCTION…
Modification
CREATE OR REPLACE PROCEDURE…
CREATE OR REPLACE FUNCTION…
Suppression
DROP PROCEDURE…
DROP FUNCTION…
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
11. Exécution et utilisation de procédures et de fonctions
SQL> CREATE OR REPLACE FUNCTION leDouble (p_telNombre IN NUMBER)
RETURN NUMBER IS
le_double NUMBER;
BEGIN
le_double := p_telNombre*2;
RETURN le_double;
END ;
/
SQL> DECLARE
v_leNombre NUMBER := 12;
v_ledouble NUMBER;
BEGIN
le_double := leDouble(v_telNombre);
END ;
/
Remarques :
- Pour repérer les erreurs, on dispose de la commande SHOW ERRORS.
- Pour afficher les variables contenues dans un bloc PL/SQL, il faut inclure le package (définit plus loin)
standard dbms_output.put_line.
Paquetages
Un paquetage PL/SQL permet de regrouper un ensemble de procédures, de fonctions, de variables et de curseurs
au sein d’un ensemble cohérent de services.
- Distinction entre ce qui est accessible depuis l’extérieur et ce qui n’est accessible qu’à l’intérieur du
paquetage : encapsulation
- Structure :
o Section de spécification : déclarations des variables, curseurs, sous-programmes accessibles depuis
l’extérieur,
o Section d’implémentation : code des sous-programmes accessibles depuis l’extérieur + sous-
programmes accessibles en interne (privés)
Il y a des packages prédéfinis :
Parmi eux, le package DBMS_OUTPUT : affichage pour la mise au point des programmes PL/SQL. Il est
utilisé pour envoyer des messages contrôlant l’exécution d’un programme PL/SQL ou en encore lors du
débogage.
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
12. Exceptions
PL/SQL permet de définir dans une zone particulière (de gestion d’exception), l’attitude que le programme doit
avoir lorsque certaines erreurs définies ou prédéfinies se produisent.
Un certain nombre d’exceptions sont prédéfinies sous Oracle. Citons, pour les plus fréquentes :
NO_DATA_FOUND (devient vrai dès qu’une requête renvoie un résultat vide), TOO_MANY_ROWS
(requête renvoie plus de lignes qu’escompté), CURSOR_ALREADY_OPEN (curseur déjà ouvert),
INVALID_CURSOR (curseur invalide)...
L’utilisateur peut définir ses propres exceptions. Dans ce cas, il doit définir celles ci dans la zone de déclaration.
Exemple :
v_exception EXCEPTION ;
Puis, cette exception est levée quelque part dans le programme (après un test non concluant, par exemple), par
l’instruction :
RAISE v_exception ;
Enfin, dans la zone d’exception un traitement est affecté à chaque exception possible (définie ou prédéfinie) :
EXCEPTION
WHEN <exception1> [OR <exception2> OR ...] THEN <instructions>
WHEN <exception3> [OR <exception2> OR ...] THEN <instructions>
WHEN OTHERS THEN <instructions>
END;
Evidemment, un seul traitement d’exception peut se produire avant la sortie du bloc.
Les exceptions internes
Une erreur interne est produite quand un bloc PL/SQL viole une règle d'Oracle ou dépasse une limite dépendant
du système d'exploitation.
Les erreurs Oracle générées par le noyau sont numérotées, or le gestionnaire des exceptions de PL/SQL, ne sait
que gérer des erreurs nommées.
Pour cela PL/SQL a redéfini quelques erreurs Oracle comme des exceptions. Ainsi, pour gérer d'autres erreurs
Oracle, l'utilisateur doit utiliser le gestionnaire OTHERS ou EXCEPTION_INIT pour nommer ces erreurs.
Les exceptions fournies par Oracle sont regroupées dans ce tableau :
Nom d'exception Valeur Sql Code Erreur Oracle
CURSOR_ALREADY_OPEN -6511 ORA-06511
DUP_VAL_ON_INDEX -1 ORA-00001
INVALID_CURSOR -1001 ORA-01001
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
13. INVALID_NUMBER -1722 ORA-01722
LOGIN_DENIED -1017 ORA-01717
NO_DATA_FOUND -1403 ORA-01413
NOT_LOGGED_ON -1012 ORA-01012
PROGRAM_ERROR -6501 ORA-06501
STORAGE_ERROR -6500 ORA-06500
TIMEOUT_ON_RESOURCE -51 ORA-00051
TOO_MANY_ROWS -1422 ORA-01422
TRANSACTION_BACKED_OUT -61 ORA-00061
VALUE_ERROR -6502 ORA-06502
ZERO_DIVIDE -1476 ORA-01476
OTHERS : toutes les autres erreurs non explicitement nommées.
Pour gérer les exceptions, le développeur doit écrire un gestionnaire des exceptions qui prend le contrôle du
déroulement du bloc PL/SQL en présence d'une exception.
Le gestionnaire d'exception fait partie du bloc PL/SQL et se trouve après les commandes.
Il commence par le mot clé EXCEPTION et se termine avec le même END du bloc.
Chaque gestion d'exception consiste à spécifier son nom d'erreur après la clause WHEN et la séquence de la
commande à exécuter après le mot clé THEN, comme le montre l'exemple suivant :
Les déclencheurs (“triggers”)
Les déclencheurs ou ”triggers” sont des séquences d’actions définis par le programmeur qui se déclenchent, sur
des actions modifiant les données de la table sur laquelle porte le trigger.
Un trigger sera un objet stocké (comme une table ou une procédure).
Syntaxe :
CREATE [OR REPLACE] TRIGGER <nomTrg>
{BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON <nomTable>
[FOR EACH ROW [WHEN (<condition>)]]
<corps du trigger>
Le type d’action qui déclenche le trigger détermine son moment d’exécution : il est précisé au début de l’écriture
du code de trigger.
(INSERT|DELETE|UPDATE)
Le trigger peut être déclenché avant ou après cette action (BEFORE|AFTER)
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI
14. L’option FOR EACH ROW [WHEN (<condition>)] fait exécuter le trigger à chaque modification d’une ligne
de la table spécifiée (on dit que le trigger est de ”niveau ligne”). En l’absence de cette option, le trigger est
exécuté une seule fois (”niveau table”).
Caractéristiques
• Un déclencheur a un nom.
• Il est associé à une table et une seule.
• Il peut être actif ou inactif.
• Il est opérationnel jusqu’à sa suppression ou la suppression de la table à laquelle il est associé.
Référence aux colonnes d’une table
• Dans le code associé aux déclencheurs de niveau ligne, on peut accéder aux valeurs des attributs de la
ligne modifiée par les variables :
:old et :new
• Pour un déclencheur sur INSERT, les nouvelles valeurs sont dans :new.<nom attribut>
• Pour un déclencheur sur UPDATE, les anciennes valeurs sont dans :old.<nom d’attribut>. Les
nouvelles valeurs sont dans :new.<nom d’attribut>
• Pour un déclencheur sur DELETE, les anciennes valeurs sont dans :old.<nom d’attribut>
Remarques
• N’utilisez pas les triggers pour effectuer des contrôles d’intégrité.
• Pour éviter de supprimer et recréer un trigger : create or replace trigger
• Pour un trigger relatif à plusieurs événements, utiliser les prédicats inserting, updating, deleting
if inserting then …end if;
if updating then …end if;
if deleting then …end if;
Activer/désactiver
Un trigger est crée par la clause CREATE TRIGGER ou CREATE OR REPLACE TRIGGER. Un
trigger existant peut être détruit par DROP TRIGGER.
ALTER TRIGGER nomTrigger ENABLE; -- active le trigger
ALTER TRIGGER nomTrigger DISABLE; -- désactive le trigger
ALTER TABLE nomTable ENABLE ALL TRIGGERS;
ALTER TABLE nomTable DISABLE ALL TRIGGERS;
MISR-MSRS : M1 Support du cours PL/SQL L. KOUTTI