63
Auteur : Aurélie Vuaroqueaux Version 1.3 – 7 août 2003 Nombre de pages : 63 Ecole Supérieure d’Informatique de Paris 23. rue Château Landon 75010 – PARIS www.supinfo.com Module n°4 NOTIONS DE BASE DU PL/SQL 1Z0-001

Notions de Base Du PL-SQL

Embed Size (px)

Citation preview

Page 1: Notions de Base Du PL-SQL

Auteur : Aurélie Vuaroqueaux Version 1.3 – 7 août 2003

Nombre de pages : 63

Ecole Supérieure d’Informatique de Paris 23. rue Château Landon 75010 – PARIS www.supinfo.com

Module n°4 NOTIONS DE BASE DU PL/SQL

1Z0-001

Page 2: Notions de Base Du PL-SQL

Notions de base du PL/SQL 2 / 63

Table des matières 1. INTRODUCTION AU PL/SQL ....................................................................................................................... 4 1.1. INTRODUCTION AU PL/SQL.......................................................................................................................... 4

1.1.1. Les caractéristiques PL/SQL................................................................................................................. 4 1.1.2. Les avantages du PL/SQL ..................................................................................................................... 4 1.1.3. Les fonctionnalités du moteur PL/SQL ................................................................................................. 5

1.2. CONVENTIONS DE PROGRAMMATION PL/SQL .............................................................................................. 6 1.2.1. La convention du code .......................................................................................................................... 6 1.2.2. La convention de dénomination d'un identifiant ................................................................................... 6

1.3. LES STRUCTURES DE PROGRAMME PL/SQL .................................................................................................. 7 1.3.1. Les blocs PL/SQL.................................................................................................................................. 7 1.3.2. Les structures de programmes PL/SQL................................................................................................. 8 1.3.3. Les règles syntaxiques des blocs PL/SQL ........................................................................................... 10

2. VARIABLES ET TYPES DE DONNEES..................................................................................................... 11 2.1. LES TYPES DE DONNEES PL/SQL ................................................................................................................ 11

2.1.1. Utilisation et traitement des variables ................................................................................................ 11 2.1.2. Les types de données scalaires............................................................................................................ 12 2.1.3. Les types de données composés........................................................................................................... 12 2.1.4. Les types de données LOB................................................................................................................... 13

2.2. LES VARIABLES SCALAIRES......................................................................................................................... 13 2.2.1. Déclarer de variables scalaires .......................................................................................................... 13 2.2.2. Assigner des valeurs aux variables ..................................................................................................... 14 2.2.3. Déclarer des variables scalaires à l’aide de %TYPE ......................................................................... 14

2.3. LES VARIABLES COMPOSEES (LES COLLECTIONS)........................................................................................ 15 2.3.1. Les collections TABLE et VARRAY..................................................................................................... 15 2.3.2. La collection RECORD ....................................................................................................................... 20 2.3.3. Des collections imbriquées.................................................................................................................. 23

2.4. LES VARIABLES NON-PL/SQL..................................................................................................................... 24 2.5. TRAITEMENT DES VARIABLES ET DES TYPES DE DONNEES PL/SQL............................................................. 25

2.5.1. Manipulation de valeurs à l’aide d’opérateurs................................................................................... 25 2.5.2. Manipulation de valeurs à l’aide de fonctions SQL............................................................................ 26 2.5.3. Manipulation de valeurs à l'aide de fonctions PL/SQL....................................................................... 26 2.5.4. Conversion de types de données.......................................................................................................... 26 2.5.5. Portée des variables et blocs imbriqués.............................................................................................. 26

3. INTERACTION AVEC LE SERVEUR ORACLE...................................................................................... 28 3.1. EXTRACTION DE DONNEES .......................................................................................................................... 28

3.1.1. Extraire des données avec l'ordre SELECT…INTO............................................................................ 28 3.1.2. Exceptions engendrées par des instructions SELECT..INTO.............................................................. 29

3.2. MANIPULATION DES DONNEES .................................................................................................................... 29 3.2.1. Insertion de données ........................................................................................................................... 29 3.2.2. Mise à jour des données ...................................................................................................................... 30 3.2.3. Suppression de données ...................................................................................................................... 30

3.3. CURSEURS SQL .......................................................................................................................................... 31 3.3.1. Les caractéristiques des curseurs SQL ............................................................................................... 31 3.3.2. Attributs des curseurs SQL.................................................................................................................. 31

3.4. GESTION DES TRANSACTIONS..................................................................................................................... 32 3.4.1. Validation des transactions en cours .................................................................................................. 32 3.4.2. Annulation des modifications en attente ............................................................................................. 32 3.4.3. Contrôle des points de transaction...................................................................................................... 32

4. LE CONTROLE DES FLUX DANS LES BLOCS PL/SQL ....................................................................... 34 4.1. LE CONTROLE CONDITIONNEL ..................................................................................................................... 34

4.1.1. Les actions à effectuer de façon sélective............................................................................................ 34

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

4.1.2. Les conditions booléennes................................................................................................................... 38

Page 3: Notions de Base Du PL-SQL

Notions de base du PL/SQL 3 / 63

4.2. LES STRUCTURES DES BOUCLES : LE CONTROLE ITERATIF ........................................................................... 39 4.2.1. La boucle élémentaire LOOP.............................................................................................................. 39 4.2.2. La boucle FOR..LOOP........................................................................................................................ 41 4.2.3. La boucle WHILE..LOOP ................................................................................................................... 42 4.2.4. Les boucles imbriquées ....................................................................................................................... 43

5. LES CURSEURS EXPLICITES.................................................................................................................... 45 5.1. INTRODUCTION SUR LES CURSEURS............................................................................................................. 45

5.1.1. Types de curseur ................................................................................................................................. 45 5.1.2. Les caractéristiques des curseurs explicites........................................................................................ 45 5.1.3. Contrôle des curseurs explicites ......................................................................................................... 45

5.2. UTILISATION DES CURSEURS EXPLICITES.................................................................................................... 46 5.2.1. Déclaration des curseurs explicites .................................................................................................... 46 5.2.2. Ouverture des curseurs explicites ....................................................................................................... 47 5.2.3. Extraction de données d’un curseur explicite ..................................................................................... 47 5.2.4. Fermeture d’un curseur ...................................................................................................................... 48

5.3. LES ATTRIBUTS DES CURSEURS EXPLICITES ................................................................................................ 48 5.3.1. Contrôle de l’état à l’aide de l’attribut %ISOPEN ............................................................................. 48 5.3.2. Contrôle de l’état à l’aide de l’attribut %FOUND ............................................................................. 49 5.3.3. Sortie d’une boucle à l’aide de l’attribut %NOTFOUND .................................................................. 49 5.3.4. Nombre de lignes renvoyées à l’aide de %ROWCOUNT.................................................................... 50

5.4. UTILISATION AVANCEE DES CURSEURS EXPLICITES..................................................................................... 50 5.4.1. Extraction de lignes à l’aide de la boucle de curseur FOR ................................................................ 50 5.4.2. La boucle de curseur FOR avec une sous-requête.............................................................................. 51 5.4.3. Verrouiller et mettre à jour les lignes d'un curseur ............................................................................ 51 5.4.4. Déclaration de curseurs explicites avec des paramètres .................................................................... 52 5.4.5. Des curseurs avec des sous-requêtes .................................................................................................. 53

6. GESTION DES EXCEPTIONS ..................................................................................................................... 54 6.1. INTRODUCTION SUR LES EXCEPTIONS.......................................................................................................... 54

6.1.1. Lever et traiter les exceptions ............................................................................................................. 54 6.1.2. Les types d'exception........................................................................................................................... 54

6.2. CAPTURER LES EXCEPTIONS........................................................................................................................ 55 6.2.1. Capturer les exceptions....................................................................................................................... 55 6.2.2. Capturer des erreurs prédéfinies du serveur Oracle .......................................................................... 55 6.2.3. Capturer des exceptions non prédéfinies du serveur Oracle .............................................................. 56 6.2.4. Les fonctions pour capturer les exceptions ......................................................................................... 58 6.2.5. Capturer les exceptions définies par l'utilisateur................................................................................ 58 6.2.6. La procédure RAISE_APPLICATION_ERROR .................................................................................. 59

6.3. LA PROPAGATION DES EXCEPTIONS............................................................................................................. 61

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 4: Notions de Base Du PL-SQL

Notions de base du PL/SQL 4 / 63

1. Introduction AU PL/SQL 1.1. Introduction au PL/SQL

1.1.1. Les caractéristiques PL/SQL - Procedural Language/SQL (PL/SQL) est une extension procédurale au SQL propre à Oracle. Le

PL/SQL possède les caractéristiques des langages de programmation procéduraux, tels que le C et le FORTRAN, qui ne sont pas disponibles dans le SQL : l'encapsulation des données, le traitement des exceptions, l'orientation objet…

- Le PL/SQL est un puissant langage de traitement des transactions. - Le PL/SQL est un langage hybride : il utilise des ordres SQL pour accéder à la base de données et

des instructions PL/SQL pour contrôler les ordres SQL afin de traiter de façon explicite des données.

- Le PL/SQL permet d'inclure la manipulation des données et les ordres SQL dans des blocs structurés et dans des unités procédurales de code.

1.1.2. Les avantages du PL/SQL o La modularisation du développement des programmes grâce aux :

- Blocs : regroupement en blocs des instructions entre lesquelles il existe un lien logique. - Fonctions et procédures : imbrication de sous blocs à l’intérieur de blocs plus importants afin

d’élaborer des programmes puissants. Fractionnement d'un problème complexe en un ensemble de modules logiques bien définis et simples à gérer. Ces modules peuvent être ensuite mis en œuvre à l’intérieur de blocs.

- Packages : Regroupement des modules en une seule unité logique.

o Déclaration d’identifiants tels que des variables, des constantes, des curseurs, des exceptions - Variables PL/SQL : déclaration de variables dont le type de données peut être simple ou

composé. - Utilisation des identifiants dans les instructions SQL et dans les instructions procédurales. - Attributs %TYPE et %ROWTYPE : déclaration dynamique de variables, en fonction de la

structure de données des colonnes d'une table et des tables de la base de données.

o Structures de contrôle des langages procéduraux - Les boucles : écriture de programmes avec des structures de contrôle issues des langages

procéduraux. Une séquence d’instructions peut donc être exécutée de façon conditionnelle ou itérative dans une boucle.

- Les curseurs explicites : traitement de façon individuelle des lignes renvoyées par une requête.

- Combinaison du PL/SQL avec des outils Oracle, tels que Oracle Developer (constitué de Forms, Reports et Graphics), afin de regrouper les commandes associées, dans le but de contrôler l’exécution.

o Traitement des erreurs

- Routine de traitement des exceptions : traitement des erreurs du serveur Oracle. - Les exceptions définies par l'utilisateur : déclaration de conditions d’erreurs par l'utilisateur et

traitement des erreurs avec les routines de traitement des exceptions.

o Portabilité accrue : - Déplacement de programme possible vers n’importe quel environnement prenant en charge

Oracle et PL/SQL (grâce aux fonctionnalités glisser-déplacer de Procédure Builder).

o Intégration :

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

- Réduction des problèmes d’intégration entre le serveur Oracle et les outils de développement.

Page 5: Notions de Base Du PL-SQL

Notions de base du PL/SQL 5 / 63

- Le PL/SQL est le langage commun au serveur Oracle (à travers les procédures stockées, les triggers de base de données et les packages) et aux outils de développement d’Oracle (à travers les triggers de Oracle Developer).

- Les bugs d’intégration sont également réduits, car les variables et types de données PL/SQL et SQL sont compatibles. Ainsi, PL/SQL facilite l’accès pratique aux bases de données et satisfait les besoins en terme de programmation procédurale.

o L’amélioration des performances

- PL/SQL peut être utilisé pour regrouper les ordres SQL ensemble en un seul bloc et d'envoyer ce bloc au serveur en un seul appel, ce qui a pour conséquence de réduire le trafic sur le réseau.

- Les performances dépendent de l’environnement d’exécution.

1.1.3. Les fonctionnalités du moteur PL/SQL Un serveur Oracle prenant en charge PL/SQL est appelé serveur Oracle avec extension procédurale. Les blocs PL/SQL sont transmis de l'application au moteur PL/SQL du serveur Oracle. Ensuite, le moteur PL/SQL fractionne les instructions SQL du bloc en instructions séparées, puis les envoie au moteur SQL.

Figure 1 : Le moteur PL/SQL au niveau du serveur Oracle

Si les blocs sont fractionnés en instructions SQL, un seul transfert est nécessaire entre l’application et le serveur Oracle ce qui permet de réduire le trafic réseau et d’augmenter de façon significative les performances, en particulier en architecture client/serveur. Le moteur PL/SQL utilisé pour traiter le code dépend de l’emplacement du bloc de code PL/SQL. La méthode de traitement du code sur le serveur Oracle est différente de celle utilisée dans les outils Oracle. En effet, beaucoup d'outils Oracle possèdent leur propre moteur PL/SQL indépendant du moteur PL/SQL présent sur le serveur Oracle. Le moteur PL/SQL des outils Oracle filtre les instructions SQL du code de l’application et les envoie individuellement vers le moteur SQL du serveur Oracle. Il exécute les instructions procédurales du bloc PL/SQL avec le moteur procédural du moteur PL/SQL. Le moteur procédural traite les données locales de l’application ce qui réduit le nombre de tâches envoyées au serveur Oracle ainsi que le nombre de curseurs mémoire utilisés.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 6: Notions de Base Du PL-SQL

Notions de base du PL/SQL 6 / 63

Figure 2 : Le moteur PL/SQL des outils Oracle

Le serveur peut accueillir du code contenant un grand nombre d’instructions SQL afin de réduire le nombre d’instructions SQL individuelles envoyées à travers le réseau.

1.2. Conventions de programmation PL/SQL 1.2.1. La convention du code

S'écrivent en majuscule : - les commandes SQL, tels que SELECT, INSERT… - les mots clés PL/SQL, tels que DECLARE, BEGIN, IF… - les types de données, tels que VARCHAR2, BOOLEAN…

Se mettent en minuscules : - les identifiants et les paramètres, tels que v_sal, emp_cursor, g_sal, p_empno… - les noms de tables et les noms de colonnes, tels que dept, emp, empno, ename…

1.2.2. La convention de dénomination d'un identifiant Afin de maintenir l’uniformité du code, un ensemble de préfixes et de suffixes a été développé afin de distinguer facilement un identifiant parmi les autres identifiants tels que les objets de base de données et les objets nommés. Grâce à une convention de dénomination standard, le code est facile à lire et à mettre à jour.

Identifiant Convention de nommage Exemple Variables v_name v_sal Constantes c_name c_compagny Curseurs name_cursor emp_cursor Exceptions e_name e_too_many

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 7: Notions de Base Du PL-SQL

Notions de base du PL/SQL 7 / 63

Types Table name_table_type amount_table_type Tables name_table order_table Types Record name_record_type emp_record_type Records name_record customer_record Variables de substitution SQL*Plus p_name p_sal Variables globales SQL*Plus g_name g_year_sal

(Voir aussi § 1.3.3 Règles syntaxiques des blocs PL/SQL)

1.3. Les structures de programme PL/SQL 1.3.1. Les blocs PL/SQL

PL/SQL est un langage structuré en blocs : les instructions entre lesquelles il existe un lien logique sont regroupées en blocs. Un bloc de base PL/SQL peut contenir trois sections : Section déclarative Elle contient toutes les déclarations des variables, constantes, curseurs et

exceptions définies par l’utilisateur et utilisées dans la section exécutable. La section déclarative est facultative et doit commencer par le mot clé DECLARE.

Section exécutable Elle contient des instructions SQL permettant de manipuler les données de la base de données et des instructions PL/SQL permettant de manipuler les données d’un bloc. La section exécutable est obligatoire et doit commencer par le mot clé BEGIN.

Section de traitement des exceptions

Elle spécifie les actions à effectuer lorsque des erreurs ou des conditions anormales se produisent dans la section exécutable. La section de traitement des exceptions est facultative et doit commencer par le mot clé EXCEPTION.

Un bloc PL/SQL se termine par le mot-clé END suivi d’un point virgule. Pour faciliter la lecture d’un bloc de code PL/SQL, chaque nouvelle instruction doit être sur une nouvelle ligne et les différents niveaux des blocs doivent être mis en évidence par des retraits. [DECLARE] [<Section déclarative optionnelle>] BEGIN <Section exécutable obligatoire> [EXCEPTION] <Section de traitement des exceptions optionnelle>] END;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 8: Notions de Base Du PL-SQL

Notions de base du PL/SQL 8 / 63

DECLARE v_ename VARCHAR2(5); BEGIN SELECT ename INTO v_ename FROM emp WHERE empno = 1234; EXCEPTION WHEN NO_DATA_FOUND THEN ... END;

La section déclarative de ce bloc déclare une variable de type VARCHAR2, d'une

longueur de 5 et appelée v_ename. La section exécutable est constituée d'une seule instruction : un ordre SELECT qui

1.3.2. Les structures de programmes PL/SQL Les structures de programmes sont des blocs ou des modules PL/SQL exécutant différentes fonctions selon l’environnement d’exécution. Une structure de programmes peut être constituée d’un bloc PL/SQL unique, de blocs imbriqués ou d’un groupe de blocs. Il existe plusieurs types de structures de programmes : les blocs anonymes, les procédures et fonctions stockées, les procédures et fonctions d'application, les packages, les triggers de base de données et les triggers d'application.

Les blocs anonymes

Un bloc anonyme est un bloc PL/SQL non nommé, imbriqué dans une application ou créé de façon interactive. Un bloc anonyme est déclaré dans une application à l’endroit de son exécution. Il est ensuite passé au moteur PL/SQL pour être exécuté. Un bloc anonyme peut être imbriqué dans un programme de pré-compilation et dans SQL*Plus (ou Server Manager). Les blocs anonymes sont disponibles dans tous les environnements PL/SQL.

[DECLARE <Déclarations>] BEGIN <Instructions> [EXCEPTION <Traitements des erreurs>] END ; Pour exécuter un bloc anonyme dans le buffer de SQL*Plus, il faut utiliser le caractère slash "/". Si le bloc s'exécute avec succès, sans erreurs soulevées ni d'erreurs de compilation, le message suivant s'affiche :

PL/SQL procedure successfully completed

Les procédures et fonctions stockées

Il s’agit d’un bloc PL/SQL nommé et stocké sous forme d’objet de base de données dans le dictionnaire de données du serveur Oracle. Il peut utiliser des paramètres d’entrée et de sortie, il peut être invoqué de façon répétée et est disponible sur le serveur Oracle avec extension procédurale.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Administrateur
Fin de phrase
Page 9: Notions de Base Du PL-SQL

Notions de base du PL/SQL 9 / 63

Une fonction, à la différence d'une procédure, retourne une valeur.

Il existe trois types de paramètres : - IN : passer des valeurs à un sous-programme qui est appelé. - OUT : retourner des valeurs à celui qui a appelé le sous-programme. - INOUT : passer des valeurs initiales à un sous-programme et retourner la mise à jour des valeurs à

celui qui a appelé le sous-programme.

Les procédures et fonctions d'application

Il s’agit d’une autre structure de programmation possédant les mêmes attributs (et même syntaxe) qu’une procédure ou fonction stockée. Il s’agit d’un bloc PL/SQL nommé résidant dans une application Oracle Developer ou dans une librairie partagée. Cette structure accepte les paramètres (entrée et sortie), et peut être invoquée de façon répétée. Elle est disponible avec le serveur Oracle et les composants de Oracle Developer.

Les packages

Il s’agit d’un bloc PL/SQL nommé regroupant des procédures, des fonctions et des identifiants (curseurs, variables, constantes, exceptions, définition de collection) liés entre eux. Les packages sont disponibles sur le serveur Oracle avec extension procédurale.

PACKAGE nom IS PROCEDURE nom (arguments) ; … END ; CREATE PACKAGE BODY AS PROCEDURE nom IS … END ; END ;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

PROCEDURE nom (parameters) IS <déclaration> BEGIN <instructions> [EXCEPTION] <traitement des exceptions> END ;

FUNCTION name (parameters) RETURN datatype IS <déclaration> BEGIN <instructions> [EXCEPTION] <traitement des exceptions> END ;

Page 10: Notions de Base Du PL-SQL

Notions de base du PL/SQL 10 / 63

Les triggers de base de données

Il s’agit d’un bloc PL/SQL associé à une table de la base de données. Il est exécuté automatiquement lors de la manipulation du contenu de la table à laquelle il est attaché. Le trigger de base de données est disponible sur le serveur Oracle.

TRIGGER nom { BEFORE | AFTER } [FOR EACH ROW] [WHEN <condition>] BEGIN <instructions> [EXCEPTION] <traitement des exceptions> END ;

Les triggers d'application

Il s’agit d’un bloc PL/SQL associé à un événement d’application et exécuté automatiquement lorsqu’un événement spécifié se produit. Le trigger d'application n'est disponible que dans les composants de Oracle Developper.

1.3.3. Les règles syntaxiques des blocs PL/SQL Les règles générales de syntaxe appliquées au langage SQL le sont également au langage PL/SQL.

- Un identifiant peut comporter un maximum de 30 caractères et doit commencer par une lettre.

- Les mots réservés ne peuvent pas être utilisés comme identifiant. - Le nom d’un identifiant doit être différent des noms des colonnes des tables (au quel cas le

moteur interprète l’identifiant comme une référence à la colonne).

- Les mots clés ne doivent pas être coupés en fin de ligne.

- Les chaînes de caractères et les dates figurant dans les instructions PL/SQL doivent être inclues entre simples quotes.

- Les expressions numériques sont représentées soit par une valeur simple, soit par une

notation scientifique. - Les commentaires sur plusieurs lignes doivent être inclus entre les caractères " /* " et " */ "

(Ces symboles sont à éviter après le mot clé SELECT car ils sont utilisés dans ce cas comme indicateur pour l’optimisateur). Les caractères "- -" sont utilisés pour mettre une seule ligne en commentaire.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

- Les unités lexicales doivent être séparées à l’aide d’un ou plusieurs espaces ou délimiteurs.

Page 11: Notions de Base Du PL-SQL

Notions de base du PL/SQL 11 / 63

2. VARIABLES ET TYPES DE DONNEES

2.1. Les types de données PL/SQL 2.1.1. Utilisation et traitement des variables

Une variable est un espace de stockage temporaire de données. variable_name [CONSTANT] datatype [NOT NULL] [ := | DEFAULT expr] ;

datatype : le type de données de la variable peut être scalaire, composé, référence ou LOB.

CONSTANT : ce mot clé contraint la variable à contenir une valeur qui ne peut être changée.

NOT NULL : ces mot clés contraignent la variable à contenir une valeur. expr : l’expression définissant la valeur par défaut d’une variable peut

être une valeur littérale, une autre variable ou une expression impliquant des opérateurs et des fonctions.

Une fois déclarées, les variables peuvent être utilisées de façon répétée dans une application simplement en les référençant dans d'autres ordres même déclaratifs. Les valeurs stockées par la variable peuvent être manipulées. Utilisation et traitement des variables : - Déclarer et initialiser les variables dans la section déclarative.

Les déclarations allouent l'espace de stockage nécessaire pour une valeur, spécifient les types de données et nomment la localisation du stockage qui sert à le référencer. Affecter de nouvelles valeurs aux variables dans la section exécutable.

- Nommer les identifiants selon les règles utilisées pour la dénomination des objets SQL. - Affecter une valeur initiale à une variable déclarée comme NOT NULL et/ou CONSTANT. - Initialiser une variable avec une expression, en utilisant l’opérateur d’affectation " := " ou le mot

réservé DEFAULT. Par défaut, la valeur NULL est affectée aux variables. - Passer les variables à des sous-programmes à l'aide de paramètres. PL/SQL prend en charge quatre types de données qui peuvent être utilisés pour la déclaration de variables, de constantes, de pointeurs ou de localisateurs : Scalaire Contient une valeur unique mais pas de composants internes.

Composé

Contient des composants internes qui peuvent être manipulés. Ce type de données est réutilisable. Les variables de type composé sont des variables temporaires auxquelles différentes valeurs peuvent être affectées au cours de l’exécution. Ex : types RECORD, TABLE, NESTED TABLE et VARRAY.

Référence Il s’agit d’un pointeur vers un autre type de données. Il contient des valeurs appelées pointeurs, désignant d’autres objets programme.

LOB Il s'agit d'un "localisateur" qui spécifie la localisation de gros objet (des images, des vidéos…) qui sont stockés "out offline".

Il existe trois types de variables non-PL/SQL :

- les variables de substitution (cf Module 2 § 4.1 Les variables de substitutions)

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

- les variables définies par l'utilisateur (cf Module 2 § 4.2 Les variables définies par l'utilisateur)

Page 12: Notions de Base Du PL-SQL

Notions de base du PL/SQL 12 / 63

- les variables hôtes (appelées aussi "bind" variable)

2.1.2. Les types de données scalaires Un type de données scalaires est utilisé pour stocker une valeur unique. En PL/SQL, le type de données scalaire est divisé en quatre catégories : nombre, caractères, date et booléen. Les types scalaires les plus utilisés et leurs sous-types :

INTEGER Entier. POSITIVE Entier positif

BINARY_INTEGER Entiers entre -2 147 483 647 et 2 147 483 947.

NUMBER [(précision, degré)] Nombre flottant

NUMBER

PLS_INTEGER Entiers signés entre -2 147 483 647 et 2 147 483 947.

LONG Chaîne de caractères variables (jusqu’à 32 760 octets).

VARCHAR2 Chaîne de caractères variables (jusqu’à 32 767 octets, pas de valeur par défaut) CHAR

CHAR [(maximum_length)]. Chaîne de caractère fixe (jusqu’à 32767 octets, si maximum_length n'est pas spécifié, alors sa taille est 1).

DATE Date et heure. La tranche des dates est de 4712 B.C. à 9999 A.D.

BOOLEAN Type de données pouvant stocker trois valeurs possibles utilisées pour les calculs logiques : TRUE, FALSE ou NULL.

RAW (maximum_size) Type de données stockant des données binaires. Sa taille maximale est de 2 000 octets. Ce type n'est pas interprété par le PL/SQL. RAW

LONG RAW (maximum_size)

Type de données stockant des données binaires. Sa taille maximale est de 32 760 octets. Ce type n'est pas interprété par le PL/SQL.

Les valeurs PLS_INTEGER requiert moins d'espace de stockage et sont plus rapide que les valeurs NUMBER et BINARY_INTEGER.

2.1.3. Les types de données composés Les types de données composés (appelées aussi collections) sont :

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

RECORD Type de données permettant de déclarer un identifiant pouvant stocker une ligne constituée de plusieurs colonnes possédant chacune son propre nom et son propre type de données.

TABLE Type de données permettant de déclarer un identifiant pouvant stocker au plusieurs valeurs toutes du même type de données. Une TABLE n'a pas de taille fixe et possède une colonne PRIMARY KEY.

VARRAY

Type de données permettant de déclarer un identifiant pouvant stocker au plusieurs valeurs toutes du même type de données. Un tableau (VARRAY) a une taille minimale fixée à 1 et une taille maximale fixée lors de sa déclaration.

Page 13: Notions de Base Du PL-SQL

Notions de base du PL/SQL 13 / 63

2.1.4. Les types de données LOB Les types de données LOB (Large Object) d'Oracle8i, des blocs de données non structurés (tels que du texte, des images, des fichiers vidéos et fichiers audios…) permettent de stocker des objets jusqu'à 4 gigaoctets dans la base de données. Il existe quatre types de données LOB : CLOB (Character Large Object Binary)

CLOB est utilisé pour stocker des gros blocs de texte (caractères sur 8 bits).

BLOB (Binary Large Object)

BLOB est utilisé pour stocker de larges objets binaires.

BFILE (Binary File)

BFILE est utilisé pour stocker de larges objets binaires tels que des fichiers OS.

NCLOB (National Language Character Large Object)

NCLOB est utilisé pour stocker de gros blocs de données, unité en octet ou multi-octets de taille fixe.

2.2. Les variables scalaires 2.2.1. Déclarer de variables scalaires

Une variable doit être déclarée avant d'être référencée dans une instruction. variable_name [CONSTANT] scalair [NOT NULL] [ := | DEFAULT expr] ; Exemple :

DECLARE v_location VARCHAR(13) := 'Atlanta' ; v_deptno NUMBER(2) NOT NULL := 10 ; c_comm CONSTANT NUMBER DEFAULT 100 ; v_hiredate DATE := SYSDATE + 7 ; v_valid BOOLEAN NOT NULL := TRUE ; v_count BINARY_INTEGER := 0 ;

v_location est une variable déclarée qui stocke la location d'un département. v_deptno est une variable déclarée qui stocke le numéro d'un département, qui ne peut pas contenir une valeur nulle et dont la valeur par défaut est 10. c_comm est une constante déclarée correspondant à une commission et dont la valeur par défaut est 100. v_hiredate est une variable déclarée correspondant à une date d'embauche et dont la valeur par défaut est la date du jour additionnée de 7 jours. v_valid est un indicateur déclaré précisant la validité ou non des données et initialisé à TRUE. v_count est une variable déclarée qui compte le nombre d'itérations dans une boucle et dont la valeur par défaut est 0.

Les chaînes de caractères littérales doivent être placées entre simple quotes, par exemple : 'Hello, World'. Si la chaîne contient une apostrophe, il faut doubler l'apostrophe. Par exemple, pour insérer la valeur Luke, I'm your father, la chaîne doit être écrit ainsi 'Luke, I''m your father'. Deux objets (dont les variables) peuvent avoir le même nom à condition qu'ils soient définis dans des blocs différents.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Les identifiants ont une longueur maximale de 30 caractères. Le premier caractère doit être une lettre, les caractères suivants peuvent être des lettres, des nombres ou des caractères spéciaux.

Page 14: Notions de Base Du PL-SQL

Notions de base du PL/SQL 14 / 63

2.2.2. Assigner des valeurs aux variables Pour assigner une valeur à une variable, il faut écrire un ordre PL/SQL d'assignement. La variable doit être explicitement nommée pour qu'elle reçoive la nouvelle valeur. Cette valeur est placé à gauche de l'opérateur d'assignement " := ". Identifiant := expr ; Exemples :

v_hiredate := '31-DEC-98';

Cet assignement n'est possible que dans la version 8i d'Oracle. Les versions

antérieures requièrent la fonction TO_DATE.

v_ename := 'Maduro';

Il existe une autre façon d'assigner une valeur à une variable : de sélectionner (SELECT) ou de ramener (FETCH) des valeurs dans la base de données. Exemple :

SQL> SELECT sal * 0.10 2 INTO v_bonus 3 FROM emp 4 WHERE empno = 7369 ;

L'exemple ci-dessus sélectionne le salaire des employés dans la table EMP, le

majore de 10% et stocke le résultat dans la variable v_bonus. La variable v_bonus peut être utilisée dans une expression ou sa valeur peut être insérée dans une table de la base de données.

2.2.3. Déclarer des variables scalaires à l’aide de %TYPE Lorsqu'une application doit mettre à jour les valeurs des colonnes d’une table, l'intégrité des données doit être respectée et les erreurs d'exécution évitées. Les variables PL/SQL qui contiendront les valeurs des colonnes doivent être déclarées du même type de données que les colonnes à mettre à jour. Plutôt que d’écrire explicitement le type de données et la précision, une variable peut être déclarée en fonction d’une colonne de base de données grâce à l’attribut %TYPE.

variable_name table_name.column_name%TYPE [NOT NULL][ := | DEFAULT expr];

%TYPE est très utile dans la mesure où la déclaration de la variable ne nécessite pas de connaître le type exacte des données de la colonne de la base de données dont elle va accueillir les valeurs. PL/SQL détermine le type de données et la précision de la variable de la variable lors de la compilation du bloc. De plus, si le type de données de la colonne change dans la base de données, le type de données de la variable déclarée à l’aide du type %TYPE sera modifié par un recompilation automatique. Exemple :

v_ename emp.ename%TYPE ;

La variable s’appelle v_ename. Le type de données de cette variable est celui de

la colonne ENAME de la table EMP.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 15: Notions de Base Du PL-SQL

Notions de base du PL/SQL 15 / 63

Si une variable est déclarée avec %TYPE et référence une colonne définie comme NOT NULL, la valeur de cette variable peut être quand même être NULL. En effet, la contrainte NOT NULL sur la colonne ne s'applique pas automatiquement sur la variable. La contrainte NOT NULL doit être appliquée à la variable pour interdire les valeurs nulles. Exemple :

v_ename emp.ename%TYPE ;

En admettant que la colonne ENAME possède la contrainte NOT NULL, la

variable v_ename peut quand même posséder des valeurs nulles.

v_ename emp.ename%TYPE NOT NULL;

La contrainte NOT NULL est appliquée à la variable, donc elle ne peut pas

contenir une valeur nulle. L’attribut %TYPE peut aussi être utilisé pour déclarer une variable présentant le même type de données qu’une autre variable déclarée précédemment. variable2 variable1%TYPE [NOT NULL] [ := | DEFAULT expr] ; Exemple :

v_balance NUMBER(7,2) ; v_min_balance v_balance%TYPE := 10 ;

La variable v_min_balance est du même type que la variable v_balance, soit

NUMBER(7,2) et est initialisée à 10.

2.3. Les variables composées (les collections) 2.3.1. Les collections TABLE et VARRAY

Définir une collection TABLE

Une table PL/SQL est un tableau à une dimension (une seule colonne utilisable) dynamique, inconsistant constitué d'éléments homogènes (données du même type) et indexé par des nombres entiers. Elle est donc composée de deux colonnes :

- La première colonne est la clé primaire qui sert à indexer la table PL/SQL. Le type de données de cette colonne est BINARY_INTEGER. ( de -2 147 483 647 à 2 147 483 647). L'index n'est pas obligé de commencer à 1 et peut être négatif.

- La seconde colonne est du type de données scalaire ou RECORD, elle stocke les éléments de la table PL/SQL.

Attention, une table PL/SQL est différente d’une table de base de données. Il ne faut pas confondre la clé primaire d'une table de base de données avec la clé primaire d'une table PL/SQL. Elles n'ont pas le même rôle.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 16: Notions de Base Du PL-SQL

Notions de base du PL/SQL 16 / 63

Exemple :

PRMARY KEY COLUMN

… … 1 Jones 2 Smith 3 Maduro

… …

Représentation graphique d'une table PL/SQL stockant des noms d'employés La taille d’une table PL/SQL peut augmenter de façon dynamique. Avant d'utiliser une table PL/SQL, il faut d'abord déclarer un type de données TABLE car il n'existe pas de types de données TABLE prédéfinies, et ensuite déclarer une variable PL/SQL de ce type. Déclaration d’un type TABLE PL/SQL : TYPE type_name IS TABLE OF { column_type | variable%TYPE | table.column%TYPE | table%ROWTYPE } [NOT NULL] [INDEX BY BINARY_INTEGER] ;

La clause INDEX BY est obligatoire en PL/SQL version 2 et optionnelle en PL/SQL version 8. Les exemples de ce cours utilise la version 2 Si la clause INDEX BY est omise, alors cela signifie que le type de la table est un type de table imbriqué dans un autre.

Exemples :

TYPE table_type IS TABLE OF VARCHAR2(25) INDEX BY BINARY_INTEGER ;

TYPE EmpList IS TABLE OF emp.empno%TYPE INDEX BY BINARY_INTEGER ;

TYPE EmpTabTyp IS TABLE OF emp%ROWTYPE; INDEX BY BINARY_INTEGER ;

Définir une collection VARRAY

La collection VARRAY permet d'associer un identifiant unique à une collection entière (un tableau). Cette association permet de manipuler la collection dans son ensemble et de référencer facilement chaque élément. Une collection VARRAY possède une taille maximale qui doit être spécifiée dans sa définition. Son index à une limite inférieure fixée à 1 et une limite supérieure fixée lors de la déclaration du type. Syntaxe : TYPE type_name IS {VARRAY | VARYING ARRAY} {size_limit} OF

{column_type | variable%TYPE | table.column%TYPE | table%ROWTYPE } [NOT NULL];

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 17: Notions de Base Du PL-SQL

Notions de base du PL/SQL 17 / 63

type_name est un type spécifique utilise plus tard pour déclarer une variable VARRAY. size_limit est un entier positif littéral déterminant le nombre de poste dans la collection (VARRAY). element_type correspond au type de données PL/SQL des éléments de la collection. Si le type de données est du type RECORD, tous les champs du RECORD doivent être du type scalaire ou objet.

Le type des éléments peut être également défini avec %ROWTYPE ou %TYPE. Exemples :

TYPE Calendar IS VARRAY(366) OF DATE;

TYPE AnEntry IS RECORD ( term VARCHAR2(20), meaning VARCHAR2(200)); TYPE Glossary IS VARRAY(250) OF AnEntry;

TYPE Platoon IS VARRAY(20) OF Soldier; p1 Platoon; p2 p1%TYPE;

CURSOR c1 IS SELECT * FROM dept; TYPE DeptFile IS VARRAY(20) OF c1%ROWTYPE;

Déclarer et Initialiser une collection TABLE ou VARRAY

Après avoir créer le type de la collection, il faut déclarer une variable de ce type : Identifiant type_name ; Tan qu'elle n'est pas initialisée, une collection est NULL (ce ne sont pas ses éléments qui sont NULL mais la collection elle-même). Pour initialiser une collection, il faut utiliser un constructeur. Un constructeur est une fonction définie par le système ayant le même nom que le type de la collection. Cette fonction "construit" la collection en lui passant des valeurs. Exemple :

DECLARE TYPE CourseList IS VARRAY(20) OF VARCHAR2(10); my_courses CourseList; my_courses2 CourseList := CourseList('Prog','Engl','Hist'); my_courses3 CourseList := CourseList(); BEGIN my_courses := CourseList('Math','Eco',NULL,'Management'); IF my_courses3 IS NOT NULL THEN ... END IF; END;

Le type de tableau CourseList a une capacité maximale de 20 postes. Les quatre premiers postes du tableau my_courses sont initialisés dans la section exécutive. La valeur NULL peut être passé au constructeur à condition que la contrainte NOT NULL ne soit pas appliquée dans la déclaration du type VARRAY.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Un tableau VARRAY peut être initialisé de la même façon dans la section déclarative, c'est le cas des tableaux my_courses2 et my_courses3. A la différence

Page 18: Notions de Base Du PL-SQL

Notions de base du PL/SQL 18 / 63

que my_courses3 est initialisé comme une collection vide (attention elle n'est pas nulle, mais vide, donc la condition de la boucle IF retournera TRUE).

Note : Cette méthode d'initialisation à l'aide d'un constructeur est applicable aux tables PL/SQL indexée. Le moteur PL/SQL n'appelle jamais implicitement un constructeur, il doit donc être appelé explicitement. Exemple :

CREATE TYPE CourseList AS VARRAY(50) OF VARCHAR2; CREATE TABLE Student ( id_num INTEGER(4), name VARCHAR2(25), address VARCHAR2(35), courses CourseList);

BEGIN INSERT INTO Student VALUES (5035, 'Mickey Mouse','122 Disney St', CourseList('Eco','Geo','Hist','Eng','Math',...)); ...

Le constructeur CourseList fournit une valeur pour le champ courses de la table de base de données Student.

Interroger les collections TABLE et VARRAY

Les méthodes d'interrogation des collections TABLE et VARRAY ont des procédures ou des fonctions qui opèrent sur des tables et qui permettent d'obtenir diverses informations sur des tables. collection_name.method_name [ (parameters) ]

Méthode Description EXISTS(n) Retourne TRUE si le n-ième élément existe dans une table PL/SQL. COUNT Retourne le nombre d'éléments que contient une table PL/SQL. FIRST LAST

Retourne le premier et le dernier (le plus petit et le plus grand) numéro d'index dans une table PL/SQL. Retourne NULL si la table PL/SQL est vide.

PRIOR(n) Retourne le numéro d'index qui précède le numéro d'index n dans une table PL/SQL. NEXT(n) Retourne le numéro d'index qui suit le numéro d'index n dans une table PL/SQL.

EXTEND *

Augmente la taille d'une table PL/SQL. EXTEND ajoute un élément null à une table PL/SQL. EXTEND(n) ajoute n éléments null à une table PL/SQL. EXTEND(n, i) ajoute n copies de l'élément i existant dans une table PL/SQL.

TRIM * TRIM supprime le dernier élément d'une table PL/SQL. TRIM(n) supprime les n dernier éléments d'une table PL/SQL.

DELETE DELETE supprime tous les éléments d'une table PL/SQL. DELETE(n) supprime le n-ième élément d'une table PL/SQL. DELETE(m,n) supprime tous les éléments dans la tranche m à n d'une table PL/SQL.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 19: Notions de Base Du PL-SQL

Notions de base du PL/SQL 19 / 63

Référencer une collection TABLE ou VARRAY

Pour référencer un élément d'une table PL/SQL, il faut utiliser la syntaxe suivante : collection_name(index)

index doit être est un entier (qui peut être issue d'une expression). Cet entier doit être compris entre -2**31 et 2**31 en ce qui concerne les tables PL/SQL, et entre 1 et la limite supérieur définie dans le type en ce qui concerne les tableaux.

Exemple :

ename_collection(3)

Cette instruction référence le troisième élément d'une collection.

Exemple :

DECLARE TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; TYPE hiredate_table_type IS TABLE OF DATE INDEX BY BINARY_INTEGER; ename_table ename_table_type; hiredate_table hiredate_table_type; BEGIN ename_table(1) := 'CAMERON'; hiredate_table(8) := SYSDATE + 7; IF ename_table.EXISTS(1) THEN INSERT INTO ... ... END;

ename_table_type est un type de table PL/SQL indexée destiné à stocker des

valeurs du même type que la colonne ENAME de la table de base de données EMP. hiredate_table_type est un type de table PL/SQL indexée destiné à stocker des dates. ename_table est une table PL/SQL du type ename_table_type. hiredate_table est une table PL/SQL du type hiredate_table_type. Dans la section exécutable, la valeur "CAMERON" est stockée dans la table ename_table à la ligne dont l'index vaut 1, et la valeur correspondant à la date du jour additionnée de 7 jours est stockée dans la table hiredate_table à la ligne dont l'index vaut 7. L'instruction IF teste si la ligne 1 existe dans la table ename_table. Si l'élément existe, alors l'instruction INSERT INTO est exécutée.

Pour pouvoir être affectée le contenu d'une collection à une autre, les deux collections doivent être du même type. Deux collections ne peuvent pas être comparées dans une égalité oud ans une inégalité. Des collections ne peuvent pas apparaître dans une liste DISTINCT, GROUP BY ou ORDER BY. Exemple :

DECLARE TYPE Admin IS VARRAY(60) OF Person; TYPE Student IS VARRAY(600) OF Person; Prepa1 Student := Student(...); Prepa2 Student := Student(...); Prof Admin := Prof(...); BEGIN

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Prepa2 := Prepa1;

Page 20: Notions de Base Du PL-SQL

Notions de base du PL/SQL 20 / 63

Prepa1 := Prof; -- illegal ; différents types IF Prepa2 = Prepa1 THEN -- compilation error ... END IF; ...

2.3.2. La collection RECORD

Déclarer et définir une collection RECORD

Le type PL/SQL RECORD permet de déclarer un enregistrement PL/SQL pouvant stocker une ligne constituée de colonnes possédant chacune son propre nom et son propre type de données. Ces colonnes sont appelées des champs. Ces champs sont créés lors de la déclaration de l’enregistrement PL/SQL. Avant d'utiliser un enregistrement PL/SQL, il faut d'abord déclarer un type de données RECORD car il n'existe pas de types de données RECORD prédéfinis pour les enregistrements PL/SQL, et ensuite déclarer une variable PL/SQL de ce type. Déclaration d’un type RECORD : TYPE type_record_name IS RECORD ( field_name1 { field_type | variable%TYPE | table.column%TYPE table%ROWTYPE } [NOT NULL { := | DEFAULT} expr], field_name2 { field_type | variable%TYPE | table.column%TYPE }

table%ROWTYPE } [NOT NULL { := | DEFAULT} expr], ...) ;

L’attribut %TYPE peut être utilisé pour définir le type de données des champs. %TYPE peut référencer le type de données d'une variable précédemment déclarée ou le type de données d'une colonne d'une table de base de données. field_type est un type de données PL/SQL (sauf le type REF CURSOR). Un enregistrement peut posséder autant de champs (field_name) que nécessaire.

Déclaration d’un enregistrement du type RECORD : Identifiant type_record_name ; Les champs ne contenant aucune valeur sont initialisée automatiquement à NULL. Les types RECORD et les enregistrements peuvent être définis et déclarés dans la section déclarative d'un bloc, d'un sous-programme ou d'un package. Par exemple :

Une table stocke des données sur les employés, telles que le numéro d'identification (empno), le nom (ename) et la fonction (job) d’un employé. Ces colonnes ne sont pas semblables, mais elles sont logiquement liées. Un enregistrement PL/SQL permet de traiter cet ensemble de champs comme une seule unité logique.

Champ1 (type de données) Champ2 (type de données) Champ3 (type de données) empno emp.empno%TYPE ename emp.ename%TYPE job emp.job%TYPE 7566 JONES MANAGER

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 21: Notions de Base Du PL-SQL

Notions de base du PL/SQL 21 / 63

Cet enregistrement possède trois champs : empno, ename et job. Il s'agit de l'employé numéro 7566 dont le nom est JONES et dont la fonction est MANAGER.

Exemple :

DECLARE TYPE emp_record_type IS RECORD ( empno emp.empno%TYPE NOT NULL :=100, ename emp.ename%TYPE, job emp.job%TYPE ) ; emp_record1 emp_record_type ; emp_record2 emp_record_type ; BEGIN ... END ;

Le type RECORD emp_record_type est composé de trois champs : empno,

ename et job. empno est un champ du même type de données que la colonne EMPNO de la table EMP. ename est un champ du même type de données que la colonne ENAME de la table EMP. job est un champ du même type de données que la colonne JOB de la table EMP. Les variables emp_record et emp_record2 sont ensuite déclarées du type emp_record_type.

Un type RECORD peut être le composant d’un autre type RECORD, c’est à dire être imbriqué dans un autre type RECORD. Exemple :

TYPE time_type IS RECORD ( min SMALLINT, hour SMALLINT ) ; TYPE meeting_type IS RECORD ( day DATE, place CHAR(20), time time_type, purpose CHAR(50)) ;

Le RECORD meeting_type contient un type de données composé, time_type, un

type RECORD déclaré précédemment. La structure d’un enregistrement PL/SQL est semblable à celle d’un enregistrement défini dans un langage de troisième génération (L3G). Par contre, sa structure est différente de celle d’une ligne d’une table de base de données.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Un type RECORD peut contenir un ou plusieurs champs de type RECORD. Les types RECORD peuvent donc être imbriqués.

Page 22: Notions de Base Du PL-SQL

Notions de base du PL/SQL 22 / 63

Déclarer une collection RECORD à l’aide de %ROWTYPE

%ROWTYPE est un attribut utilisé pour déclarer un enregistrement PL/SQL pouvant stocker une ligne entière de données sélectionnée dans une table ou une vue.

identifiant table_name%ROWTYPE ; La structure de l’enregistrement déclaré sera identique à la structure de la table de base de données spécifiée : l'enregistrement possèdera le même nombre de champs avec les mêmes noms et les mêmes types de données que les colonnes de la table. Un enregistrement peut également adopter la structure d'une ligne de données extraites d'un curseur. Grâce à l'attribut %ROWTYPE :

- Il n’est pas nécessaire de connaître le nombre de colonnes et le type de données des colonnes sous-jacentes.

- Le type de données des champs de l’enregistrement sera modifié en conséquence lors de l’exécution et sera automatiquement modifier si le type d'une colonne change.

Cet attribut est utile lors de l’extraction d’une ou plusieurs lignes à l’aide de l’instruction SELECT ou à l’aide d’un curseur explicite. Exemple :

emp_record emp%ROWTYPE;

Grâce à l’attribut %ROWTYPE, la variable emp_record est un enregistrement qui

possède la même structure (même colonnes, même types de données) que la table EMP.

Exemple :

DECLARE emp_rec emp%ROWTYPE; BEGIN SELECT * INTO emp_rec FROM emp WHERE empno = &employee_number; INSERT INTO retired_emps(empno, ename, job, mgr, hiredate, leavedate, sal, comm, deptno) VALUES ( emp_rec.empno, emp_rec.ename, emp_rec.job,

emp_rec.mgr, emp_rec.hiredate, SYSDATE, emp_rec.sal, emp_rec.comm, emp_rec.deptno); COMMIT; END;

Ce bloc recherche dans la table EMP l'employé dont le numéro a été saisi par

l'utilisateur (&employee_number). Les renseignements relatifs à cet employé sont stockés dans un enregistrement PL/SQL emp_rec. Cet enregistrement va servir à insérer l'employé concerné dans la table RETIRED_EMPS.

Référencer et initialiser une collection RECORD

Pour référencer et/ou initialiser un champ dans un enregistrement, il faut utiliser la syntaxe suivante :

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

record_name.field_name

Page 23: Notions de Base Du PL-SQL

Notions de base du PL/SQL 23 / 63

Exemple :

emp_record.job

Cette instruction référence le champ job de l'enregistrement emp_record.

emp_record.job := 'CLERK' ;

Cette instruction affecte la valeur "CLERK" au champ job de l'enregistrement

emp_record. Les instructions SELECT..INTO (§ 3.1.1 Extraction de données à l'aide la clause SELECT..INTO) et FETCH (§ 5.2.3 Extraction de données d'un curseur explicite) permettent d'affecter, en une seule instruction, une valeur à chaque colonne d'un enregistrement. Les noms des colonnes doivent apparaître dans le même ordre que les champs de l'enregistrement Un champ d'un enregistrement peut être assigné à un champ d'un autre enregistrement à condition qu'ils aient le même type de données. Un enregistrement défini par l'utilisateur et un enregistrement défini avec l'attribut %ROWTYPE n'aura jamais le même type de données.

2.3.3. Des collections imbriquées Une table d'enregistrements permet de stocker de façon dynamique des enregistrements dans une table. Une table d'enregistrements est constituée de deux colonnes : une colonne clé primaire et une colonne de type RECORD. Exemple :

Colonne de la table Champ1 de

l'enregistrement Champ2 de

l'enregistrement Champ3 de

l'enregistrement Clé primaire

de la table empno number(4) ename varchar2(10) job varchar2(9)

1 7566 JONES MANAGER 2 7369 SMITH SALESMAN

… … … … Pour référencer un champ dans une table PL/SQL : table(index).field Exemple :

DECLARE TYPE dept_table_type IS TABLE OF dept%ROWTYPE INDEX BY BINARY_INEGER; dept_table dept_table_type; -- each element of dept_table is a record BEGIN dept_table(2).job := 'CLERK'; ... END;

La première instruction de la section exécutable affecte la valeur "CLERK" au

champ job de la ligne indexée à 2 de la table dept_table.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 24: Notions de Base Du PL-SQL

Notions de base du PL/SQL 24 / 63

De la même façon, une collection RECORD peut être imbriquée dans une collection VARRAY (cf Exemple § 2.3.1.3 Définir une collection VARRAY).

2.4. Les variables non-PL/SQL Il existe trois types de variables non-PL/SQL :

- les variables de substitution (cf Module 2 § 4.1 Les variables de substitutions) - les variables définies par l'utilisateur (cf Module 2 § 4.2 Les variables définies par l'utilisateur) - les variables hôte (appelées aussi "bind" variable)

Une variable hôte est une variable déclarée dans l'environnement hôte utilisée pour passer des valeurs, en entrée ou en sortie d'un ou plusieurs programmes PL/SQL. Des ordres PL/SQL peuvent référencer des variables déclarées dans l'environnement hôte sauf si ces ordres se trouvent dans une procédure, une fonction ou un package. Déclarer une variable hôte : VAR[IABLE] variable_name data_type

La longueur de la variable devra être précisé pour les types de chaîne de caractères. Exemple :

SQL> VARIABLE return_code NUMBER SQL> VARIABLE return_msg VARCHAR2(30)

Le SQL et l'environnement SQL*Plus peuvent référencer les variables hôtes. Pour afficher, sous SQL*Plus, toutes les variables hôtes définies et leurs types de données ou le type de données d'une variable hôte donnée: VAR[IABLE] {variable_name} Pour afficher, sous SQL*Plus, la valeur courante de toutes les variables hôtes ou d'une variable hôte donnée : PRI[NT] {variable_name} Pour faire référence à des variables hôtes ou des variables de substitution, vous devez faire précéder les variables hôtes de deux points (:) et les variables de substitution d'un ampersand afin de les distinguer des variables PL/SQL déclarées. :host_variable := expression &substitution_variable := expression Pour les chaînes de caractères : '&substitution_variable' := expression

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 25: Notions de Base Du PL-SQL

Notions de base du PL/SQL 25 / 63

VARIABLE g_monthly_sal NUMBER ACCEPT p_annual_sal PROMPT 'Please enter the annual salary : ' DECLARE v_sal NUMBER(9,2) := &p_annual_sal; BEGIN :g_monthly_sal := v_sal/12; END; / PRINT g_monthly_sal

g_monthly_sal est une variable hôte référencée avec (:). p_annual_sal est une variable de substitution référencée apr (&). A l'exécution du bloc, le moteur PL/SQL demandera la saisie de la variable p_annual_sal. Sa valeur sera divisée par 12, le résultat sera stocké dans la variable g_monthly_sal.

2.5. Traitement des variables et des types de données PL/SQL 2.5.1. Manipulation de valeurs à l’aide d’opérateurs

Il existe quatre types d'opérateurs utilisés en PL/SQL : - les opérateurs logiques - les opérateurs arithmétiques - les opérateurs de concaténations - l'opérateur exponentiel

Les trois premiers types d'opérateurs sont les mêmes qu'en SQL. (cf. cours Oracle SQLP "Module 1 : Ordres SELECT basiques", le paragraphe 2.1.4 "Les expressions arithmétiques", le paragraphe 2.2.2 "L'opérateur de concaténation", le paragraphe 3.2 "Les opérateurs de comparaison", le paragraphe 3.3 "Les opérateurs logiques") Ordre d'évaluation des opérateurs utilisés en PL/SQL:

Opérateurs Opérations ** NOT Exponentiation, négation logique + - Identité, négation * / Multiplication, division + - || Addition, soustraction, concaténation =, !=, <, >, <=, >=, IS NULL, LIKE, BETWEEN, IN Comparaison

AND Conjonction OR Inclusion

Exemple :

DECLARE v_n1 NUMBER := 500; v_n2 NUMBER := 1003; v_value BOOLEAN; v_valid BOOLEAN; BEGIN v_value := (v_n1 = v_n2); v_valid := (v_value IS NOT NULL); END;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 26: Notions de Base Du PL-SQL

Notions de base du PL/SQL 26 / 63

(v_n1 = v_n2) retourne une valeur booléenne affectée à v_value. Si v_value ne contient pas la valeur NULL, alors v_valid contiendra TRUE. Au contraire, si v_value contient la valeur NULL, alors v_valid contiendra FALSE.

Comme dans SQL, l'ordre dans lequel les opérations sont effectuées peut être contrôlé à l'aide de parenthèses.

2.5.2. Manipulation de valeurs à l’aide de fonctions SQL Voici des fonctions SQL valides dans des expressions PL/SQL : - Fonctions mono-ligne alphanumériques :

LOWER(), SUBSTR(), LENGTH()

- Fonctions mono-ligne numériques : ROUND(), TRUNC()...

- Fonctions de conversion de type de données : TO_CHAR(), TO_DATE(), TO_NUMBER()...

- Fonctions portant sur les dates : ADD_MONTH(), ADD_DAY()...

- GREATEST(), LEAST() Les fonctions non disponibles dans les instructions procédurales sont les fonctions de groupe suivantes : AVG(), MIN(), MAX(), COUNT(), SUM(), STDDEV(), VARIANCE(), et la fonction DECODE.

2.5.3. Manipulation de valeurs à l'aide de fonctions PL/SQL P17-8

2.5.4. Conversion de types de données Les variables concaténées dans une expression doivent être du même type de données. Les fonctions de conversion sont utilisées afin d'éviter qu'une expression ne contienne des types de données différents. conversion_function(value,format)

Exemple :

v_comment := USER||':'||TO_CHAR(SYSDATE);

USER est une fonction SQL qui retourne une valeur de type CHAR contenant le

nom de l'utilisateur courant. Cette valeur est concaténée à la chaîne ' ; '. La fonction SYSDATE retourne une valeur de type DATE. Cette valeur est convertie par la fonction TO_CHAR en une valeur de type CHAR. Ainsi, la valeur retournée par la fonction TO_CHAR peut être concaténée au reste de la chaîne. Le résultat de la concaténation est stocké dans la variable v_comment.

2.5.5. Portée des variables et blocs imbriqués L’avantage de PL/SQL par rapport à SQL est la prise en charge des blocs imbriqués. Un bloc peut être imbriqué à n’importe quel endroit où une instruction exécutable est autorisée. Le bloc imbriqué fonctionne comme une instruction. La partie exécutable d’un bloc peut donc être divisée en blocs plus petits.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

La section de traitement des exceptions peut également contenir des blocs imbriqués.

Page 27: Notions de Base Du PL-SQL

Notions de base du PL/SQL 27 / 63

Le fractionnement de la partie exécutable en blocs plus petits facilite la modularisation et la possibilité de réutilisation du code. Le code est ainsi mieux structuré. La portée d’un objet est la partie d’un programme pouvant faire référence à un objet. La portée s’applique à tous les objets déclarés, à savoir les variables, les curseurs, les exceptions définis par l’utilisateur et les constantes. Lorsqu’une variable est déclarée dans un bloc, elle est visible dans le bloc et ses sous blocs imbriqués. Cette règle s'applique à tous les objets : les variables, les curseurs, les exceptions définies par l'utilisateur et les constantes. Exemple :

... x BINARY_INTEGER ; BEGIN ... DECLARE Y NUMBER ; BEGIN ... END ; ... END ;

La section de traitement des exceptions peut contenir des blocs imbriqués. Une variable est également visible pour tous les blocs de la procédure ou de la fonction dans laquelle elle est déclarée. Si un bloc ne trouve pas la variable déclarée localement, il recherche en amont dans la section déclarative des blocs qui l'imbriquent (appelés blocs parents). Le bloc ne recherche jamais en aval dans les blocs imbriqués (appelés blocs enfants).

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Portée de x

Portée de y

Page 28: Notions de Base Du PL-SQL

Notions de base du PL/SQL 28 / 63

3. Intéraction avec le serveur oracle 3.1. Extraction de données

3.1.1. Extraire des données avec l'ordre SELECT…INTO Pour traiter les données stockées dans une table de la base de données, les données doivent d'abord être extraites de la table et ensuite placées dans des variables PL/SQL. Cette opération peut être effectuée facilement à l’aide de l’instruction SELECT..INTO. Cette instruction place les valeurs issues de l'ordre SELECT dans des variables. SELECT select_list INTO { variable_name [variable_name,...] | record_name } FROM table_list[WHERE condition] ;

select_list spécifie la liste des colonnes à extraire d’une table de base de données. Elle peut contenir des expressions SQL, des fonctions de ligne ou des fonctions de groupes. variable_name est une variable scalaire destine à stocker une valeur récupérée par la requête. Les variables booléennes ne sont pas admises. record_name est un enregistrement destiné à stocker toutes les valeurs récupérées par la requête. table_list spécifie la liste des tables intervenant dans la requête. condition est la ou les conditions de la requête qui peuvent être composées de noms de colonnes, d'expressions, de constantes, d'opérateurs de comparaison, des variables et constantes PL/SQL.

La requête ne doit retourner qu'une seule ligne. Si elle ne retourne aucune ligne ou plus d'une ligne, alors une erreur est générée. En PL/SQL, la clause INTO est obligatoire dans l’instruction SELECT. La clause INTO est requise pour le stockage des valeurs extraites dans des variables scalaires (variable_name) ou dans un enregistrement PL/SQL (record_name). En plus de son usage habituel, la clause WHERE peut être aussi utilisée pour spécifier des variables d’entrée, des constantes, des valeurs littérales ou des expressions PL/SQL.

Afin d’éviter des erreurs de syntaxe et les ambiguïtés, certaines règles doivent être respectées lors de l’utilisation de l'ordre SELECT..INTO : - Les colonnes de la base de données et les identifiants, tels que les variables, doivent avoir des

noms différents. - Le nombre de variable dans la clause INTO doit être identique au nombre de colonnes

sélectionnées dans la clause SELECT. Leurs positions doivent correspondre. - Le type de données des identifiants doit correspondre à celui des colonnes. Dans ce cas, l'attribut

%TYPE peut être utile pour assurer la compatibilité des types de données.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 29: Notions de Base Du PL-SQL

Notions de base du PL/SQL 29 / 63

DECLARE v_orderdate ord.orderdate%TYPE; v_shipdate ord.shipdate%TYPE; v_id ord.id%TYPE := 100; BEGIN SELECT orderdate, shipdate INTO v_orderdate, v_shipdate FROM ord WHERE id = v_id ; END ;

Les colonnes date_ordered et date_shipped sont extraites de la table S_ORD et

leurs valeurs sont respectivement placées dans les variables scalaires v_date_ordered et v_date_shipped.

Pour extraire toutes les colonnes d’une ligne appartenant à une table, il faut utilisé un enregistrement PL/SQL dans la clause INTO. Exemple :

DECLARE v_id dept.id%TYPE := 1; dept_record dept%ROWTYPE; BEGIN SELECT * INTO dept_record FROM dept WHERE id = v_id ; END ;

dept_record est un enregistrement dont la structure est identique à la structure

d'une ligne de la table DEPT. L'instruction SELECT..INTO retourne les enregistrements de la table DEPT et les stocke dans l'enregistrement det_record.

3.1.2. Exceptions engendrées par des instructions SELECT..INTO Les erreurs d’exécution dues à des erreurs de codage interrompent le traitement normal. Une erreur provoquant l’arrêt d’un bloc PL/SQL est appelée une exception. Une exception peut également être produite lors de l’extraction de données d’une table de base de données à l’aide de l’instruction SELECT..INTO. L’instruction SELECT ne doit extraire qu'une seule ligne, sinon une exception se produit. Les deux exceptions SELECT pouvant être produites sont :

TOO_MANY_ROWSCette exception se produit lorsque l’instruction SELECT retourne plus d’une ligne. Le serveur Oracle attribue le numéro d’erreur 1422 à cette exception.

NO_DATA_FOUND Cette exception se produit lorsque l’instruction SELECT ne retourne aucune ligne. Le serveur Oracle attribue le numéro d’erreur +1403 à cette exception.

Les exceptions produites peuvent être traitées à l’aide de routines de traitements d’exceptions.

3.2. Manipulation des données 3.2.1. Insertion de données

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

L’instruction INSERT est une commande du langage de manipulation des données. Elle est utilisée pour ajouter de nouvelles lignes dans une table.

Page 30: Notions de Base Du PL-SQL

Notions de base du PL/SQL 30 / 63

INSERT INTO table_name [(column1, column2, ...)] VALUES (variable1, variable2, ...); L'instruction INSERT a le même fonctionnement qu’en SQL. Lors de l’insertion de données dans toutes les colonnes de la ligne, il n’est pas nécessaire de préciser le nom des colonnes. L'instruction INSERT peut utiliser des fonctions SQL, peut générer des valeurs de clé primaire en utilisant des séquences dans la base de données, utiliser des variables définies dans le bloc PL/SQL, ajouter des valeurs de colonne par défaut Exemple :

DECLARE v_ename emp.ename%TYPE := 'LILI' ; v_job emp.job%TYPE := 'TEACHER' ; v_deptno emp.deptno%TYPE := 10 ; BEGIN INSERT INTO emp (empno, ename, job, deptno) VALUES (empno_sequence.NEXTVAL, v_ename, v_job, v_deptno); END ;

La valeur de la clé primaire empno est obtenue à partir de la pseudo colonne

NEXTVAL de la séquence empno_sequence.

3.2.2. Mise à jour des données L’instruction UPDATE modifie les données existantes de la table. Il s’agit d’une instruction du langage de manipulation des données (DML). UPDATE table_name SET colonne = variable [, colonne2 = variable2…] [WHERE condition] ; Exemple :

DECLARE v_sal_increase emp.sal%TYPE := 20; BEGIN UPDATE emp SET sal = sal + v_sal_increase WHERE job = 'ANALYST' ; END ;

Tous les employés de la table EMP dont la fonction est ANALYST voient leur

salaire s'augmenter de $20.

3.2.3. Suppression de données L’instruction DELETE supprime des lignes dans une table. DELETE FROM table_name[WHERE condition] ; Si la clause WHERE est omise, toutes les lignes de la table sont supprimées.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 31: Notions de Base Du PL-SQL

Notions de base du PL/SQL 31 / 63

DECLARE v_deptno emp.deptno%TYPE := 1234; BEGIN DELETE FROM emp WHERE deptno = v_deptno ; END ;

L'employé portant le numéro 1234 est supprimé de la table EMP.

3.3. Curseurs SQL 3.3.1. Les caractéristiques des curseurs SQL

Lorsqu’une commande SQL est exécuté, le serveur Oracle réserve une zone de la mémoire pour l ‘analyse et l’exécution de cette commande. Cette zone est appelé curseur SQL ou curseur implicite. Un curseur SQL ne peut pas être ouvert ou fermé par un programme. PL/SQL traite implicitement le curseur et le ferme, mais ne gère pas l’ouverture du curseur.

3.3.2. Attributs des curseurs SQL Les résultats d’un curseur SQL peuvent être évalués à l’aide d’attributs de curseurs SQL. Il existe quatre attributs des curseurs SQL : SQL%ROWCOUNT Nombre de lignes affectées par la dernière instruction SQL.

SQL%FOUND Retourne TRUE si la dernière instruction SQL a retourné une ou plusieurs lignes.

SQL%NOTFOUND Retourne TRUE si la dernière instruction SQL n’a retourné aucune ligne.

SQL%ISOPEN Détermine si un curseur est ouvert. Il prend toujours la valeur FALSE, car PL/SQL ferme les curseurs implicites immédiatement après leur exécution.

Les attributs des curseurs SQL ne peuvent pas être utilisés dans des ordres SQL; mais ils peuvent être utilisés dans la section de traitement des exceptions d'un bloc PL/SQL. Exemple :

VARIABLE rows_deleted VARCHAR2(30) DECLARE v_ordid NUMBER := 605; BEGIN DELETE FROM item WHERE ordid = v_ordid; : rows_deleted := (SQL%ROWCOUNT || ' rows deleted. '); END; / PRINT rows_deleted

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Tous les enregistrements de la table item dont le numéro de ordid vaut 605 sont effacés de la table. SQL%ROWCOUNT affecte le nombre d'enregistrements effacés à la "bind" variable rows_deleted. Ensuite la valeur de cette variable est affichée avec la commande PRINT.

Page 32: Notions de Base Du PL-SQL

Notions de base du PL/SQL 32 / 63

3.4. Gestion des transactions 3.4.1. Validation des transactions en cours

Toutes les modifications ou transactions en cours apportées aux enregistrements de bases de données sont temporaires, et ne sont pas écrites immédiatement dans la base de données. Ces modifications sont stockées dans une zone de mémoire appelée database buffer cache. La commande SQL COMMIT sert à valider les modifications en cours apportées aux données de la base. La commande SQLCOMMIT confirme la transaction en cours en la rendant permanente dans la base de données. COMMIT [WORK] ; Exemple :

DECLARE v_deptno emp.deptno%TYPE := 50 ; BEGIN DELETE FROM emp WHERE deptno = v_deptno ; COMMIT ; END ;

Les employés appartenant au département n°50 sont supprimés de la table EMP.

La commande COMMIT rend la suppression des lignes permanente. Des commandes explicites de verrouillage, telles LOCK TABLE et SELECT..FOR UPDATE (cf…), peuvent être utilisées dans un bloc. Dans ce cas, le verrouillage prend effet jusqu'à la fin de la transaction. (Attention, un bloc PL/SQL n'implique pas nécessairement une transaction)

3.4.2. Annulation des modifications en attente La commande ROLLBACK permet d’annuler les modifications en attente d'être validées. Grâce à cette commande, les modifications stockées dans la zone de mémoire database buffer cache sont annulées avant la mise à jour de la table. ROLLBACK [WORK] ; Exemple :

DECLARE v_deptno emp.deptno%TYPE := 50 ; BEGIN DELETE FROM emp WHERE deptno = v_deptno ; ROLLBACK ; END ;

Les employés appartenant au département n°50 sont supprimés de la table EMP.

La commande ROLLBACK annule les modifications apportées à la table EMP.

3.4.3. Contrôle des points de transaction La commande SAVEPOINT associée à la commande ROLLBACK permet d’annuler les modifications en attente à partir d’un point donné. Elle est utilisée pour créer un marqueur dans la transaction afin d’enregistrer les modifications jusqu’à un point donné. La commande ROLLBACK est utilisée ultérieurement pour faire référence au marqueur afin d’annuler une partie de la transaction.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 33: Notions de Base Du PL-SQL

Notions de base du PL/SQL 33 / 63

SAVEPOINT marqueur ; ROLLBACK TO SAVEPOINT marqueur ; Exemple :

BEGIN INSERT INTO temp (num_col1, num_col2, char_col) VALUES (1, 1, ‘ROW 1’); SAVEPOINT a; INSERT INTO temp (num_col1, num_col2, char_col) VALUES (2, 1, ‘ROW 2’); SAVEPOINT b; INSERT INTO temp (num_col1, num_col2, char_col) VALUES (3, 1, ‘ROW 3’); SAVEPOIINT c; ROLLBACK TO SAVEPOINT b; END ;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Le troisième ordre INSERT est annulé.

Page 34: Notions de Base Du PL-SQL

Notions de base du PL/SQL 34 / 63

4. Le contrôle des flux dans les blocs PL/SQL

4.1. Le contrôle conditionnel 4.1.1. Les actions à effectuer de façon sélective

Le flux logique des ordres peut être changé en utilisant un ordre conditionnel IF et des structures de contrôle de boucle. Des instructions peuvent être exécutées de façon sélective en fonction d’une condition, à l’aide de l’instruction IF. IF condition THEN statements ; [ELSIF condition THEN statements ; ] [ELSE statements ; ] END IF ;

condition est une variable booléenne ou une expression booléenne associée à une séquence d'ordres qui sont exécutés seulement si le résultat de l'expression ou la variable est vrai. THEN est une clause qui associe la condition qui la précède avec la séquence d'ordres qui la suit. statements : les instructions peuvent être des ordres SQL et PL/SQL. ELSIF est une clause suivie d'une condition. La clause ELSIF est utilisée si la condition précédente est fausse. ESLE est une clause suivie d'une séquence d'ordres. La clause est utilisée si toutes les conditions qui la précèdent sont fausses.

Il existe trois formes d'ordre IF :

- IF-THEN-END IF - IF-THEN-ELSE-END IF - IF-THEN-ELSIF-END IF

La boucle IF-THEN-END IF

IF-THEN-END IF est l'ordre IF simple qui permet d'effectuer des actions sous certaines conditions.

IF condition THEN instructions ; Si la condition booléenne est vraie, la séquence d'ordres associée est exécutée. Si la condition booléenne est fausse ou nulle, la séquence d'ordre associée n'est pas exécutée.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 35: Notions de Base Du PL-SQL

Notions de base du PL/SQL 35 / 63

Figure 3 : Algorithme de l'ordre IF-THEN-END IF

Exemple :

... IF v_ename = 'MILLER' THEN v_job := 'SALESMAN' ; v_deptno := 30 ; v_new_comm := sal * 0.20 ; END IF ; ...

Cette ordre IF attribue la fonction de SALESMAN, le département 35 et une

commission de 20% du salaire actuel si le nom de l'employé est Miller. La boucle IF peut contenir d'autres boucles IF, par exemple : IF condition1 THEN IF condition2 THEN IF condition3 THEN ... END IF; ... END IF; ... END IF;

La boucle IF-THEN-ELSE-END IF

Cette boucle possède une clause ELSE qui permet d'exécuter une séquence d'ordres spécifique si la condition de la boucle est fausse ou nulle. IF condition THEN statements1 ; ELSE Statements2 ; END IF ; Il ne peut y avoir qu'une seule clause ELSE

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 36: Notions de Base Du PL-SQL

Notions de base du PL/SQL 36 / 63

Figure 4 : Algorithme de l'ordre IF-THEN-ELSE-END IF

i la condition booléenne est vraie, la séquence d'ordres associée au IF est exécutée. Si la condition

ne peut y avoir q'une seule clause

xemple :

Sbooléenne est fausse ou nulle, la séquence d'ordre associée à la clause ELSE est exécutée. Il E

... IF v_ename = 'KING' THEN v_job := 'MANAGER'; ELSE v_job := 'CLERK'; END IF; ...

e Manager à l'employé KING et la fonction

out comme les ordres associés à la clause IF, les ordres associés à la clause ELSE peuvent contenir

F condition1 THEN

N ...

... N

...

Cette ordre IF attribue la fonction dClerk aux autres employés.

Tdes ordres IF imbriqués. Par exemple : I ... IF condition2 THE END IF; ... ELSE IF condition2 THE ... ELSE END IF; ...

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

END IF ;

Page 37: Notions de Base Du PL-SQL

Notions de base du PL/SQL 37 / 63

La boucle IF-THEN-ELSIF-END IF

Cette boucle possède une clause ELSIF qui est utilisée pour faciliter l'écriture, en effet une clause ELSIF et équivalente à un ordre IF imbriquée. IF condition1 THEN statements1 ; ELSIF condition2 THEN statements2 ; ELSE Statements4 ; END IF ;

Est equivalent à :

IF condition1 THEN statements1 ; ELSE IF condition2 THEN statements3 ; ELSE statements4 ; END IF; END IF ;

Figure 5 : Algorithme de l'ordre IF-THEN-ELSIF-END IF

Une instruction IF peut contenir plusieurs clauses ELSIF mais qu'une seule clause ELSE.

Exemple :

... IF v_deptno = 10 THEN v_comm := 5000 ; ELSIF v_deptno = 20 THEN v_comm := 7500 ; ELSIF v_deptno = 30 THEN v_comm := 3000; ELSE v_comm := 2000 ; END IF; ...

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 38: Notions de Base Du PL-SQL

Notions de base du PL/SQL 38 / 63

Cette ordre IF attribue une commission de $5000 aux employés du département 10, une commission de $7500 aux employés du département 20 et une commission de $2000 aux autres employés.

La syntaxe de l’instruction IF est dictée par deux règles :

- le mot clé ELSIF représente un seul mot et le mot clé END IF est composé de deux mots, - l’instruction IF peut comporter plusieurs clauses ELSIF mais uniquement une seule clause

ELSE. Remarque : l'ordre GOTO p19-3

4.1.2. Les conditions booléennes Les conditions booléennes peuvent être simples ou complexes. Une condition booléenne simple est la combinaison d'expressions avec un opérateur de comparaison. Exemple :

v_sal > 1000

v_sal = (v_comm * 4)

Une condition booléenne complexe est la combinaison de plusieurs conditions simples avec des opérateurs logiques tels que AND, OR et NOT. Exemple :

(v_sal > 1000) AND (v_sal = (v_comm * 4))

v_result := (v_tag1 AND v_tag2)

AND TRUE FALSE NULLTRUE TRUE FALSE NULL

FALSE FALSE FALSE FALSENULL NULL FALSE NULL

v_result := (v_tag1 OR v_tag2)

OR TRUE FALSE NULLTRUE TRUE TRUE TRUE

FALSE TRUE FALSE NULLNULL TRUE NULL NULL

v_result := (NOT v_tag1) L’opérateur NOT opère sur une condition unique

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

NOTTRUE FALSE

FALSE TRUENULL NOT NULL

Page 39: Notions de Base Du PL-SQL

Notions de base du PL/SQL 39 / 63

4.2. Les structures des boucles : le contrôle itératif 4.2.1. La boucle élémentaire LOOP

Les instructions de contrôle itératif sont utilisées pour exécuter plusieurs fois une instruction ou une séquence d’instructions. La boucle élémentaire est constituée d’un ensemble d’instructions incluses entre les délimiteurs LOOP et END LOOP. Ces instructions sont exécutées de façon répétée. LOOP statement1 ; statement2 ; … statementN ; END LOOP ; A chaque fois que le flux de l’exécution rencontre l’instruction END LOOP, le contrôle est renvoyé à la première instruction de la boucle. Sous cette forme, la boucle élémentaire est infinie. L’instruction EXIT permet de sortir de la boucle. L'instruction EXIT peut être utilisée en tant qu’action dans une instruction IF, ou comme instruction autonome dans la boucle. EXIT en tant qu'action dans une instruction IF :

LOOP statement1 ; statement2 ; … statementN ; IF condition THEN EXIT ; END LOOP ;

EXIT en tant qu'instruction autonome dans la boucle : LOOP statement1 ; statement2 ; … statementN ; EXIT [WHEN condition] ; END LOOP ;

Dans le cas où l'instruction EXIT est utilisée comme une instruction autonome, la condition de la clause WHEN doit être une variable booléenne ou une expression retournant une valeur booléenne. Une boucle LOOP peut contenir plusieurs conditions de sortie.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 40: Notions de Base Du PL-SQL

Notions de base du PL/SQL 40 / 63

Figure 6 : Algorithme du boucle LOOP avec une condition de sortie

La boucle s'arrête lorsque la condition de sortie est vraie. Si la condition est placée à la fin de la boucle, les instructions seront exécutées au moins une fois. Si la condition est placée au début de la boucle et que cette condition est vraie, alors aucunes instructions associées à la boucle n'est exécutées.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 41: Notions de Base Du PL-SQL

Notions de base du PL/SQL 41 / 63

Exemple :

DECLARE v_ordid item.ordid%TYPE := 601 ; v_counter NUMBER(2) := 1 ; BEGIN LOOP INSERT INTO item (ordid, itemid) VALUES (v_ordid, v_counter); V_counter := v_counter + 1 ; EXIT WHEN v_counter > 10 ; END LOOP; END;

Ce bloc permet d'insérer les dix lignes dans la table ITEM dont les identifiant des

lignes insérées vont de 1 à 10 et dont le numéro d'ordre est de 601 pour chaque ligne insérée.

4.2.2. La boucle FOR..LOOP La boucle FOR est un mécanisme permettant d’exécuter un ensemble d’instructions un certain nombre de fois dans une boucle. La boucle FOR..LOOP a la même structure générale que la boucle basique LOOP. FOR..LOOP possède, en plus, un ordre de contrôle placé avant le mot clé LOOP qui détermine le nombre d'itération que PL/SQL doit effectuer. FOR index IN [REVERSE] lower_limit..higher_limit LOOP statements ; END LOOP ;

REVERSE déclenche une décrémentation (au lieu d'une incrémentation) du compteur (index) de 1 à chaque itération de la boucle jusqu'à ce que la limite inférieure soit atteinte.

Le compteur (index) est déclaré, initialisé et incrémenté (ou décrémenté) implicitement. Lorsque le contrôle entre dans la boucle, les limites inférieures (lower_limit) et supérieure (lower_limit) sont utilisées pour déterminer le nombre d’exécutions de la boucle. Si la valeur de la limite supérieure est inférieure à la valeur de la limite inférieure, la boucle ne s’exécute pas. Les règles à respecter concernant l’utilisation de la boucle FOR :

- Ne faire référence à l’index qu’à l’intérieur de la boucle, car il n’est pas défini en dehors de celle-ci.

- Les références à la valeur existante d’un index doivent être effectuées dans une expression. La valeur précédente d’un index ne peut pas être référencée.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

- La référence à l’index ne peut pas être une cible d’affectation. index := value ; code non valide

Page 42: Notions de Base Du PL-SQL

Notions de base du PL/SQL 42 / 63

Figure 7 : Algorithme de la boucle FOR

Exemple :

DECLARE v_ordid item.ordid%TYPE := 601; BEGIN FOR i IN 1..10 LOOP INSERT INTO item(ordid,itemid) VALUES(v_ordid,i); END LOOP ; END ;

Ce bloc insère dans la table ITEM dix nouvelles lignes dont l'identifiant correspond

à l'index de la boucle i, et dont le numéro d'ordre est 601.

4.2.3. La boucle WHILE..LOOP La boucle WHILE exécute des instructions tant que sa condition est vraie. WHILE condition LOOP statement1 ; statement2 ; … statementN ; END LOOP ; La condition est évaluée au démarrage de chaque itération. La boucle se termine lorsque la condition est fausse. Si la condition est fausse au démarrage de la première itération, aucune itération n’a lieu et le contrôle sort de la boucle. Si la condition est nulle, la séquence d'instructions de la boucle n'est pas exécutée et le contrôle passe à l'ordre suivant : l'instruction END LOOP. La boucle WHILE peut posséder un compteur (un index) explicite. La condition de la boucle WHILE peut être altérée par les instructions de la boucle.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 43: Notions de Base Du PL-SQL

Notions de base du PL/SQL 43 / 63

Figure 8 : Algorithme de la boucle WHILE

Exemple :

ACCEPT p_new_order PROMPT 'Enter the order number : ' ACCEPT p_item PROMPT 'Enter the number of items in this order : ' DECLARE v_count NUMBER(2) := 1; BEGIN WHILE v_count <= &p_items LOOP INSERT INTO item (ord_id, item_id) VALUES (v&p_new_order, v_count); v_count := v_count+1; END LOOP; END ;

L'utilisateur saisit le numéro d'ordre (p_new_order) et un nombre de lignes à

insérer pour ce numéro d'ordre (p_item). La boucle WHILE insère le nombre de ligne défini par l'utilisateur (p_item). Ces lignes insérées auront pour identifiant la valeur courante de v_count et pour numéro d'ordre p_new_order. Les insertions dans la table s'arrêtent lorsque le compteur v_count est supérieur à p_item.

4.2.4. Les boucles imbriquées Une boucle imbriquée est une boucle intégrée dans une autre. La boucle contenant une autre boucle est appelée boucle externe. La boucle imbriquée est appelée boucle interne. Les boucles peuvent être imbriquées à plusieurs niveaux. Les boucles FOR peuvent être imbriquées dans des boucles WHILE et inversement. La fin d’une boucle imbriquée ne provoque pas l’arrêt de la boucle externe, sauf si une exception est levée. Les étiquettes permettent de sortir d’une boucle externe en fonction de la valeur d’une boucle interne. Une étiquette est un identifiant déclaré qui désigne de façon facultative une instruction ou un bloc vers lequel le contrôle doit être transféré.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 44: Notions de Base Du PL-SQL

Notions de base du PL/SQL 44 / 63

<<outer>>LOOP … LOOP … EXIT outer WHEN … END LOOP ; … END LOOP outer ;

L'instruction EXIT provoque la sortie de la boucle outer, donc des deux boucles à la fois.

La précision d'un label dans la clause END LOOP est facultative et est utilisée pour clarifier le code. Exemple :

... BEGIN <<outer_loop>> LOOP v_counter := v_counter + 1 ; EXIT WHEN v_counter > 10 ; <<inner_loop>> LOOP ... EXIT outer_loop WHEN total_done = 'YES'; -- leave both loops EXIT WHEN inner_done = 'YES'; -- leave inner loop only ... END LOOP inner_loop; ... END LOOP outer_loop; END;

Ce bloc possède deux boucles. La boucle externe est identifiée par le label

outer_loop, la boucle interne est identifiée par le label inner_loop. La boucle interne est imbriquée dans la boucle externe. Les noms des labels sont inclus dans l'ordre END LOOP pour des raisons de clarté.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 45: Notions de Base Du PL-SQL

Notions de base du PL/SQL 45 / 63

5. Les curseurs explicites 5.1. Introduction sur les curseurs

5.1.1. Types de curseur Les curseurs permettent de nommer des zones de mémoire SQL privée et d’accéder ainsi aux informations qui y sont stockées lors de l’exécution d’une instruction SQL. Il existe deux types de curseurs : les curseurs implicites (ou curseurs SQL) et explicites. Les curseurs implicites et explicites réalisent la même fonction, à savoir la fourniture d’espace mémoire pour le traitement des lignes. La différence entre eux réside dans la façon dont ils sont déclarés : - Un curseur implicite est automatiquement (implicitement) déclaré par PL/SQL lors de l'exécution

d'instructions PL/SQL et DML (telles que INSERT, UPDATE et DELETE). - Un curseur explicite est déclaré et nommé par le programmeur. Les curseurs explicites sont

manipulés grâce à des instructions spécifiques dans la section exécutable d'un bloc.

L’avantage de la création d’un curseur explicite est de pouvoir l’utiliser pour traiter plusieurs ensembles de résultats de lignes. Le traitement dans un curseur explicite se fait ligne par ligne au-delà de la première ligne renvoyée par la requête.

5.1.2. Les caractéristiques des curseurs explicites Les curseurs explicites sont déclarés par l’utilisateur et sont utilisés pour traiter les résultats d’une requête qui retournent plusieurs lignes. L'instruction SELECT..INTO ne doit retourner qu'une seule ligne. Un curseur explicite permet de gérer des requêtes retournant plusieurs lignes et de traiter chaque ligne individuellement. Les lignes renvoyées par une requête sont appelées ensemble actif. PL/SQL définit automatiquement la taille du curseur en fonction de la taille de l’ensemble actif. Un curseur explicite possède un pointeur inhérent qui enregistre la ligne courante (actuellement en cours de traitement) de l’ensemble actif. Les curseurs explicites peuvent être contrôlés manuellement par le programmeur.

5.1.3. Contrôle des curseurs explicites Le contrôle d’un curseur est le processus de création et d’utilisation d’un curseur. Le contrôle des curseurs a lieu en quatre étapes :

- Déclaration du curseur : Un curseur explicite est déclaré en le nommant et en définissant la structure de la requête dont il stockera le résultat.

- Ouverture du curseur :

L’instruction OPEN est utilisée pour ouvrir un curseur explicite. L’instruction exécute la requête et identifie l’ensemble actif (résultat de la requête).

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

- Accès aux données du curseur : Une fois un curseur explicite déclaré et ouvert, le résultat de la requête du curseur peut être accédé. L’instruction FETCH est utilisée pour extraire une ligne à la fois de l’ensemble actif.

Page 46: Notions de Base Du PL-SQL

Notions de base du PL/SQL 46 / 63

Elle charge la ligne actuelle du curseur dans les variables. Pour accéder à une ligne à la fois, l’extraction doit être effectuée à l'intérieure d'une boucle.

- Fermeture du curseur : L’instruction CLOSE permet de fermer un curseur explicite. L’instruction CLOSE libère l’ensemble actif du curseur.

Figure 9 : Le contrôle des curseurs explicites à l'aide de quatre commandes

5.2. Utilisation des curseurs explicites 5.2.1. Déclaration des curseurs explicites

Un curseur est déclaré dans la section déclarative à l’aide de l’instruction CURSOR. CURSOR cursor_name IS Select_statement ; Un curseur doit être déclaré, nommé et associé à une requête. La requête peut contenir des variables préalablement déclarées, mais en aucun cas de clause INTO. Exemple :

DECLARE CURSOR emp_cursor IS SELECT empno, sal * 10 FROM emp; CURSOR dept_cursor IS SELECT * FROM dept WHERE deptno = 10 ; BEGIN ... END ;

Le curseur explicite nommé emp_cursor stocke les valeurs du champ empno de

la table EMP et le résultat de la multiplication du champ sal de la table EMP par 10. Le curseur explicite nommé dept_cursor stocke les enregistrements de la table DEPT dont le numéro de département est 10.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 47: Notions de Base Du PL-SQL

Notions de base du PL/SQL 47 / 63

5.2.2. Ouverture des curseurs explicites L’ouverture d’un curseur exécute la requête associée au curseur et identifie l'ensemble actif. OPEN cursor_name ; L’instruction OPEN :

- alloue de façon dynamique de la mémoire pour une zone de contexte destinée à contenir les informations de traitement.

- parse la requête associée au curseur. - "binds" les variables en entrée. - identifie l'ensemble actif. - positionne le pointeur juste avant la première ligne du curseur.

Si le curseur est déclaré avec la clause FOR UPDATE, l'ordre OPEN verrouille les lignes retournées par la requête.

5.2.3. Extraction de données d’un curseur explicite L’instruction FETCH est utilisée pour extraire une par une les lignes de l'ensemble actif. FETCH cursor_name INTO {variable1 [,variable2…] | record_name} :

La clause INTO contient les noms des variables ou le nom d'un enregistrement PL/SQL dans lequel les données de l'ensemble actif seront stockées pour permettre le traitement.

L’instruction FETCH :

- avance le pointeur à la prochaine ligne de l'ensemble actif. - lit les données de la ligne courante de l'ensemble actif. - extrait les valeurs de la ligne actuelle et les places dans les variables de la clause INTO.

Le nombre de variables à déclarer dépend du nombre de champs retournés par l'ordre FETCH. La clause INTO de l’instruction FETCH autant de variables qu'il y a de colonnes dans la clause SELECT de la requête associée au curseur. Pour chaque valeur de colonne retournée par la requête associée au curseur, il doit y avoir une variable qui lui correspond dans la clause INTO. Les types de données des variables doivent être compatibles aux types de données des colonnes qui leur correspondent. Le pointeur du curseur avance jusqu’à la ligne suivante à chaque exécution de la commande FETCH. Exemple :

DECLARE v_empno emp.empno%TYPE; v_ename emp.ename%TYPE; CURSOR emp_cursor IS SELECT empno, ename FROM emp; BEGIN OPEN emp_cursor; FOR i IN 1..10 LOOP FETCH emp_cursor INTO v_empno, v_ename; ... END LOOP; ... END ;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 48: Notions de Base Du PL-SQL

Notions de base du PL/SQL 48 / 63

Le curseur emp_cursor sélectionne tous les numéros et noms des employés de la table EMP. La boucle FOR et l'instruction FETCH permettent de récupérer un par un les dix premiers employés sélectionnés par le curseur.

Si une instruction FECTH ne retourne aucune valeur, aucune erreur n'est retournée. C'est pourquoi le statut du curseur doit être contrôlé à l'aide d'attributs (paragraphe 5.3 Les attributs des curseurs explicites).

5.2.4. Fermeture d’un curseur L'instruction CLOSE est utilisée pour fermer le curseur. CLOSE cursor_name ; L'instruction CLOSE :

- désactive le curseur (l'ensemble actif devient indéfini). - libère des ressources pouvant être utilisées pour l’extraction d’autres tâches.

Bien qu’il soit possible de terminer le bloc PL/SQL sans fermer le curseur, il est préférable de le fermer explicitement. De plus, le nombre de curseurs ouverts pour chaque utilisateur est limité par le paramètre de base de données OPEN_CURSORS qui vaut, par défaut, 50. L’accès aux données n’est plus possible après la fermeture d’un curseur. Si une tentative d’accès aux données à partir d’un curseur fermé est effectuée, une exception INVALID_CURSOR est levée. Exemple :

... BEGIN OPEN emp_cursor; FOR i IN 1..10 LOOP FETCH emp_cursor INTO v_empno, v_ename; ... END LOOP; CLOSE emp_cursor; END ;

Le curseur emp_cursor est ouvert. Les dix premières lignes de l'ensemble actif de

emp_cursor sont traitées une par une. emp_cursor est fermé lorsque son traitement est terminé (en dehors de la boucle).

5.3. Les attributs des curseurs explicites Comme dans le cas des curseurs implicites, quatre attributs permettent d’obtenir les informations relatives à l’état d’un curseur explicite : %ISOPEN, %FOUND, %NOTFOUND et%ROWCOUNT. Ces attributs ne peuvent pas être utilisés dans des ordres SQL.

5.3.1. Contrôle de l’état à l’aide de l’attribut %ISOPEN L’attribut %ISOPEN est un attribut booléen qui prend la valeur TRUE si le curseur est ouvert. Si FALSE est le résultat de l’attribut %ISOPEN, le curseur peut être ouvert. L’ajout du mot clé NOT inverse la condition.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

cursor_name%ISOPEN

Page 49: Notions de Base Du PL-SQL

Notions de base du PL/SQL 49 / 63

NOT cursor_name%ISOPEN Exemple :

BEGIN ... IF NOT emp_cursor%ISOPEN THEN OPEN emp_cursor ; END IF ; LOOP FETCH emp_cursor ... END LOOP; CLOSE item_cursor ; ... END ;

L'instruction IF ouvre le curseur emp_cursor si ce dernier est fermé afin que

l'instruction FETCH qui suit n'échoue pas.

5.3.2. Contrôle de l’état à l’aide de l’attribut %FOUND %FOUND est un attribut de type booléen qui prend la valeur TRUE si l’opération d’accès la plus récente a renvoyé une ligne. Lorsque aucune ligne n’est renvoyée, l’attribut prend la valeur FALSE. cursor_name%FOUND Exemple :

… BEGIN OPEN emp_cursor ; FETCH emp_cursor INTO v_empno, v_ename ; WHILE emp_cursor%FOUND LOOP INSERT INTO emp2 VALUES (v_empno, v_ename) ; FETCH emp_cursor INTO v_empno, v_ename ; END LOOP ; END ;

Ce bloc insère les valeurs du curseur dans la table EMP2 tant que le pointeur du

curseur n'est pas arrivé à la fin de l'ensemble actif. Le contrôle de l’état d’un curseur à l’aide de l’attribut %FOUND permet d'assurer que le curseur contient toujours des données à traiter.

5.3.3. Sortie d’une boucle à l’aide de l’attribut %NOTFOUND %NOTFOUND est un attribut booléen qui prend la valeur TRUE si l’opération d’accès la plus récente ne renvoie aucune ligne. Si une ligne est renvoyée, l’attribut prend la valeur FALSE. cursor_name%NOTFOUND Avant le premier ordre FETCH, l'attribut %NOTFOUND est évalué à NULL.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 50: Notions de Base Du PL-SQL

Notions de base du PL/SQL 50 / 63

… BEGIN OPEN emp_cursor ; LOOP FETCH emp_cursor INTO v_empno, v_ename; EXIT WHEN emp_cursor%NOTFOUND OR emp_cursor%NOTFOUNT IS NULL; END LOOP ; END ;

La boucle LOOP et l'instruction FETCH permettent d'extraire les lignes de

l'ensemble actif de emp_cursor jusqu'à ce que plus aucunes lignes ne soit trouvées.

5.3.4. Nombre de lignes renvoyées à l’aide de %ROWCOUNT %ROWCOUNT est un attribut numérique qui prend la valeur du nombre total de lignes accédées jusqu’alors dans une boucle. cursor_name%ROWCOUNT Exemple :

… BEGIN OPEN emp_cursor ; LOOP FETCH emp_cursor INTO v_empno, v_ename ; EXIT WHEN emp_cursor%ROWCOUNT > 5 ; END LOOP ; END ;

La boucle LOOP et l'instruction FETCH permettent d'extraire les cinq premières

lignes de l'ensemble actif de emp_cursor.

5.4. Utilisation avancée des curseurs explicites 5.4.1. Extraction de lignes à l’aide de la boucle de curseur FOR

La boucle de curseur FOR permet d'extraire et de traiter une par une les lignes de l'ensemble actif. FOR record_name IN cursor_name LOOP statements ; END LOOP ; La boucle de curseur FOR ouvre et ferme automatiquement le curseur. De plus, il n’est plus nécessaire de déclarer l'enregistrement PL/SQL contrôlant la boucle (record_name) , celui-ci est déclaré implicitement par le boucle de curseur FOR. Une boucle de curseur FOR sélectionne une plage de lignes d’une table de base de données, puis extrait chaque ligne de cette plage. Cette procédure est différente de la boucle FOR classique (appelée boucle FOR numérique), dans laquelle une plage de valeurs numériques est spécifiée, puis chaque valeur de cette plage est traitée. Les paramètres d’un curseur peuvent être spécifiés entre parenthèses après le nom du curseur dans l’instruction FOR.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

La boucle de curseur FOR ne doit pas être utilisée lorsque les opérations sont traitées manuellement.

Page 51: Notions de Base Du PL-SQL

Notions de base du PL/SQL 51 / 63

Exemple :

SET SERVEROUTPUT ON DECLARE CURSOR emp_cursor IS SELECT ename, deptno FROM emp ; BEGIN FOR emp_record IN emp_cursor -- implicit open and implicit fetch LOOP IF emp_record.deptno = 30 THEN DBMS_OUTPUT.PUT_LINE ('Employee '|| emp_record.ename || ' works in the Sales Dept.'); -- display END IF; END LOOP ; -- implicit close cursor END ;

La boucle FOR extrait une par une les lignes de l'ensemble actif de emp_cursor.

Chaque ligne est stockée dans l'enregistrement emp_record, implicitement déclaré. Si la valeur du champ deptno de emp_record vaut 30, alors s'affiche à l'écran "Employee [emp_record.ename] works in the Sales Dept." où emp_record.ename est le nom de l'employé stocké dans l'enregistrement.

5.4.2. La boucle de curseur FOR avec une sous-requête Une requête peut être définie au début de la boucle. La requête est appelée un sous-ordre SELECT ou une sous-requête, le curseur est interne à la boucle FOR et ne possède donc pas de nom. Les attributs ne peuvent pas être testés sur ce type de curseur, car il ne possède pas de nom. FOR record_name IN (select_statement) LOOP statements ; END LOOP ; Exemple :

BEGIN FOR emp_record IN (SELECT ename, deptno FROM emp) LOOP IF emp_record.deptno = 30 THEN ... END IF; END LOOP; END;

5.4.3. Verrouiller et mettre à jour les lignes d'un curseur La clause WHERE CURRENT OF permet de mettre à jour ou de supprimer la dernière ligne accédée (la ligne courante) d'un curseur. Cette clause est utilisée dans les ordres SQL UPDATE et DELETE dans la section exécutable. WHERE CURRENT OF cursor_name Le curseur auquel WHERE CURRENT OF fait référence doit exister, sinon une erreur sera générée.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Lors de l’utilisation de la clause WHERE CURRENT OF dans un ordre SQL, il est nécessaire d’utiliser la clause FOR UPDATE dans la requête du curseur. La clause FOR UPDATE verrouille

Page 52: Notions de Base Du PL-SQL

Notions de base du PL/SQL 52 / 63

toutes les lignes identifiées par la requête du curseur. Le verrouillage de la ligne permet de garantir qu’elle ne sera pas traitée par d’autres utilisateurs lors de sa mise à jour ou de sa suppression. CURSOR cursor_name IS SELECT select_list FROM table_list [WHERE condition] FOR UPDATE [OF column_reference] [NOWAIT] ;

column_reference précise la colonne de la table dont les valeurs sélectionnées par la requête sont à verrouiller. (Il peut s'agir d'une liste de colonnes) Le mot clé NOWAIT permet de retourner une erreur Oracle si le verrou porte sur des lignes déjà verrouillées par une autre session.

La clause FOR UPDATE est la dernière clause d'un ordre SELECT. Un curseur possédant la clause FOR UPDATE ne peut plus être interroger après validation. Dans le cas d'une grosse mise à jour sur une grosse table, tous les enregistrements peuvent être verrouillés avec l'ordre LOCK TABLE. Si l'ordre LOCK TABLE est utilisé, la clause WHERE CURRENT OF ne peut pas être utilisée. Il faut utiliser la clause traditionnelle WHERE column = identifier. Exemple :

PROCEDURE ma_procedure IS CURSOR emp_cursor IS SELECT id, salary, start_date FROM s_emp WHERE dept_id = 41 FOR UPDATE OF salary ; BEGIN FOR emp_record IN emp_cursor LOOP UPDATE s_emp SET salary = salary * 2 ; WHERE CURRENT OF emp_cursor; END LOOP ; COMMIT ; END ;

WHERE CURRENT OF permet de mettre à jour la dernière ligne accédée dans le

curseur emp_cursor.

5.4.4. Déclaration de curseurs explicites avec des paramètres Il est possible d’utiliser le même curseur dans différentes situations et d’extraire des données différentes chaque fois. Pour cela, des paramètres sont passés au curseur autorisant ainsi l’exécution de la requête pour différentes valeurs. Un curseur avec des paramètres aboutit à des ensembles actifs différents suivant les paramètres passés au curseur. CURSOR cursor_name [(parameter [IN] datatype [{:= | DEFAULT} expr, …)] IS

select_statement ; Le nom du paramètre doit être suivi d’un type de données scalaire. La taille des données des paramètres ne doit pas être spécifiée. Les valeurs des paramètres sont transmises au curseur lors de son ouverture. Ces valeurs sont utilisées dans la requête du curseur lors de son exécution. OPEN cursor_name (value,...) Ou

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Page 53: Notions de Base Du PL-SQL

Notions de base du PL/SQL 53 / 63

FOR record_name IN cursor_name(value,...) LOOP ... END LOOP; Exemple :

DECLARE CURSOR emp_cursor ( p_job emp.job%TYPE, p_deptno emp.deptno%TYPE) IS SELECT ename, empno, hiredate FROM emp WHERE deptno= p_deptno AND job = p_job ; BEGIN OPEN emp_cursor('ANALYST',20); ... END ;

Le curseur prend en paramètre deux variables scalaires p_job et p_deptno. Le

curseur sélectionne les enregistrements relatifs aux employés exerçant la fonction ANALYST passée en paramètre au curseur et travaillant dans le département 20 également passé en paramètre.

5.4.5. Des curseurs avec des sous-requêtes La requête associée à un curseur peut être composée, tout comme une requête traditionnelle, d'une ou plusieurs sous-requêtes. (cf Module 2 : Récupération de données …) Exemple :

DECLARE CURSOR my_cursor IS SELECT t1.deptno, t1.dname, t2.STAFF FROM dept t1, ( SELECT deptno, COUNT(*) STAFF FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

END t2.STAFF >= 5 ;

Page 54: Notions de Base Du PL-SQL

Notions de base du PL/SQL 54 / 63

6. Gestion des exceptions 6.1. Introduction sur les exceptions

Une exception est un identificateur ("identifier") en PL/SQL qui est levée durant l'exception. Lorsqu'une exception survient dans la section des commandes exécutables, le contrôle de l'exécution quitte immédiatement cette section et recherche dans la section de gestion des exceptions une exception correspondant à l'erreur rencontrée.

6.1.1. Lever et traiter les exceptions Il existe deux façons de lever une exception :

- Une erreur Oracle survient et l'exception associée est automatiquement levée. Par exemple, si aucune ligne n'est retournée dans un ordre SELECT, l'erreur ORA-01403 survient, alors le langage PL/SQL lève l'exception NO_DATA_FOUND.

- Le programmeur lève une exception explicitement en utilisant l'ordre RAISE dans un bloc. L'exception levée doit être une exception définie par le développeur ou une exception prédéfinie.

- Il existe deux façons de traiter une exception :

- L'attraper (la capturer) avec un traitement ("handler"). - La propager dans l'environnement.

Si une exception est levée dans la section exécutable d'un bloc, l'exécution du bloc rejoint ("branches") le traitement correspondant à l'exception dans la section de gestion des exceptions du bloc. Si le moteur PL/SQL traite avec succès l'exception, alors l'exception n'est pas propagée au bloc "père" ni à l'environnement. Dans ce cas, le bloc PL/SQL se termine alors avec succès. Si une exception est levée dans la section exécutable d'un bloc et qu'il n'existe pas de traitement pour cette exception. Le bloc PL/SQL se termine avec une erreur d'exécution ("failure") et l'exception est propagée dans l'environnement.

6.1.2. Les types d'exception Il existe trois types d'exception :

- Les erreurs du serveur Oracle prédéfinies - Les erreurs du serveur Oracle non prédéfinies - Les erreurs définies par le développeur

Les erreurs du serveur Oracle prédéfinies correspondent approximativement aux 20 erreurs qui apparaissent le plus souvent dans un bloc PL/SQL. Elles ne sont pas déclarées et sont levées automatiquement par le serveur Oracle. Les erreurs du serveur Oracle non prédéfinies correspondent à toutes les autres erreurs standard qui peuvent apparaître dans un bloc PL/SQL. Elles sont déclarées dans la section déclarative et sont automatiquement levées par le serveur Oracle. Les erreurs définies par l'utilisateur correspondent à des conditions que le développeur a jugé anormales. Elles sont déclarées dans la section déclarative et sont levées explicitement par le développeur dans la section exécutive.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Note : Des applications avec des clients PL/SQL, tel que Oracle Developer Forms, possèdent leurs propres exceptions.

Page 55: Notions de Base Du PL-SQL

Notions de base du PL/SQL 55 / 63

6.2. Capturer les exceptions 6.2.1. Capturer les exceptions

Le développeur peut capturer n'importe quel erreur en incluant une routine correspondante dans la section de gestion des exceptions d'un bloc PL/SQL. Chaque section de traitement (appelé "handler") est constitué d'une clause WHEN qui spécifie une exception, suivie d'une séquence d'ordres exécutée lorsque l'exception est levée. Syntaxe : EXCEPTION WHEN exception1 [OR exception2...] THEN statement1; statement2; ... [WHEN exception3 [OR exception4...] THEN statement1; statement2; ...] [WHEN OTHERS THEN statement1; statement2; ...]

exception représente le nom standard d'une exception prédéfinie ou le nom d'une exception définie par le développeur déclarée dans la section déclarative. statement représente un ou plusieurs ordres SQL ou PL/SQL. OTHERS est une clause optionnelle dans la gestion des exceptions qui capture les exceptions non spécifiées dans les clauses WHEN précédentes. Cette clause doit être la dernière zone de traitement d'exception et ne doit apparaître qu'une seule fois. (Certains outils d'Oracle possèdent leurs propres exceptions qui peuvent être soulevées. La clause OTHERS peut capturer ces exceptions).

6.2.2. Capturer des erreurs prédéfinies du serveur Oracle Pour capturer une erreur prédéfinie par le serveur Oracle, son nom doit être référencé dans la routine de traitement des exceptions. Exemple :

BEGIN EXCEPTION WHEN NO_DATA_FOUND THEN statement1; statement2; WHEN TOO_MANY_ROWS THEN statement1; WHEN OTHERS THEN statement1; statement2; statement3;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

END;

Page 56: Notions de Base Du PL-SQL

Notions de base du PL/SQL 56 / 63

Tableaux des exceptions prédéfinies :

Nom de l'exception

Numéro de l'erreur du

serveur Oracle

Description

ACCESS_INTO_NULL ORA-06530 Des valeurs ont essayé d'être assignées à des attributs d'un objet non initialisé

COLLECTION_IS_NULL ORA-06531 Des méthodes autres que EXISTS ont essayé d'être appliquées à un tableau ou une table imbriquée.

CURSOR_ALREADY_OPEN ORA-06511 Un curseur a essayé d'être ouvert. DUP_VAL_ON_INDEX ORA-00001 Une valeur existante a essayé d'être insérée. INVALID_CURSOR ORA-01001 L'opération sur un curseur illégale s'est produite. INVALID_NUMBER ORA-01722 La conversion de chaînes de caractères en nombre

a échoué. LOGIN_DENIED ORA-01017 La connexion à Oracle a été réalisé avec un nom

d'utilisateur invalide ou un mot de passe. NO_DATA_FOUND ORA-01403 Un ordre SELECT ne retourne aucune donnée. NOT_LOGGED_ON ORA-01012 Un programme PL/SQL interroge une base de

données sans être connecté à Oracle. PROGRAM_ERROR ORA-06501 Le moteur PL/SQL a un problème interne. ROWTYPE_MISMATCH ORA-06504 La variable d'un curseur hôte et la variable d'un

curseur invoquées dans un assignement ont des types de données retournés invalides.

STORAGE_ERROR ORA-06500 Il n'y a pas assez de mémoire pour le moteur PL/SQL ou la mémoire est corrompu.

SUBSCRIPT_BEYOND_COUNT ORA-06533 L'élément d'une table imbriquée ou d'un tableau a été référencé en utilisant un numéro d'index plus grand que le nombre d'éléments contenu dans la collection.

SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 L'élément d'une table imbriquée ou d'un tableau a été référencé en utilisant un numéro d'index qui est en dehors des limites légales (-1 par exemple).

TIMEOUT_ON_RESSOURCE ORA-00051 "Time-out occured while Oracle is waiting for a ressource"

TOO_MANY_ROWS ORA-01422 Un ordre SELECT retourne plus d'une ligne. VALUE_ERROR ORA-06502 Une erreur arithmétique, de conversion, de

troncation ou de contrainte de taille est apparu. ZERO_DEVIDE ORA-01476 Une division par zéro a été tenté.

6.2.3. Capturer des exceptions non prédéfinies du serveur Oracle Pour capturer une exception non prédéfinie du serveur Oracle, il existe deux méthodes. La première consiste à utiliser la clause OTHERS dans la section de gestion des exceptions. La deuxième permet un traitement personnalisé de l'exception : 1. Déclarer l'exception dans la section déclarative.(L'exception déclarée est implicitement levée)

Syntaxe :

exception EXCEPTION; exception est le nom de l'exception donné par le développeur.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

2. Associer le nom de l'exception à un numéro d'erreur Oracle à l'aide du pragma (appelé aussi pseudo-instruction) EXCEPTION_INIT dans la section déclarative. Ce pragma permet de

Page 57: Notions de Base Du PL-SQL

Notions de base du PL/SQL 57 / 63

référencer n'importe quelle exception interne par un nom et d'y rattacher un traitement spécifique dans la section de gestion des exceptions. Syntaxe :

PRAGMA EXCEPTION_INIT(exception, error_number);

exception correspond à l'exception déclarée précédemment. error-number est un numéro d'erreur standard du serveur Oracle.

Un pragma est une directive de compilateur, un pragma peut être vu comme une remarque entre parenthèses faite au compilateur. Un pragma est traité au moment de la compilation et non de l'exécution. Le pragma EXCEPTION_INIT peut être déclaré dans la section déclarative d'un bloc PL/SQL ou dans un package. La déclaration du pragma doit apparaître quelque part après la déclaration de l'exception dans la même section déclarative.

3. Référencer l'exception dans une routine de la section de gestion des exceptions. Syntaxe :

WHEN exception THEN statement1; statement2; ...

exception correspond à l'exception déclarée et associée à un numéro d'erreur précédemment. statement correspondent aux ordres PL/SQL traitant l'exception.

Déclarer Associer

Section de gestion des exceptions Section déclarative

Figure 1 : Capturer des exceptions non prédéfinies du serveur Oracle

Exemple :

DECLARE e_emps_remaining EXCEPTION; PRAGMA EXCEPTION_INIT (e_emps_remaining, -2292); v_deptno dept.deptno%TYPE := &p_deptno; BEGIN DELETE FROM dept WHERE deptno = v_deptno; COMMIT; EXCEPTION WHEN e_emps_remaining THEN DBMS_OUTPUT.PUT_LINE('Cannot remove department ' || TO_CHAR(v_deptno) || ', Employees

exist.'); END;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Référencer

Page 58: Notions de Base Du PL-SQL

Notions de base du PL/SQL 58 / 63

Ce bloc PL/SQL gère le cas où un département ne peut pas être supprimé car il reste des employés dans ce département. Un message explicatif s'affiche alors à l'utilisateur.

6.2.4. Les fonctions pour capturer les exceptions Lorsqu'une exception se produit, le code de l'erreur associé à l'exception et le message d'erreur peuvent être récupérés avec deux fonctions :

SQLCODE retourne le numéro d'erreur Oracle d'une exception interne. La valeur retournée peut être assignée à une variable de type NUMBER.

- SQLERRM retourne le message associé au numéro de l'erreur. La valeur retournée peut être assignée à une variable de type chaîne de caractères.

En générale, SQLCODE retourne un nombre négatif. Quelques valeurs particulières retournées par SQLCODE :

- Si SQLCODE retourne 0, cela signifie qu'aucune exception n'a été levée ("encountered"). - Si SQLCODE retourne 1, cela signifie que l'exception levée a été définie par l'utilisateur. - Si SQLCODE retourne +100, cela signifie que l'exception levée est l'exception prédéfinie

NO_DATA_FOUND. Exemple :

DECLARE v_error_code NUMBER; v_error_message VARCHAR2(255); BEGIN ... EXCEPTION ... WHEN OTHERS THEN ROLLBACK; v_error_code:=SQLCODE; v_error_message:=SQLERRM; INSERT INTO errors VALUES(v_error_code, v_error_message); END;

Ce bloc PL/SQL récupère le numéro et le message de l'erreur par l'intermédiaire de deux variables, puis stocke leurs valeurs dans la table ERRORS.

6.2.5. Capturer les exceptions définies par l'utilisateur Le langage PL/SQL permet à l'utilisateur de définir ses propres exceptions. Les exceptions définies par l'utilisateur doivent être : 1. déclarées dans la section déclarative d'un bloc PL/SQL.

Syntaxe :

exception EXCEPTION;

exception est le nom de l'exception donné par le développeur. 2. levées explicitement dans la section exécutable avec l'ordre RAISE.

Syntaxe :

RAISE exception;

exception est le nom de l'exception déclarée par le développeur.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

3. référencées avec dans une routine de la section de gestion des exceptions.

Page 59: Notions de Base Du PL-SQL

Notions de base du PL/SQL 59 / 63

Syntaxe :

WHEN exception THEN statements;

exception est le nom de l'exception déclarée et levée explicitement précédemment.

Figure 2 : Capturer des exceptions définies par l'utilisateur

Exemple :

DECLARE E_invalid_product EXCEPTION; BEGIN UPDATE product SET describ = '&product_description' WHERE prodid = &product_number; IF SQL%NOTFOUND THEN RAISE e_invalid_product; END IF; COMMIT; EXCEPTION WHEN e_invalid_product THEN DBMS_OUTPUT.PUT_LINE('Invalid product number.'); END;

Ce bloc met à jour la description d'un produit. L'utilisateur saisi la nouvelle description et le numéro du produit. Si l'utilisateur saisie un numéro qui n'existe pas, aucune ligne ne sera mise à jour dans la table PRODUCT. Une exception est levée explicitement. Un message s'affiche à l'utilisateur l'informant de l'invalidité du numéro de produit qu'il a saisi.

6.2.6. La procédure RAISE_APPLICATION_ERROR La procédure RAISE_APPLICATION_ERROR permet de publier des messages d'erreurs définis par l'utilisateur depuis un bloc PL/SQL. Ainsi, il est possible d'annoncer des erreurs à une application et d'éviter de retourner des exceptions non définies. Syntaxe : RAISE_APPLICATION_ERROR (error_number, message [,{TRUE|FALSE}]);

error_number est le numéro d'exception spécifié par le développeur qui doit se

trouver entre -20000 et -20999. message est le message d'erreur associée à l'exception et spécifié par le

développeur. Il s'agit d'une chaîne de caractères avec une taille maximale de 2048 octets.

Déclarer Lever

Section Section déclarative exécutable

Section de gestion des exceptions

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Référencer

Page 60: Notions de Base Du PL-SQL

Notions de base du PL/SQL 60 / 63

TRUE | FALSE correspond à un paramètre booléen optionnel. (Si la valeur est TRUE, l'erreur est placée sur la pile des erreurs précédentes. Si la valeur est FALSE (valeur par défaut), l'erreur remplace toutes les erreurs précédentes).

La procédure RAISE_APPLICATION_ERROR peut être utilisée à deux emplacements différents :

- Dans la section exécutable Exemple :

... BEGIN ... DELETE FROM emp WHERE mgr = v_mgr; ... EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR (-20201, 'This is not a valid manager'); END;

- Dans la section de gestion des exceptions

Exemple :

... BEGIN ... DELETE FROM emp WHERE mgr = v_mgr; IF SQL%NOTFOUND THEN RAISE_APPLICATION_ERROR(-20201, 'This is not a valid Manager'); END IF; ...

Dans les deux exemples, l'erreur -20201 est une exception définie par le développeur, ce n'est pas une erreur standard du serveur Oracle. Le développeur a défini son exception par un numéro d'erreur qui n'existe pas parmi les standards du serveur Oracle et par un message.

Une application ne peut appeler la procédure RAISE_APPLICATION_ERROR que depuis un bloc PL/SQL (nommé ou non) exécutable. Quand elle est appelée, la procédure termine le bloc (ou sous-programme) et retourne un numéro d'erreur et un message définis par l'utilisateur à l'application. Ce numéro et ce message peuvent être attrapés comme une erreur du serveur Oracle. L'application obtient une exception PL/SQL qui peut être traitée en utilisant les fonctions SQLCODE et SQLERRM dans une routine OTHERS. L'application peut aussi utiliser le pragma EXCEPTION_INIT pour récupérer les numéros d'erreur retournés par la procédure RAISE_APPLICATION_ERROR. Exemple :

CREATE PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) AS curr_sal NUMBER; BEGIN SELECT sal INTO curr_sal FROM emp WHERE empno=emp_id; IF curr_sal IS NULL THEN RAISE_APPLICATION_ERROR(-20101, 'Salary is missing'); ELSE UPDATE emp SET sal=curr_sal+amount WHERE empno=emp_id; END IF;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

END raise_salary;

Page 61: Notions de Base Du PL-SQL

Notions de base du PL/SQL 61 / 63

Dans cet exemple, il s'agit de la création d'un bloc PL/SQL nommé, soit une procédure appelée raise_salary. Cette procédure récupère le salaire d'un employé dont le numéro est passé en paramètre. Si le salaire de l'employé est nul, alors la procédure RAISE_APPLICATION_ERROR est appelée. Sinon la procédure met à jour le salaire de l'employé dans la base en lui ajoutant une augmentation passée en paramètre. EXEC SQL EXECUTE DECLARE ... null_salary EXCEPTION; PRAGMA EXCEPTION_INIT(null_salary, -20101); BEGIN ... raise_salary(:my_emp_id, :my amount); EXCEPTION WHEN null_salary THEN INSERT INTO emp_audit VALUES (:my_emp_id,...); ... END; END-EXEC;

Ce bloc ci-dessous est placé dans le code d'une application, par exemple du code Pro*C. Ce bloc déclare une exception et lui associe un numéro d'erreur. Ce numéro d'erreur correspond à une exception définie par l'utilisateur : -20101. Ce bloc appelle la procédure, déclarée ci avant, raise_salary. Si la procédure lève l'exception -20101, ce sera le bloc PL/SQL inclus dans le code Pro*C qui la traitera et non la procédure elle-même. L'application peut ainsi récupérer directement l'erreur et le message qui lui est associé.

Note : La procédure RAISE_APPLICATION_ERROR appartient au package DBMS_STANDARD livré par Oracle. Ce package fournit des "language facilities" pour aider une application à interagir avec Oracle. Le package DBMS_STANDARD est une extension du package STANDARD, donc il n'est pas nécessaire de référencer leurs procédures.

6.3. La propagation des exceptions Quand un sous-bloc traite une exception, le sous-bloc se termine normalement, et le programme reprend donc dans le bloc "père" immédiatement après l'ordre END du sous-bloc. Cependant, si le moteur PL/SQL lève une exception qui ne possède pas de routine dans la section de gestion des exceptions du bloc courant, alors l'exception est propagée successivement dans les blocs "pères" jusqu'à trouver une routine. Si aucun des blocs ne capture l'exception, une exception non traitée aboutit dans l'environnement hôte et le programme échoue.

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

Exemple :

Page 62: Notions de Base Du PL-SQL

Notions de base du PL/SQL 62 / 63

BEGIN BEGIN IF x = 1 THEN RAISE A; ELSIF x = 2 THEN RAISE B; ELSE RAISE C; END IF ... EXCEPTION WHEN A THEN ... END; EXCEPTION WHEN B THEN ... END;

Quand une exception se propage dans un bloc "père", les actions exécutables restantes dans le sous-bloc sont contournées. Exemple 2 :

BEGIN BEGIN IF x = 1 THEN RAISE A; ELSIF x = 2 THEN RAISE B; ELSE RAISE C; END IF ... EXCEPTION WHEN A THEN ... END; EXCEPTION WHEN B THEN ... END;

Exemple 3 :

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

L'exception A est traitée localement, puis l'exécution reprend dans le bloc "père"

L'exception B se propage dans le premier bloc "père" avec une routine appropriée.

L'exception B est traitée, puis le contrôle passe dans

l'environnement hôte.

Page 63: Notions de Base Du PL-SQL

Notions de base du PL/SQL 63 / 63

BEGIN BEGIN IF x = 1 THEN RAISE A; ELSIF x = 2 THEN RAISE B; ELSE RAISE C; END IF ... EXCEPTION WHEN A THEN ... END; EXCEPTION WHEN B THEN ... END;

Un des avantages de la propagation est que des ordres qui requièrent leurs propres traitements d'exceptions peuvent être inclus dans des sous blocs en laissant les traitements d'exception plus généraux dans les blocs "pères". Une exception déclarée dans un bloc est considérée comme local pour ce bloc et global pour tous les sous blocs. Une exception ne peut pas être déclarée deux fois dans un même bloc, mais elle peut être déclarée deux fois dans deux blocs différents. C'est l'exception locale qui prévaut sur l'exception globale. Pour référencer l'exception globale, il faut utiliser des blocs labellisés : block_label.exception ;

http://www.labo-oracle.com Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs

L'exception B n'a pas de routine dans le sous-bloc ni dans le bloc "père", donc une exception non traitée est retournée à l'environnement hôte.