Langage PL/SQL - WordPress.com

Transcription

Langage PL/SQL - WordPress.com
ISAMM
Cours SGBD & L4G
Oracle PL/SQL
1. INTRODUCTION
•
Les traitements complexes sont parfois très difficile à écrire si on ne peut utiliser des variables et les structures de programmation
comme les boucles et les alternatives. 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
•
PL/SQL : Langage procédural de 4ème génération (L4G). Il s’agit d’une extension du langage SQL avec des caractéristiques propres
aux langages de programmation
¾ Déclaration de variables et de constants
¾ Types de données abstraits (collections, enregistrements, objets)
¾ Modularité (sous-programmes, packages)
¾ Gestion des erreurs à l'exécution (exceptions)
¾ Interaction étroite avec Oracle (avec SQL)
Avantages de PL/SQL
•
Performance (traitements par lot)
•
Productivité (uniformité dans tous les outils)
•
Portabilité (sur tous systèmes Oracle)
•
Intégration étroite avec Oracle (mêmes types de données que SQL, par exemple)
Structure d'un bloc PL/SQL
[DECLARE
-- Déclaration types, constantes et variables]
BEGIN
-- Instructions PL/SQL & Commandes SQL
[EXCEPTION
-- Traitement des erreurs]
END;
Types de blocs PL/SQL
•
Bloc Anonyme
• Stocké en-dehors de la base de données
• Compilé et exécuté à la volée
•
Procédure Stockée :
• Compilée séparément
• Stockée de façon permanente dans la BD
•
Déclencheur (Trigger)
• Procédure stockée associée à une table
• Exécution automatique sur événement
2. DECLARATIONS
Variables et constantes
•
Déclaration dans la partie déclarative d’un bloc PL/SQL
•
Variables
date_naissance DATE;
compteur1 INTEGER:=0;
compteur2 INTEGER DEFAULT 0;
id VARCHAR2(5) NOT NULL := ‘AP001’;
•
Constantes
pi CONSTANT REAL := 3.141592653;
Référencement de type existant
•
Type d’une autre variable
Credit REAL;
Debit Credit%TYPE;
•
Type d'un attribut d'une table
•
Type d’un tuple d’une table
num_emp Emp.empno%TYPE;
un_client Client%ROWTYPE;
3. OPERATEURS
Affectation
•
Affectation simple
Numero := 0;
Numero := numero + 1;
•
Valeurs issues d'une base de données si la requête ramène un et un seul enregistrement
SELECT numcli INTO numero FROM Client WHERE numcli = 10;
SELECT empno, ename INTO num, nom FROM Emp WHERE ename = 'KING';
-1-
ISAMM
Cours SGBD & L4G
Expressions et comparaisons
•
Opérateurs arithmétiques :
+
-
/
*
**
•
Opérateur de concaténation :
•
Opérateurs de comparaison :
•
Opérateurs logiques :
||
=
<
>
<=
>=
<>
!=
IS NULL
LIKE
BETWEEN
IN
AND, OR, NOT
Conversion de type de données
•
Fonctions de conversion : TO_CHAR, TO_DATE, TO_NUMBER
v_date1 := to_date('01/01/1999’, ‘dd/mm/yyyy’);
v_date2 := to_date(’01 janvier 1999’, ‘dd month yyyy’);
v_date3 := to_date(’01-jan-1999’, ‘dd-mon-yyyy’);
v_str_date_systeme := to_char(sysdate, ‘dd/mm/yyyy');
v_str_heure_systeme := to_char(sysdate, ‘hh24:mi:ss');
v_str_date_systeme_complete := to_char(sysdate, ‘dd/mm/yyyy hh24:mi:ss');
v_num_str := to_char(130);
v_num := to_number('140');
4. STRUCTURES DE CONTROLE
Traitements conditionnels :
•
IF - THEN, IF - THEN - ELSE ou IF - THEN - ELSIF
IF condition1 THEN
-- Instructions
[ELSIF condition2 THEN
-- Instructions]
[ELSE
-- Instructions]
END IF;
Traitements itératifs
•
Boucle pour
FOR compteur IN [REVERSE] borne_inf..borne_sup LOOP
-- Instructions
END LOOP;
NB: borne_inf doit être inférieure à borne_sup
•
Boucle tant que
WHILE condition LOOP
-- Instructions
END LOOP;
•
Boucle "infinie"
LOOP
-- Instructions
END LOOP;
•
Sortie de boucle, uniquement autorisé pour sortir d'une boucle infinie
EXIT WHEN condition;
5. AFFICHAGE
•
DBMS_OUTPUT.PUT_LINE('chaîne');
DBMS_OUTPUT.PUT_LINE('Bonjour');
DBMS_OUTPUT.PUT_LINE('nom='||nom);
NB: Pour que l'affichage fonctionne, la variable d'environnement SERVEROUTPUT de SQL*Plus doit être à ON.
SET SERVEROUTPUT ON
•
Exemple
--Affichage en dinars tunisien du salaire de SCOTT qui stocké en euros
--Salire en dinars tunisien = salaire en euros * 1.621
SET SERVEROUTPUT ON
DECLARE
Euro CONSTANT REAL := 1.621;
Salaire emp.sal%TYPE;
BEGIN
--Affectation
SELECT sal INTO Salaire FROM emp WHERE ename = 'SCOTT';
--Conversion
Salaire := Salaire*Euro;
--Affichage
DBMS_OUTPUT.PUT_LINE(TO_CHAR(Salaire)||' DT');
END;
/
-2-
ISAMM
Cours SGBD & L4G
6. LES CURSEURS
Définition et déclaration
•
Curseur : Structure de données permettant de stocker le résultat d’une requête qui retourne plusieurs tuples (lignes).
•
Déclaration :
CURSOR nom_curs IS requêteSQL;
CURSOR calcul IS
SELECT NumProd, PrixUni*1.18 AS PrixTTC FROM Produit;
NB: Un tuple du curseur sera de type nom_curs%ROWTYPE.
Parcours personnalisé
DECLARE
CURSOR emp_cursor IS
-- déclarer le curseur
SELECT ename, dname FROM emp, dept
WHERE emp.deptno = dept.deptno;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
-- Ouvrir le curseur
LOOP
FETCH emp_cursor INTO emp_record;
-- avancer au tuple suivant du curseur
EXIT WHEN emp_cursor%NOTFOUND;
-- sortir si la fin du curseur est détectée
DBMS_OUTPUT.PUT_LINE('L''employé '|| emp_record.ename ||
' travaille dans le département ' || emp_record.dname);
END LOOP;
CLOSE emp_cursor;
-- fermer le curseur
END;
/
Parcours complet (boucle pour)
DECLARE
CURSOR calcul IS
SELECT EMPNO, SAL + nvl(COMM) AS Total_Salaire FROM Produit;
tuple calcul%ROWTYPE;
BEGIN
FOR tuple IN calcul LOOP -- Ouverture, parcours et fermeture automatiquement effectués
DBMS_OUTPUT.PUT_LINE('Employé numéro '||TO_CHAR(tuple.EMPNO) ||' a un salaire = '||
TO_CHAR(tuple.Total_Salaire));
END LOOP;
END;
/
Attributs des curseurs
•
%NOTFOUND
•
%FOUND
•
%ROWCOUNT
•
%ISOPEN
est égal à TRUE si le dernier FETCH n’a pas retourné un résultat
est égal à TRUE si le dernier FETCH a retourné un résultat (opposé logique de %NOTFOUND)
retourne le nombre de lignes lues
est égal à TRUE si le curseur est ouvert
7. EXCEPTIONS
Définitions
•
Une exception est une erreur déclenchée pendant l’exécution d’un bloc PL/SQL.
•
Une exception est déclenchée implicitement par une erreur Oracle ou explicitement par le programme
Avantages
•
Traitement systématique des erreurs
•
Traitement groupé d'erreurs similaires
•
Lisibilité du code (traitement des erreurs séparé)
Fonctions PL/SQL pour la gestion d’erreurs
•
SQLCODE : renvoie la valeur numérique associée à la dernière exception détectée
•
SQLERRM : renvoi le message associé au code de l’erreur
Exceptions prédéfinies
Nom
Code erreur
Sqlcode
Description
-------------------------------------------------------------------------------------------------NO_DATA_FOUND
ORA-01403
-1403
SELECT mono-ligne retournant 0 ligne
TOO_MANY_ROWS
ORA-01422
-1422
SELECT mono-ligne retournant plus d’1 ligne
DUP_VAL_ON_INDEX
ORA-00001
-1
Insertion d’une ligne en doublon
VALUE_ERROR
ORA-06502
-6502
Erreur arithmétique, conversion ou limite de taille
ZERO_DIVIDE
ORA-01476
-1476
Division par zéro
CURSOR_ALREADY_OPEN
ORA-06511
-6511
Ouverture d’un curseur déjà ouvert
INVALID_NUMBER
ORA-01722
-1722
Echec sur une conversion d’un chaîne de caractères
vers un nombre
…
-3-
ISAMM
Cours SGBD & L4G
Exceptions personnalisées
•
Déclaration (section DECLARE)
nom_exception EXCEPTION;
•
Lever l'exception (section BEGIN)
IF condition THEN
RAISE nom_exception;
END IF;
•
Traitement de l'exception (section EXCEPTION)
•
Exemple 1 :
WHEN nom_exception THEN ...;
DECLARE
c INTEGER;
x_aucun EXCEPTION;
BEGIN
SELECT COUNT(*) INTO c FROM EMP;
IF c=0 THEN
RAISE x_aucun;
ELSE
DBMS_OUTPUT.PUT_LINE('La table EMP contient '||c||' employés');
END IF;
EXCEPTION
WHEN x_aucun THEN DBMS_OUTPUT.PUT_LINE('La table EMP est vide');
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Erreur inconnue numéro ' || SQLCODE);
END;
/
•
Exemple 2 :
SET SERVEROUTPUT ON
SET ECHO OFF
-- Saisie du numéro, du nom et du salire du nouveau employé
PROMPT Entrer le numéro de l'employé
ACCEPT num_emp PROMPT 'numéro : '
PROMPT Entrer le nom de l'employé
ACCEPT nom_emp PROMPT 'nom : '
PROMPT Entrer le salaire de l'employé
ACCEPT sal_emp PROMPT 'salaire : '
Commande SQL*Plus
-- Test de clé primaire sur la table emp
DECLARE
N number(2);
cle_existe EXCEPTION;
cle_nulle EXCEPTION;
BEGIN
-- Valeur nulle
IF &num_emp IS NULL
THEN RAISE cle_nulle;
END IF;
-- Existence de la clé primaire
SELECT COUNT(empno)
INTO n
FROM emp
WHERE empno = &num_emp;
Bloc PL/SQL
IF n>0
THEN RAISE cle_existe;
ELSE insert into emp(EMPNO,ENAME,HIREDATE,SAL)
values (&num_emp,'&nom_emp',sysdate,&sal_emp);
END IF;
EXCEPTION
WHEN cle_existe
THEN DBMS_OUTPUT.PUT_LINE('Clé primaire déjà utilisée!');
WHEN cle_nulle
THEN DBMS_OUTPUT.PUT_LINE('La clé primaire doit avoir une valeur!');
WHEN others
THEN DBMS_OUTPUT.PUT_LINE('Erreur inconnue : ' || SQLERRM);
END;
/
-4-

Documents pareils