Académique Documents
Professionnel Documents
Culture Documents
D52824
Edition 1.0
Janvier 2008
D49990FR10
®
PL/SQL
Manuel du stagiaire
Oracle Database 11g :
Les fondamentaux du langage
Auteur
Tulika Srivastava Avertissement
Rédacteurs Oracle est une marque déposée d'Oracle Corporation et/ou de ses filiales. Tout autre
nom de produit ou de société peut être une marque de son propriétaire.
Atanu Raychaudhuri
Richard Wallis
Concepteurs graphique
Satish Bettegowda
Rajiv Chandrabhanu
Editeurs
Sujatha Nagendra
Michael Sebastian
Giri Venugopal
Table des matières
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Préface
I Introduction
Objectifs I-2
Objectifs du cours I-3
Contenu du cours I-4
iv
4 Interagir avec le serveur de base de données Oracle
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Objectifs 4-2
Instructions SQL en langage PL/SQL 4-3
Instructions SELECT en langage PL/SQL 4-4
Extraire des données en langage PL/SQL 4-8
Conventions d'appellation 4-10
Utiliser PL/SQL pour manipuler des données 4-12
Insérer des données 4-13
Mettre à jour des données 4-14
Supprimer des données 4-15
Fusionner des lignes 4-16
Curseur SQL 4-18
Attributs de curseur SQL pour les curseurs implicites 4-20
Synthèse 4-22
v
6 Utiliser des types de données composites
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Objectifs 6-2
Types de données composites 6-3
Enregistrements PL/SQL 6-5
Créer un enregistrement PL/SQL 6-6
Structure d'un enregistrement PL/SQL 6-8
Attribut %ROWTYPE 6-9
Avantages liés à l'utilisation de l'attribut %ROWTYPE 6-11
Attribut %ROWTYPE : Exemple 6-12
Insérer un enregistrement à l'aide de %ROWTYPE 6-13
Mettre à jour une ligne d'une table
à l'aide d'un enregistrement 6-14
Tables INDEX BY ou tableaux associatifs 6-15
Créer une table INDEX BY 6-16
vi
Synthèse 7-27
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
vii
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Exercices complémentaires
viii
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Introduction
Objectifs
But du chapitre
Ce chapitre constitue une présentation générale du cours et de son déroulement. Il présente le
schéma de base de données et les tables utilisés.
Objectifs du cours
Objectifs du cours
Ce cours présente les concepts de base du langage PL/SQL. Vous découvrirez la syntaxe,
les blocs et les structures de programmation du langage PL/SQL, ainsi que les avantages de
l'intégration du langage SQL à ces structures. Vous apprendrez à écrire des programmes
PL/SQL et à les exécuter efficacement. En outre, vous apprendrez à utiliser SQL Developer
en tant qu'environnement de développement de code PL/SQL. Enfin, vous apprendrez à
concevoir des programmes réutilisables, tels que des procédures et des fonctions.
Contenu du cours
Contenu du cours
DEPARTMENTS LOCATIONS
department_id location_id
department_name street_address
manager_id postal_code
location_id city
state_province
country_id
JOB_HISTORY
employee_id
start_date EMPLOYEES
employee_id
end_date
first_name
job_id
last_name COUNTRIES
department_id country_id
email
phone_number country_name
hire_date region_id
job_id
salary
Editer
Synthèse
Exercices du cours
Dans les exercices de ce cours, vous allez développer une application simple à l'aide de blocs
anonymes. Vous effectuerez les actions suivantes :
• Ecrire une section déclarative
• Déclarer des variables de type scalaire
• Déclarer des variables avec l'attribut %TYPE
• Ecrire une section exécutable
• Accepter la saisie de valeurs par l'utilisateur pour les variables
• Extraire des valeurs de la base de données et les stocker dans des variables à l'aide de la clause
INTO
• Ecrire un bloc imbriqué dans la section exécutable
• Utiliser des structures de contrôle dans la section exécutable afin d'exécuter une logique métier
• Utiliser une table INDEX BY pour stocker des valeurs et les afficher
• Traiter les exceptions
Objectifs
But du chapitre
Ce chapitre présente le langage PL/SQL et les structures de programmation PL/SQL. Vous en
saurez plus sur les avantages du langage PL/SQL.
Le langage PL/SQL :
• signifie "Procedural Language extension to SQL"
(extension procédurale du langage SQL)
• est le langage standard d'accès aux données d'Oracle
Corporation pour les bases de données relationnelles
• intègre de manière transparente les structures procédurales
au langage SQL
Environnement PL/SQL
Moteur PL/SQL
Programme
instruction
Bloc d'exécution
procédurale
PL/SQL des instructions
procédurales
SQL
Environnement PL/SQL
La diapositive ci-dessus illustre l'environnement d'exécution PL/SQL du serveur de base de
données Oracle. Un bloc PL/SQL contient des instructions procédurales et des instructions
SQL. Lorsque vous soumettez un bloc au serveur, le moteur PL/SQL commence par l'analyser
(parse). Il identifie les instructions procédurales et les instructions SQL. Il transmet les
instructions procédurales au programme d'exécution des instructions procédurales et les
instructions SQL au programme d'exécution des instructions SQL.
Le schéma de la diapositive ci-dessus illustre le moteur PL/SQL dans le serveur de base de
données. Les outils de développement d'applications Oracle peuvent également contenir un
moteur PL/SQL. L'outil transmet les blocs au moteur PL/SQL local. Par conséquent, toutes
les instructions procédurales sont exécutées localement et seules les instructions SQL sont
exécutées dans la base de données. Le moteur utilisé dépend de l'emplacement à partir duquel
le bloc PL/SQL est appelé.
SQL 1
SQL 2
…
• DECLARE (facultatif)
– Variables, curseurs, exceptions définies par l'utilisateur
• BEGIN (obligatoire)
– Instructions SQL
– Instructions PL/SQL
• EXCEPTION (facultatif)
– Actions à effectuer lorsque
des erreurs se produisent
Types de bloc
Types de bloc
Un programme PL/SQL comporte un ou plusieurs blocs. Ces blocs peuvent être entièrement
distincts ou être imbriqués. Il existe trois types de bloc qui constituent un programme
PL/SQL. Il s'agit des types suivants :
• Blocs anonymes
• Procédures
• Fonctions
Blocs anonymes : Les blocs anonymes sont des blocs non nommés. Ils sont déclarés en ligne
(inline) dans une application, à l'endroit où ils doivent être exécutés, et sont compilés chaque
fois que l'application est exécutée. Ces blocs ne sont pas stockés dans la base de données. Ils
sont transmis au moteur PL/SQL en vue de leur exécution. Les déclencheurs (triggers)
d'Oracle Developer sont constitués de tels blocs. Ces blocs anonymes sont pris en compte lors
de l'exécution parce qu'ils sont en ligne. Si vous souhaitez exécuter de nouveau le même bloc,
vous devez réécrire le bloc. Vous ne pouvez pas appeler le bloc que vous avez écrit
précédemment, car les blocs sont anonymes et n'existent plus après leur exécution.
Structures de programme
Structures du serveur
Structures des outils de base de données
Blocs anonymes Blocs anonymes
Procédures ou Procédures ou
fonctions applicatives fonctions stockées
Structures de programme
Le tableau suivant répertorie différentes structures de programme PL/SQL utilisant le bloc
PL/SQL de base. La disponibilité de ces structures dépend de l'environnement d'exécution.
Procédures ou Blocs PL/SQL nommés, stockés dans une Outils Oracle Developer (par
fonctions application ou une bibliothèque partagée exemple, Oracle Forms
applicatives Oracle Forms Developer. Ils acceptent des Developer, Oracle Reports)
paramètres et peuvent être appelés à plusieurs
reprises par leur nom.
Procédures ou Blocs PL/SQL nommés, stockés sur le serveur Serveur Oracle ou outils Oracle
fonctions Oracle. Ils acceptent des paramètres et peuvent Developer
stockées être appelés à plusieurs reprises par leur nom.
Déclencheurs Blocs PL/SQL associés à une table de base de Outils Oracle Developer (par
applicatifs données ou à des événements système. Ils sont exemple, Oracle Forms
exécutés automatiquement lorsqu'ils sont Developer)
déclenchés par une instruction LMD ou par un
événement système.
Types d'objet Types de données composites définis par Serveur Oracle et outils Oracle
Run Script
Enable DBMS
Onglet DBMS
Output
Output
Synthèse
Synthèse
Le langage PL/SQL comporte des fonctionnalités de programmation qui permettent d'étendre
le langage SQL. Ce dernier, qui est un langage non procédural, est rendu procédural avec les
structures de programmation PL/SQL. Les applications PL/SQL peuvent s'exécuter sur toute
plate-forme ou tout système d'exploitation sur lequel s'exécute un serveur Oracle. Dans ce
chapitre, vous avez appris à créer des blocs PL/SQL de base.
Présentation de l'exercice 1
Présentation de l'exercice 1
Cet exercice renforce les bases du langage PL/SQL apprises dans ce chapitre.
• Le point 1 vous permet d'identifier les blocs PL/SQL qui s'exécutent avec succès.
Répondez-y par écrit.
• Le point 2 vous fait créer et exécuter un bloc PL/SQL simple.
Exercice 1
Le dossier labs est votre répertoire de travail. Vous pouvez y enregistrer vos scripts. Demandez au
formateur de vous aider à localiser le dossier labs de ce cours. Les solutions de tous les exercices se
trouvent dans le dossier soln.
1. Parmi les blocs PL/SQL suivants, lesquels s'exécutent avec succès ?
a. BEGIN
END;
b. DECLARE
amount INTEGER(10);
END;
c. DECLARE
d. DECLARE
amount INTEGER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE(amount);
END;
2. Créez et exécutez un bloc anonyme simple qui affiche "Hello World". Exécutez ce script et
enregistrez-le sous le nom lab_01_02_soln.sql.
Objectifs
But du chapitre
Dans le chapitre précédent, vous avez étudié un bloc PL/SQL de base ainsi que ses sections.
Dans le présent chapitre, vous découvrirez les identificateurs valides et non valides. Vous
apprendrez à déclarer et à initialiser des variables dans la section déclarative d'un bloc
PL/SQL. Vous étudierez les différents types de données. Enfin, vous découvrirez l'attribut
%TYPE et ses avantages.
SELECT
first_name,
department_id
Un nom de variable :
• doit commencer par une lettre
• peut inclure des lettres ou des chiffres
• peut inclure des caractères spéciaux (tels que $, _ et #)
• ne doit pas contenir plus de 30 caractères
• ne doit pas inclure de mots réservés
Les variables :
• sont déclarées et initialisées dans la section déclarative
• sont utilisées et font l'objet de l'affectation de nouvelles
valeurs dans la section exécutable
• sont transmises en tant que paramètres aux
sous-programmes PL/SQL
• sont utilisées pour contenir la sortie d'un sous-programme
PL/SQL
Syntaxe :
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
Exemples :
DECLARE
v_hiredate DATE;
v_deptno NUMBER(2) NOT NULL := 10;
v_location VARCHAR2(13) := 'Atlanta';
c_comm CONSTANT NUMBER := 1400;
DECLARE
v_myName VARCHAR2(20);
1 BEGIN
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
v_myName := 'John';
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
END;
/
DECLARE
v_myName VARCHAR2(20):= 'John';
DECLARE
v_event VARCHAR2(15);
BEGIN
v_event := q'!Father's day!';
DBMS_OUTPUT.PUT_LINE('3rd Sunday in June is :
'|| v_event );
v_event := q'[Mother's day]';
DBMS_OUTPUT.PUT_LINE('2nd Sunday in May is :
'|| v_event );
Types de variable
• Variables PL/SQL :
– Scalaire
– Composite
– Référencée
– LOB
• Variables non PL/SQL : Variables attachées
Types de variable
Toutes les variables PL/SQL présentent un type de données qui définit un format de stockage,
des contraintes et une plage de valeurs valide. Le langage PL/SQL prend en charge cinq
catégories de types de données que vous pouvez utiliser pour déclarer des variables, des
constantes et des pointeurs : scalaire, composite, référencé, LOB (Large Object) et objet.
• Types de données scalaires : Les types de données scalaires contiennent une seule
valeur. La valeur dépend du type de données de la variable. Par exemple, la variable
v_myName utilisée dans l'exemple de la section "Déclarer et initialiser des variables
PL/SQL" (dans ce chapitre) est de type VARCHAR2. Par conséquent, v_myName peut
contenir une valeur de type chaîne. Le langage PL/SQL prend également en charge les
variables booléennes.
• Types de données composites : Les types de données composites contiennent des
éléments internes de type scalaire ou composite. RECORD et TABLE sont des exemples
de types de données composites.
• Types de données référencés : Les types de données référencés contiennent des valeurs,
appelées pointeurs, qui désignent un emplacement de stockage.
• Types de données LOB : Les types de données LOB contiennent des valeurs, appelées
pointeurs, qui indiquent l'emplacement d'objets volumineux (par exemple des images)
stockés à l'extérieur de la table.
Les variables non PL/SQL comprennent les variables du langage hôte déclarées dans des
précompilateurs, les champs d'écran des applications Forms et les variables hôte. Les
variables hôte seront décrites plus loin dans ce chapitre.
Pour plus d'informations sur les types de données LOB, consultez le manuel PL/SQL User's
Guide and Reference.
Oracle Database 11g : Les fondamentaux du langage PL/SQL 2 - 9
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
Types de variable
TRUE 25-JAN-01
Blanche Neige
Il y a bien longtemps,
dans un pays lointain,
vivait une princesse appelée
Blanche Neige. . .
TRUE 25-JAN-01
L'âme du paresseux a
des désirs qu'il ne peut satisfaire ;
Mais l'âme des hommes
256120.08 Atlanta
• CHAR [(maximum_length)]
• VARCHAR2 (maximum_length)
• NUMBER [(precision, scale)]
• BINARY_INTEGER
• PLS_INTEGER
• BOOLEAN
• BINARY_FLOAT
• BINARY_DOUBLE
• DATE
• TIMESTAMP
• TIMESTAMP WITH TIME ZONE
• TIMESTAMP WITH LOCAL TIME ZONE
• INTERVAL YEAR TO MONTH
• INTERVAL DAY TO SECOND
Exemples :
DECLARE
v_emp_job VARCHAR2(9);
v_count_loop BINARY_INTEGER := 0;
v_dept_total_sal NUMBER(9,2) := 0;
v_orderdate DATE := SYSDATE + 7;
c_tax_rate CONSTANT NUMBER(3,2) := 8.25;
v_valid BOOLEAN NOT NULL := TRUE;
Attribut %TYPE
Les variables PL/SQL sont généralement déclarées pour contenir des données stockées dans
une base en vue de leur manipulation. Lors de la déclaration de variables PL/SQL devant
contenir des valeurs de colonne, vous devez vous assurer que le type et la précision de ces
variables sont corrects. Dans le cas contraire, une erreur PL/SQL survient au moment de
l'exécution. Si vous devez concevoir des sous-programmes volumineux, le processus peut être
long et sujet à erreur.
Plutôt que de coder en dur le type et la précision d'une variable, vous pouvez utiliser l'attribut
%TYPE pour déclarer une variable par rapport à une autre variable déclarée antérieurement ou
par rapport à une colonne de base de données. L'attribut %TYPE est le plus souvent utilisé
lorsque la valeur stockée dans la variable est issue d'une table de la base de données. Lorsque
vous utilisez l'attribut %TYPE pour déclarer une variable, vous devez préfixer celle-ci avec le
nom de la table et de la colonne de la base de données. Si vous référencez une variable
déclarée précédemment, faites précéder le nom de celle-ci du nom de la variable en cours de
déclaration.
Syntaxe
identifier table.column_name%TYPE;
Exemples
...
emp_lname employees.last_name%TYPE;
...
...
Variables attachées
Variables attachées
Les variables attachées (bind variables) sont des variables que vous créez dans un
environnement hôte. Pour cette raison, elles sont parfois appelées variables hôte.
Utilisation des variables attachées
Les variables attachées sont créées dans l'environnement et non dans la section déclarative
d'un bloc PL/SQL. Les variables déclarées dans un bloc PL/SQL sont disponibles uniquement
lorsque vous exécutez le bloc. Une fois le bloc exécuté, la mémoire utilisée par la variable est
libérée. Cependant, les variables attachées restent accessibles après l'exécution du bloc. Par
conséquent, lorsqu'elles sont créées, les variables attachées peuvent être utilisées et
manipulées par plusieurs sous-programmes. Elles peuvent être utilisées dans les instructions
SQL et les blocs PL/SQL comme n'importe quelle autre variable. Ces variables peuvent être
transmises en tant que valeurs d'exécution à destination ou en provenance de sous-
programmes PL/SQL.
Créer des variables attachées
Pour créer une variable attachée dans SQL Developer, utilisez la commande VARIABLE.
Par exemple, vous pouvez déclarer des variables de type NUMBER et VARCHAR2 comme
suit :
VARIABLE return_code NUMBER
VARIABLE return_msg VARCHAR2(30)
SQL Developer peut référencer la variable attachée et afficher sa valeur via la commande
PRINT.
b_result
----------
Exemple :
VARIABLE b_emp_salary NUMBER
BEGIN
SELECT salary INTO :b_emp_salary
FROM employees WHERE employee_id = 178;
END;
/
PRINT b_emp_salary
SELECT first_name, last_name FROM employees
WHERE salary=:b_emp_salary;
Exemple :
Livre
(CLOB)
Photo
(BLOB)
Film
NCLOB
1 SMITH 1 5000
2 JONES 2 2345
VARCHAR2 NUMBER
PLS_INTEGER PLS_INTEGER
Synthèse
Synthèse
Un bloc PL/SQL anonyme représente l'unité de base, sans nom, d'un programme PL/SQL. Il
se compose d'un ensemble d'instructions SQL ou PL/SQL permettant d'exécuter une fonction
logique. La section déclarative constitue la première partie d'un bloc PL/SQL. Elle sert à
déclarer des objets tels que les variables, les constantes, les curseurs et les définitions des
situations d'erreur (exceptions).
Dans ce chapitre, vous avez appris à déclarer des variables dans la section déclarative.
Vous avez étudié quelques-unes des règles de déclaration des variables. Vous avez appris à
initialiser les variables lors de leur déclaration.
La section exécutable représente la partie obligatoire d'un bloc PL/SQL. Elle contient des
instructions SQL et PL/SQL permettant l'interrogation et à la manipulation de données.
Vous avez appris à initialiser des variables dans la section exécutable, ainsi qu'à les utiliser et
à manipuler leurs valeurs.
Présentation de l'exercice 2
Présentation de l'exercice 2
Les points 1, 2 et 3 sont à traiter par écrit.
Exercice 2
1. Déterminez les noms d'identificateur valides et non valides :
a. today
b. last_name
c. today’s_date
d. Number_of_days_in_February_this_year
e. Isleap$year
f. #number
g. NUMBER#
h. number1to7
Exercice 2 (suite)
c. Exécutez ce script et enregistrez-le sous le nom lab_02_04_soln.sql. Un exemple
de sortie est présenté ci-après.
Objectifs
But du chapitre
Vous avez appris à déclarer des variables et à écrire des instructions exécutables dans un bloc
PL/SQL. Dans le présent chapitre, vous découvrirez comment des unités lexicales constituent
un bloc PL/SQL. Vous apprendrez à écrire des blocs imbriqués. Vous découvrirez également
la portée et la visibilité des variables dans les blocs imbriqués, ainsi que la qualification des
variables à l'aide d'étiquettes.
Symboles composés
Symbole Signification
<> Opérateur de non-égalité
!= Opérateur de non-égalité
|| Opérateur de concaténation
-- Indicateur de commentaire
monoligne
/* Délimiteur de début de
commentaire
*/ Délimiteur de fin de commentaire
:= Opérateur d'affectation
Remarque : Les délimiteurs ne sont pas tous détaillés ci-dessus.
• Littéraux : Toute valeur affectée à une variable est un littéral. Un caractère, un nombre, une
valeur booléenne ou une date qui ne constitue pas un identificateur est un littéral. Les littéraux
sont classés comme suit :
- Littéraux de type caractère : Tous les littéraux de type chaîne présentent le type CHAR ou
VARCHAR2 et sont donc appelés littéraux de type caractère (par exemple John et 12C).
- Littéraux numériques : Les littéraux numériques représentent une valeur entière ou réelle
(par exemple, 428 et 1,276).
- Littéraux booléens : Les valeurs affectées aux variables booléennes sont des littéraux
booléens. TRUE, FALSE et NULL sont des littéraux ou des mots-clés booléens.
• Commentaires : Il est judicieux d'expliquer le rôle d'une section de code lors de la
programmation. Lorsque vous incluez des explications dans un bloc PL/SQL, le compilateur ne
peut pas interpréter ces instructions. Il faut pouvoir indiquer que ces instructions ne doivent pas
être compilées. Les commentaires sont principalement utilisés pour cela. Toute instruction
marquée comme commentaire n'est pas interprétée par le compilateur.
- Indiquez deux traits d'union (--) pour marquer une ligne unique en tant que commentaire.
- Utilisez les délimiteurs de début et de fin de commentaire (/* et */) pour mettre en
commentaire plusieurs lignes.
Oracle Database 11g : Les fondamentaux du langage PL/SQL 3 - 4
THESE eKIT MATERIALS ARE FOR YOUR USE IN THIS CLASSROOM ONLY. COPYING eKIT MATERIALS FROM THIS COMPUTER IS STRICTLY PROHIBITED
1
2
DECLARE
...
v_annual_sal NUMBER (9,2);
BEGIN
/* Compute the annual salary based on the
monthly salary input from the user */
Blocs imbriqués
Blocs imbriqués
En tant que compilateur procédural, PL/SQL peut imbriquer des instructions. Vous pouvez
imbriquer des blocs partout où une instruction exécutable est autorisée. Le bloc imbriqué
devient alors une instruction. Si la section exécutable comporte du code pour de nombreuses
fonctionnalités liées logiquement afin de prendre en charge plusieurs besoins métier, vous
pouvez la fractionner en blocs plus petits. La section de traitement des exceptions peut aussi
contenir des blocs imbriqués.
Blocs imbriqués
Exemple :
DECLARE
v_outer_variable VARCHAR2(20):='GLOBAL VARIABLE';
BEGIN
DECLARE
v_inner_variable VARCHAR2(20):='LOCAL VARIABLE';
BEGIN
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
DECLARE
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
1 DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
Qualifier un identificateur
BEGIN <<outer>>
DECLARE
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '
||outer.v_date_of_birth);
Qualifier un identificateur
Un qualificateur est une étiquette affectée à un bloc. Vous pouvez utiliser ce qualificateur
pour accéder aux variables qui figurent dans la portée mais ne sont pas visibles. Examinez le
code : vous pouvez à présent afficher la date de naissance du père et celle de l'enfant dans le
bloc interne. Le bloc externe est nommé outer. Vous pouvez utiliser cette étiquette pour
accéder à la variable v_date_of_birth déclarée dans le bloc externe.
L'étiquetage n'est pas limité au bloc externe. Vous pouvez étiqueter n'importe quel bloc.
La sortie du code de la diapositive ci-dessus est le suivant :
BEGIN <<outer>>
DECLARE
v_sal NUMBER(7,2) := 60000;
v_comm NUMBER(7,2) := v_sal * 0.20;
v_message VARCHAR2(255) := ' eligible for commission';
BEGIN
DECLARE
v_sal NUMBER(7,2) := 50000;
v_comm NUMBER(7,2) := 0;
v_total_comp NUMBER(7,2) := v_sal + v_comm;
BEGIN
}
• Opérateur logique
• Opérateur arithmétique
• Opérateur de concaténation
Identiques en
• Parenthèses permettant de
contrôler l'ordre des opérations langage SQL
Indenter le code
Indenter le code
Pour plus de clarté et de lisibilité, indentez chaque niveau du code. Pour mettre la structure en
évidence, vous pouvez couper les lignes en utilisant des retours chariot et indenter les lignes
avec des espaces et des tabulations. Comparez la lisibilité des instructions IF suivantes :
IF x>y THEN max:=x;ELSE max:=y;END IF;
IF x > y THEN
max := x;
ELSE
max := y;
END IF;
Synthèse
Synthèse
Le langage PL/SQL étant une extension du langage SQL, les règles syntaxiques générales qui
régissent le code SQL s'appliquent également à PL/SQL.
Un bloc peut comporter un nombre illimité de blocs imbriqués dans sa section exécutable. Les
blocs définis à l'intérieur d'un bloc sont appelés sous-blocs. Vous ne pouvez imbriquer des
blocs que dans la section exécutable d'un bloc. Etant donné que la section de traitement des
exceptions se trouve dans la section exécutable, cette section peut également comporter des
blocs imbriqués. Assurez-vous que la portée et la visibilité des variables sont correctes lors de
l'utilisation de blocs imbriqués. Evitez d'utiliser les mêmes identificateurs dans les blocs
parent et enfant.
La plupart des fonctions disponibles en langage SQL le sont également dans les expressions
PL/SQL. Les fonctions de conversion convertissent une valeur d'un type de données dans un
autre. Les opérateurs de comparaison permettent de comparer des expressions entre elles. Le
résultat est toujours TRUE, FALSE ou NULL. Généralement, les opérateurs de comparaison
sont utilisés dans les instructions de contrôle conditionnelles, ainsi que dans la clause WHERE
des instructions SQL de manipulation de données. Les opérateurs relationnels permettent de
comparer des expressions complexes.
Présentation de l'exercice 3
Présentation de l'exercice 3
Les points 1 et 2 sont à traiter par écrit.
Exercice 3
Bloc PL/SQL
DECLARE
v_weight NUMBER(3) := 600;
v_message VARCHAR2(255) := 'Product 10012';
BEGIN
DECLARE
v_weight NUMBER(3) := 1;
v_message VARCHAR2(255) := 'Product 11001';
v_new_locn VARCHAR2(50) := 'Europe';
BEGIN
v_weight := v_weight + 1;
v_new_locn := 'Western ' || v_new_locn;
1
1. Observez le bloc PL/SQL qui précède et déterminez le type de données et la valeur de chacune
des variables suivantes d'après les règles relatives à la portée.
a. La valeur de v_weight à la position 1 est :
Exercice 3 (suite)
Exemple relatif à la portée
DECLARE
v_customer VARCHAR2(50) := 'Womansport';
v_credit_rating VARCHAR2(50) := 'EXCELLENT';
BEGIN
DECLARE
v_customer NUMBER(7) := 201;
v_name VARCHAR2(25) := 'Unisports';
BEGIN
v_credit_rating :='GOOD';
…
END;
…
END;
2. Dans le bloc PL/SQL qui précède, déterminez les valeurs et les types de données pour chacun
des cas suivants.
a. La valeur de v_customer dans le bloc imbriqué est :
Exercice 3 (suite)
3. Editez lab_02_05_soln.sql.
a. Mettez en commentaire les lignes de création des variables attachées (bind variables), en
utilisant la syntaxe de commentaire monoligne.
b. Dans la section exécutable, mettez en commentaire les lignes qui affectent des valeurs aux
variables attachées, en utilisant la syntaxe de commentaire multiligne.
c. Déclarez les variables v_basic_percent et v_pf_percent et initialisez-les à 45 et
12, respectivement. Déclarez également deux autres variables : v_fname de type
VARCHAR2 et de taille 15, et v_emp_sal de type NUMBER et de taille 10.
d. Incluez l'instruction SQL suivante dans la section exécutable :
SELECT first_name, salary
INTO v_fname, v_emp_sal FROM employees
WHERE employee_id=110;
e. Modifiez la ligne qui affiche "Hello World" afin d'afficher "Hello" et le prénom. Si vous le
Objectifs
But du chapitre
Dans ce chapitre, vous apprendrez à intégrer des instructions SQL standard SELECT,
INSERT, UPDATE, DELETE et MERGE dans des blocs PL/SQL. Vous apprendrez à inclure
des instructions LDD (Langage de définition de données) et des instructions de gestion des
transactions dans du code PL/SQL. Vous comprendrez la nécessité des curseurs et vous
pourrez distinguer les deux types de curseur. Enfin, vous étudierez les divers attributs de
curseur SQL pouvant être utilisés avec les curseurs implicites.
• Définissez autant de variables dans la clause INTO que de colonnes de base de données dans la
clause SELECT. Assurez-vous qu'elles correspondent de manière appropriée et que les types de
données sont compatibles.
• Utilisez les fonctions de groupe, telles que SUM, dans une instruction SQL. En effet, les
fonctions de groupe s'appliquent à des ensembles de lignes dans une table.
Comment extraire plusieurs lignes d'une table et opérer sur les données
Une instruction SELECT avec la clause INTO peut extraire une seule ligne à la fois. Si vous
souhaitez extraire plusieurs lignes et opérer sur les données, vous pouvez utiliser des curseurs
explicites. Les curseurs seront présentés ultérieurement dans ce chapitre. Les curseurs explicites
seront détaillés dans le chapitre "Utiliser des curseurs explicites".
Exemple :
DECLARE
v_emp_hiredate employees.hire_date%TYPE;
v_emp_salary employees.salary%TYPE;
BEGIN
SELECT hire_date, salary
INTO v_emp_hiredate, v_emp_salary
DECLARE
v_sum_sal NUMBER(10,2);
v_deptno NUMBER NOT NULL := 60;
BEGIN
SELECT SUM(salary) -- group function
Conventions d'appellation
DECLARE
hire_date employees.hire_date%TYPE;
sysdate hire_date%TYPE;
employee_id employees.employee_id%TYPE := 176;
BEGIN
SELECT hire_date, sysdate
INTO hire_date, sysdate
FROM employees
WHERE employee_id = employee_id;
END;
/
Conventions d'appellation
Dans les instructions SQL présentant un risque d'ambiguïté, les noms des colonnes de base de
données ont priorité sur les noms des variables locales.
L'exemple de la diapositive extrait de la table employees la date d'embauche et la date du
jour pour l'employé dont la valeur employee_id est égale à 176. Cet exemple déclenche
une exception d'exécution non gérée, car la clause WHERE contient des noms de variable
PL/SQL identiques aux noms des colonnes de base de données de la table employees.
L'instruction DELETE suivante supprime de la table employees tous les employés dont le
nom de famille n'est pas NULL (au lieu de supprimer uniquement ceux dont le nom est
"King"). En effet, le serveur Oracle suppose que les deux occurrences de last_name dans
la clause WHERE font référence à la colonne de base de données :
DECLARE
last_name VARCHAR2(25) := 'King';
BEGIN
DELETE FROM employees WHERE last_name = last_name;
. . .
Conventions d'appellation
MERGE
UPDATE
Exemple :
BEGIN
INSERT INTO employees
(employee_id, first_name, last_name, email,
hire_date, job_id, salary)
VALUES(employees_seq.NEXTVAL, 'Ruth', 'Cores',
Exemple :
DECLARE
sal_increase employees.salary%TYPE := 800;
BEGIN
UPDATE employees
SET salary = salary + sal_increase
WHERE job_id = 'ST_CLERK';
Exemple :
DECLARE
deptno employees.department_id%TYPE := 10;
BEGIN
DELETE FROM employees
WHERE department_id = deptno;
END;
BEGIN
MERGE INTO copy_emp c
USING employees e
ON (e.employee_id = c.empno)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email = e.email,
Curseur SQL
Curseur SQL
Nous avons vu que vous pouvez inclure des instructions SQL qui renvoient une ligne unique
dans un bloc PL/SQL. Les données extraites par l'instruction SQL doivent être stockées dans
des variables à l'aide de la clause INTO.
Où le serveur Oracle traite-t-il les instructions SQL ?
Le serveur Oracle alloue une zone de mémoire privée appelée zone de contexte pour le
traitement des instructions SQL. L'instruction SQL est analysée (parse) et traitée dans cette
zone. Les informations requises pour le traitement et les informations extraites après le
traitement sont toutes stockées dans cette zone. Vous ne pouvez pas contrôler cette zone car
elle est gérée en interne par le serveur Oracle.
Un curseur est un pointeur vers la zone de contexte. Cependant, ce curseur est un curseur
implicite, géré automatiquement par le serveur Oracle. Lorsque le bloc exécutable traite une
instruction SQL, le compilateur PL/SQL crée un curseur implicite.
Types de curseur
Il existe deux types de curseur :
• Implicite : Un curseur implicite est créé et géré par le serveur Oracle. Vous n'y avez pas
accès. Le serveur Oracle crée un tel curseur lorsqu'il doit exécuter une instruction SQL.
END;
Synthèse
Synthèse
Les commandes LMD et les instructions de gestion des transactions peuvent être utilisées sans
restriction dans les programmes PL/SQL. En revanche, les commandes LDD ne peuvent pas
être utilisées directement.
Une instruction SELECT incluse dans un bloc PL/SQL ne peut renvoyer qu'une seule ligne.
L'utilisation de la clause INTO est obligatoire pour le stockage des valeurs extraites par
l'instruction SELECT.
Un curseur est un pointeur vers la zone de mémoire. Il existe deux types de curseur.
Les curseurs implicites sont créés et gérés en interne par le serveur Oracle pour l'exécution
des instructions SQL. Vous pouvez utiliser les attributs de curseur SQL avec ces curseurs afin
de déterminer le résultat de l'instruction SQL. Les curseurs explicites sont déclarés par les
programmeurs.
Présentation de l'exercice 4
Exercice 4
1. Créez un bloc PL/SQL qui sélectionne l'ID de département le plus grand dans la table
departments et qui le stocke dans la variable v_max_deptno. Affichez l'ID de
département le plus élevé.
a. Déclarez une variable v_max_deptno de type NUMBER dans la section déclarative.
b. Commencez la section exécutable par le mot-clé BEGIN et incluez une instruction
SELECT afin d'extraire la valeur department_id maximale de la table
departments.
c. Affichez v_max_deptno et terminez le bloc exécutable.
d. Exécutez votre script et enregistrez-le sous le nom lab_04_01_soln.sql.
Un exemple de sortie est affiché ci-après.
Exercice 4 (suite)
3. Dans le point 2, vous avez affecté la valeur NULL à location_id. Créez un bloc PL/SQL
qui met à jour location_id avec la valeur 3000 pour le nouveau département. Utilisez la
variable attachée dept_id pour mettre à jour la ligne.
Remarque : Ignorez l'étape (a) si vous n'avez pas démarré une nouvelle session pour cet
exercice.
a. Si vous avez démarré une nouvelle session, supprimez le département que vous avez ajouté
à la table departments et exécutez le script lab_04_02_soln.sql.
b. Commencez le bloc exécutable par le mot-clé BEGIN. Incluez l'instruction UPDATE afin
d'affecter la valeur 3000 à location_id pour le nouveau département (dept_id =
280).
c. Terminez le bloc exécutable par le mot-clé END. Terminez le bloc PL/SQL par "/" et
incluez une instruction SELECT afin d'afficher le département que vous avez mis à jour.
1 rows selected
1 rows deleted
Objectifs
But du chapitre
Vous avez appris à écrire des blocs PL/SQL contenant des sections déclaratives et
exécutables. Vous avez également appris à inclure des expressions et des instructions SQL
dans le bloc exécutable.
Dans le présent chapitre, vous apprendrez à utiliser les structures de contrôle telles que
les instructions IF, les expressions CASE et les structures LOOP dans un bloc PL/SQL.
for
loop
Syntaxe :
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
Instruction IF
La structure de l'instruction IF en langage PL/SQL est semblable à celle des instructions IF
utilisées dans les autres langages procéduraux. Elle permet au langage PL/SQL d'exécuter des
actions dépendant de conditions spécifiques.
Dans la syntaxe :
condition Variable ou expression booléenne (renvoie TRUE, FALSE ou
NULL)
THEN Introduit une clause qui associe l'expression booléenne à la
séquence d'instructions qui suit.
statements Une ou plusieurs instructions PL/SQL ou SQL. Ces dernières
peuvent inclure d'autres instructions IF comprenant elles-mêmes
plusieurs instructions IF, ELSE et ELSIF imbriquées. Les
instructions de la clause THEN ne sont exécutées que si la
condition de la clause IF associée prend la valeur TRUE.
Dans la syntaxe :
ELSIF Est un mot-clé qui introduit une expression booléenne (si la première
condition donne FALSE ou NULL, le mot-clé ELSIF introduit des
conditions supplémentaires).
ELSE Introduit la clause par défaut, qui est exécutée si et seulement si aucun
des prédicats précédents (introduits par IF et ELSIF) n'a la valeur
TRUE. Les tests sont exécutés dans l'ordre. Ainsi, un prédicat pouvant
être vrai n'est pas pris en compte si un prédicat antérieur est vrai.
END IF Marque la fin d'une instruction IF.
Remarque : Les clauses ELSIF et ELSE sont facultatives dans une instruction IF. Vous pouvez
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
END IF;
END;
/
Instructions IF simples
La diapositive ci-dessus illustre un exemple d'instruction IF simple avec la clause THEN.
La variable v_myage est initialisée avec la valeur 31. La condition de l'instruction IF
renvoie FALSE, car v_myage n'est pas inférieur à 11. Par conséquent, le contrôle n'atteint
jamais la clause THEN. Nous allons ajouter du code à cet exemple afin d'étudier l'utilisation
des clauses ELSE et ELSIF.
Une instruction IF peut comporter plusieurs expressions conditionnelles liées à l'aide
d'opérateurs logiques tels que AND, OR et NOT. Voici un exemple :
IF (myfirstname='Christopher' AND v_myage <11)
…
La condition utilise l'opérateur AND et prend donc la valeur TRUE uniquement si les deux
conditions ont la valeur TRUE. Le nombre des expressions conditionnelles n'est pas limité.
Toutefois, celles-ci doivent être liées à l'aide d'opérateurs logiques appropriés.
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
/
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSIF v_myage < 20 THEN
DBMS_OUTPUT.PUT_LINE(' I am young ');
ELSIF v_myage < 30 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my twenties');
ELSIF v_myage < 40 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my thirties');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am always young ');
END IF;
DECLARE
v_myage number;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
Expressions CASE
Une expression CASE renvoie un résultat basé sur une ou plusieurs alternatives. Pour cela,
elle utilise un sélecteur, c'est-à-dire une expression admettant plusieurs valeurs qui permettent
de choisir entre différentes alternatives. Le sélecteur est suivi d'une ou plusieurs clauses
WHEN, qui sont vérifiées de façon séquentielle. La valeur du sélecteur détermine le résultat
renvoyé. Si cette valeur est égale à celle d'une expression comportant une clause WHEN, cette
dernière est exécutée et le résultat est renvoyé.
Le langage PL/SQL fournit également une expression de recherche pour la clause CASE, qui
se présente sous la forme suivante :
CASE
WHEN search_condition1 THEN result1
WHEN search_condition2 THEN result2
...
WHEN search_conditionN THEN resultN
[ELSE resultN+1]
END;
Une expression de recherche pour la clause CASE n'a pas de sélecteur. En outre, ses clauses
WHEN contiennent des conditions de recherche renvoyant une valeur booléenne plutôt que des
expressions pouvant renvoyer une valeur de n'importe quel type.
DECLARE
v_grade CHAR(1) := UPPER('&grade');
appraisal VARCHAR2(20);
BEGIN
appraisal := CASE
WHEN v_grade = 'A' THEN 'Excellent'
WHEN v_grade IN ('B','C') THEN 'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| v_grade || '
DECLARE
v_deptid NUMBER;
v_deptname VARCHAR2(20);
v_emps NUMBER;
v_mngid NUMBER:= 108;
BEGIN
CASE v_mngid
WHEN 108 THEN
SELECT department_id, department_name
INTO v_deptid, v_deptname FROM departments
WHERE manager_id=108;
SELECT count(*) INTO v_emps FROM employees
WHERE department_id=v_deptid;
WHEN 200 THEN
Instruction CASE
Rappelez-vous l'utilisation de l'instruction IF. Vous pouvez inclure n instructions PL/SQL
dans la clause THEN et dans la clause ELSE. De la même façon, vous pouvez inclure des
instructions dans une instruction CASE. Une instruction CASE est plus facile à lire que
plusieurs instructions IF et ELSIF.
En quoi une expression CASE diffère-t-elle d'une instruction CASE ?
Une expression CASE évalue une condition et renvoie une valeur, alors qu'une instruction
CASE évalue une condition et effectue une action. Une instruction CASE peut être un bloc
PL/SQL complet.
• Les instructions CASE se terminent par END CASE ;
• Les expressions CASE se terminent par END ;
Tables logiques
TRUE TRUE FALSE NULL TRUE TRUE TRUE TRUE TRUE FALSE
FALSE FALSE FALSE FALSE FALSE TRUE FALSE NULL FALSE TRUE
Tables logiques
Vous pouvez créer une condition booléenne simple en combinant des expressions de type
numérique, caractère et date à des opérateurs de comparaison.
Vous pouvez créer une condition booléenne complexe en combinant des conditions
booléennes simples avec les opérateurs logiques AND, OR et NOT. Les opérateurs logiques
sont utilisés pour vérifier les valeurs des variables booléennes et pour renvoyer TRUE, FALSE
ou NULL. Dans les tables logiques de la diapositive ci-dessus :
• FALSE est prioritaire dans une condition AND, tandis que TRUE est prioritaire dans une
condition OR.
• AND renvoie TRUE uniquement si ses deux opérandes sont TRUE.
• OR renvoie FALSE uniquement si ses deux opérandes sont FALSE.
• NULL et TRUE renvoient toujours NULL, car on ignore si la valeur du deuxième
opérande est TRUE.
Remarque : La négation de NULL (NOT NULL) renvoie une valeur NULL, car les valeurs
NULL sont indéterminées.
Conditions booléennes
Conditions booléennes
Vous pouvez utiliser la table logique AND pour évaluer les différents résultats possibles de
la condition booléenne de la diapositive.
Réponses
1. TRUE
2. FALSE
3. NULL
4. FALSE
Boucles de base
Syntaxe :
LOOP
statement1;
. . .
EXIT [WHEN condition];
END LOOP;
Boucles de base
La forme de boucle la plus simple est la boucle LOOP de base, qui contient une séquence
d'instructions entre les mots-clés LOOP et END LOOP. Dès que l'exécution du code atteint
le mot-clé END LOOP, le programme reprend le contrôle à partir de l'instruction LOOP
correspondante. Une boucle de base exécute au moins une fois les instructions qui lui sont
associées, même si la condition EXIT est remplie avant l'entrée dans la boucle. En l'absence
d'instruction EXIT, la boucle est infinie.
Instruction EXIT
Vous pouvez mettre fin à une boucle en utilisant l'instruction EXIT. L'exécution reprend alors
à l'instruction qui suit END LOOP. Vous pouvez utiliser EXIT en tant qu'action dans une
instruction IF ou en tant qu'instruction autonome dans la boucle. L'instruction EXIT doit être
placée à l'intérieur de la boucle. Dans ce dernier cas, vous pouvez ajouter une clause WHEN
pour permettre une sortie conditionnelle de la boucle. Lorsque l'instruction EXIT est
rencontrée, la condition de la clause WHEN est évaluée. Si la condition renvoie TRUE, la
boucle se termine et l'exécution du programme reprend à la première instruction qui suit END
LOOP. Une boucle de base peut contenir plusieurs instructions EXIT, mais il est recommandé
d'utiliser un seul point EXIT.
Boucles de base
Exemple :
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_counter NUMBER(2) := 1;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
LOOP
Syntaxe :
WHILE condition LOOP
statement1;
statement2;
. . .
END LOOP;
Boucles WHILE
Vous pouvez utiliser une boucle WHILE pour répéter une séquence d'instructions jusqu'à ce
que la condition de contrôle ne soit plus TRUE. La condition est évaluée au début de chaque
itération. La boucle se termine lorsque la condition renvoie FALSE ou NULL. Si la condition
est FALSE ou NULL dès le début de la boucle, aucune itération n'est effectuée. Il est donc
possible qu'aucune instruction de la boucle ne soit exécutée.
Dans la syntaxe :
condition Variable ou expression booléenne (TRUE, FALSE ou NULL).
statement Une ou plusieurs instructions PL/SQL ou SQL.
Si les variables impliquées dans les conditions ne changent pas au cours de la boucle, la
condition est toujours vérifiée (TRUE) et la boucle ne s'arrête jamais.
Remarque : Si la condition renvoie la valeur NULL, la boucle est ignorée et l'exécution du
programme reprend à l'instruction qui suit la fin de la boucle.
Exemple
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
v_counter NUMBER := 1;
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
WHILE v_counter <= 3 LOOP
Boucles FOR
Les boucles FOR ont la même structure globale que les boucles de base. En outre, elles
possèdent une instruction de contrôle précédant le mot-clé LOOP, qui détermine le nombre
d'itérations à effectuer par le compilateur PL/SQL.
Dans la syntaxe :
counter Entier déclaré implicitement, dont la valeur décroît ou augmente
automatiquement de 1 à chaque itération de la boucle jusqu'à ce que
la limite supérieure ou inférieure soit atteinte (elle décroît si le mot-clé
REVERSE est utilisé).
REVERSE Le compteur est décrémenté lors de chaque itération, de la limite
supérieure à la limite inférieure.
Remarque : La limite inférieure est toujours référencée en premier.
lower_bound Indique la limite inférieure de la plage des valeurs du compteur.
upper_bound Indique la limite supérieure de la plage des valeurs du compteur.
Ne déclarez pas le compteur. Il est déclaré implicitement en tant qu'entier.
Remarque : La séquence d'instructions est exécutée à chaque fois que le compteur est incrémenté,
en fonction des limites inférieure et supérieure de celui-ci. Ces limites peuvent être des littéraux, des
variables ou des expressions. Cependant, elles doivent correspondre à des entiers. Les limites sont
arrondies à des entiers, ce qui signifie que 11/3 et 8/5 sont des limites supérieure et inférieure valides.
Les limites sont incluses dans la plage des valeurs de la boucle. Si la limite inférieure prend une
valeur entière supérieure à la limite supérieure, la séquence d'instructions n'est pas exécutée.
Par exemple, l'instruction suivante ne s'exécute qu'une seule fois :
FOR i IN 3..3
LOOP
statement1;
END LOOP;
Exemple :
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id
FROM locations
WHERE country_id = v_countryid;
FOR i IN 1..3 LOOP
Règles
• Ne référencez le compteur qu'à l'intérieur de la boucle.
Il n'est pas défini en dehors.
• Ne référencez pas le compteur en tant que cible d'une
affectation.
• Aucune limite de boucle ne doit être NULL.
...
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';
• Définition
– Ajoute la fonctionnalité consistant à commencer l'itération de
boucle suivante
– Permet aux programmeurs de transférer le contrôle à
l'itération suivante d'une boucle
– Utilise une structure et une sémantique parallèles à celles de
l'instruction EXIT
• Avantages
– Facilite le processus de programmation
Synthèse
Synthèse
Un langage n'est considéré comme un langage de programmation que s'il offre des structures
de contrôle pour l'implémentation de la logique métier. Ces structures de contrôle sont
également utilisées pour contrôler le flux du programme. Le langage PL/SQL est un langage
de programmation qui complète le langage SQL avec des structures de programmation.
Une structure de contrôle conditionnel permet de vérifier la validité d'une condition et exécute
une action en conséquence. La structure IF permet une exécution conditionnelle des
instructions.
Une structure de contrôle d'itération exécute une séquence d'instructions de façon répétitive,
tant que la condition indiquée est vérifiée (TRUE). Vous pouvez utiliser les différentes
structures de boucle pour exécuter des opérations itératives.
Présentation de l'exercice 5
Présentation de l'exercice 5
Dans cet exercice, vous allez créer des blocs PL/SQL comportant des boucles et des structures
de contrôle conditionnelles. Vous pourrez ainsi vous exercer à écrire des instructions IF et
des structures LOOP.
Exercice 5
1. Exécutez la commande du fichier lab_05_01.sql pour créer la table messages. Ecrivez
un bloc PL/SQL permettant d'insérer des nombres dans la table messages.
a. Insérez les nombres 1 à 10, en excluant 6 et 8.
b. Effectuez une validation (commit) avant la fin du bloc.
c. Exécutez une instruction SELECT pour vérifier le fonctionnement du bloc PL/SQL.
Vous devez obtenir le résultat suivant :
Exercice 5 (suite)
d. Affichez la ligne de la table emp afin de vérifier que le bloc PL/SQL s'est exécuté
correctement.
e. Exécutez le script et enregistrez-le sous le nom lab_05_02_soln.sql. La sortie
devrait se présenter comme suit :
Objectifs
But du chapitre
Nous avons déjà présenté les types de données composites. Dans ce chapitre, vous en saurez
plus sur les types de données composites et leurs utilisations.
Enregistrements PL/SQL
Enregistrements PL/SQL
Un enregistrement est un groupe de données associées et stockées dans des champs. Chacun
d'eux possède un nom et un type de données qui lui sont propres.
• Chaque enregistrement ainsi défini peut contenir autant de champs que nécessaire.
• Il est possible de définir un enregistrement comme NOT NULL et de lui affecter des
valeurs initiales.
• Les champs qui ne contiennent pas de valeur initiale sont initialisés avec la valeur NULL.
• Le mot-clé DEFAULT peut être utilisé dans la définition des champs.
• Vous pouvez définir des types RECORD et déclarer des enregistrements définis par
l'utilisateur dans la section déclarative des blocs, des sous-programmes ou des packages.
• Vous pouvez déclarer et référencer des enregistrements imbriqués. Un enregistrement
peut être un composant d'un autre enregistrement.
Syntaxe :
2 identifier type_name;
field_declaration:
Exemple :
Champ1 Champ2 Champ3
Attribut %ROWTYPE
Nous avons vu que %TYPE est utilisé pour déclarer une variable d'un type de colonne.
La variable présente le même type de données et la même taille que la colonne de la table.
L'avantage de l'attribut %TYPE est que vous n'avez pas à modifier la variable si la colonne est
modifiée. En outre, si la variable est utilisée dans des calculs, vous n'avez pas à vous
préoccuper de sa précision.
L'attribut %ROWTYPE est utilisé pour déclarer un enregistrement pouvant contenir une ligne
entière d'une table ou d'une vue. Les champs de l'enregistrement tirent leurs noms et leurs
types de données des colonnes de la table ou de la vue. L'enregistrement peut également
contenir une ligne complète de données extraite à partir d'un curseur ou d'une variable de
curseur.
La diapositive ci-dessus présente la syntaxe de déclaration d'un enregistrement. Dans la
syntaxe :
identifier Nom choisi pour l'enregistrement.
reference Nom de la table, de la vue, du curseur ou de la variable de curseur
servant de base à l'enregistrement (la table ou la vue doit exister
pour que cette référence soit valide).
Dans l'exemple suivant, un enregistrement est déclaré via l'attribut %ROWTYPE, qui permet
de définir le type de données :
DECLARE
emp_record employees%ROWTYPE;
...
DECLARE
v_employee_number number:= 124;
v_emp_rec employees%ROWTYPE;
BEGIN
SELECT * INTO v_emp_rec FROM employees
WHERE employee_id = v_employee_number;
INSERT INTO retired_emps(empno, ename, job, mgr,
hiredate, leavedate, sal, comm, deptno)
VALUES (v_emp_rec.employee_id, v_emp_rec.last_name,
v_emp_rec.job_id, v_emp_rec.manager_id,
Insérer un enregistrement
à l'aide de %ROWTYPE
...
DECLARE
v_employee_number number:= 124;
v_emp_rec retired_emps%ROWTYPE;
BEGIN
SELECT employee_id, last_name, job_id, manager_id,
hire_date, hire_date, salary, commission_pct,
department_id INTO v_emp_rec FROM employees
Syntaxe :
TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table%ROWTYPE
[INDEX BY PLS_INTEGER | BINARY_INTEGER
| VARCHAR2(<size>)];
identifier type_name;
Déclarez une table INDEX BY pour le stockage du nom des
employés :
La contrainte NOT NULL permet d'empêcher l'affectation de valeurs NULL à une table PL/SQL.
N'initialisez pas la table INDEX BY.
Les tables INDEX BY peuvent présenter n'importe quel type scalaire.
Les tables INDEX BY ne sont pas remplies automatiquement lors de leur création. Vous devez les
alimenter au moyen de programmes PL/SQL avant de les utiliser.
1 Jones
5 Smith
3 Maduro
... ...
DECLARE
TYPE ename_table_type IS TABLE OF
employees.last_name%TYPE
INDEX BY PLS_INTEGER;
TYPE hiredate_table_type IS TABLE OF DATE
INDEX BY PLS_INTEGER;
ename_table ename_table_type;
hiredate_table hiredate_table_type;
BEGIN
ename_table(1) := 'CAMERON';
hiredate_table(8) := SYSDATE + 7;
Méthode Description
EXISTS(n) Renvoie TRUE si le nième élément d'une table PL/SQL existe.
COUNT Renvoie le nombre d'éléments contenus dans une table PL/SQL.
FIRST • Renvoie le premier (le plus petit) numéro d'index d'une table PL/SQL.
• Renvoie NULL si la table PL/SQL est vide.
LAST • Renvoie le dernier (le plus grand) numéro d'index d'une table PL/SQL.
• Renvoie NULL si la table PL/SQL est vide.
PRIOR(n) Renvoie le numéro d'index qui précède l'index n dans une table PL/SQL.
NEXT(n) Renvoie le numéro d'index qui suit l'index n dans une table PL/SQL.
DELETE • DELETE supprime tous les éléments d'une table PL/SQL.
• DELETE(n) supprime le nième élément d'une table PL/SQL.
• DELETE(m, n) supprime tous les éléments d'une table PL/SQL situés
dans la plage comprise entre m et n.
DECLARE
TYPE emp_table_type IS TABLE OF
employees%ROWTYPE INDEX BY PLS_INTEGER;
my_emp_table emp_table_type;
max_count NUMBER(3):= 104;
BEGIN
FOR i IN 100..max_count
LOOP
SELECT * INTO my_emp_table(i) FROM employees
WHERE employee_id = i;
END LOOP;
FOR i IN my_emp_table.FIRST..my_emp_table.LAST
Tables imbriquées
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
2 Go
Tables imbriquées
Les tables imbriquées ont des fonctionnalités similaires à celles des tables INDEX BY, mais
elles présentent quelques différences dans leur implémentation. Le type de données table
imbriquée est valide dans une table au niveau schéma, contrairement au type table
INDEX BY. La clé ne peut pas avoir une valeur négative (contrairement à celle d'une table
INDEX BY). Bien que la première colonne soit indiquée comme colonne de clé, il n'y a pas de
clé dans une table imbriquée. Il existe une colonne comprenant des nombres ordonnés,
considérée comme la colonne de clé. Les éléments peuvent être supprimés n'importe où dans
une table imbriquée, ce qui donne une table dispersée avec des clés non séquentielles. Les
lignes d'une table imbriquée ne sont définies dans aucun ordre particulier. Lorsque vous
extrayez des valeurs d'une table imbriquée, des indices consécutifs sont affectés aux lignes, en
commençant à 1. Les tables imbriquées peuvent être stockées dans la base de données
(contrairement aux tables INDEX BY).
Syntaxe
TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table.%ROWTYPE
Depuis Oracle Database 10g, les tables imbriquées peuvent faire l'objet d'une comparaison
d'égalité. Vous pouvez vérifier si un élément existe dans une table imbriquée et également si
une table imbriquée est un sous-ensemble d'une autre.
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
10 Tokyo
VARRAY
Un tableau de taille variable (VARRAY) est semblable à une table PL/SQL, à ceci près que sa
taille est soumise à une contrainte. Un VARRAY est valide dans une table de niveau schéma.
Les éléments de type VARRAY sont appelés des VARRAY. Les VARRAY présentent une limite
supérieure fixe. Vous devez indiquer cette limite lorsque vous les déclarez, comme pour les
tableaux en langage C. La taille maximale d'un VARRAY est de 2 Go, comme pour les tables
imbriquées. La distinction entre une table imbriquée et un VARRAY réside dans le mode de
stockage physique. Les éléments d'un VARRAY sont stockés de manière contiguë dans la
mémoire, et non dans la base de données. Il est possible de créer un type VARRAY dans la
base de données à l'aide du langage SQL.
Exemple :
TYPE location_type IS VARRAY(3) OF locations.city%TYPE;
offices location_type;
La taille de ce VARRAY est limitée à 3. Vous pouvez initialiser un VARRAY à l'aide de
constructeurs. Si vous tentez d'initialiser le VARRAY avec plus de trois éléments, vous obtenez
le message d'erreur "Subscript outside of limit".
Synthèse
Synthèse
Un enregistrement PL/SQL est un ensemble de champs représentant une ligne dans une table.
Les enregistrements vous permettent de regrouper des données au sein d'une même structure
et de manipuler cette dernière comme une entité ou une unité logique. Vous pouvez ainsi
limiter l'écriture de code, ce qui facilite la maintenance et la compréhension des programmes.
Comme les enregistrements PL/SQL, la table est un autre type de données composite. Les
tables INDEX BY sont des objets de type TABLE semblables aux tables de base de données,
avec toutefois une légère différence. Les tables INDEX BY utilisent une clé primaire
permettant d'accéder aux lignes comme dans un tableau. Elles ne présentent pas de contrainte
de taille. Les tables INDEX BY contiennent des paires clé-valeur. La colonne de clé doit être
de type entier ou chaîne alors que la colonne contenant la valeur peut être de n'importe quel
type.
Les valeurs de clé d'une table imbriquée ne peuvent pas être négatives, contrairement à celles
d'une table INDEX BY. Par ailleurs, elles doivent être séquentielles.
Les tableaux de taille variable (VARRAY) sont semblables aux tables PL/SQL, à ceci près que
leur taille fait l'objet d'une contrainte.
Présentation de l'exercice 6
Présentation de l'exercice 6
Dans cet exercice, vous allez définir, créer et utiliser des tables INDEX BY, ainsi qu'un
enregistrement PL/SQL.
Exercice 6
1. Ecrivez un bloc PL/SQL permettant d'afficher les informations relatives à un pays donné.
a. Déclarez un enregistrement PL/SQL conforme à la structure de la table countries.
b. Déclarez une variable v_countryid. Affectez CA à v_countryid.
c. Dans la section déclarative, utilisez l'attribut %ROWTYPE et déclarez la variable
v_country_record de type countries.
d. Dans la section exécutable, obtenez toutes les informations de la table countries à l'aide
de countryid. Affichez les informations sélectionnées sur le pays. Voici un exemple de
résultat :
DEPARTMENT_ID DEPARTMENT_NAME
10 Administration
20 Marketing
30 Purchasing
40 Human Resources
50 Shipping
60 IT
70 Public Relations
80 Sales
90 Executive
100 Finance
Exercice 6 (suite)
d. A l'aide d'une autre boucle, extrayez les noms des départements de la table INDEX BY et
affichez-les.
e. Exécutez votre script et enregistrez-le sous le nom lab_06_02_soln.sql. Un exemple
de sortie est affiché ci-après.
Exercice 6 (suite)
3. Modifiez le bloc créé au point 2 afin d'extraire toutes les informations sur les départements de la
table departments et de les afficher. Utilisez une table d'enregistrements INDEX BY.
a. Chargez le script lab_06_02_soln.sql.
b. Vous avez déclaré la table INDEX BY comme étant de type
departments.department_name. Modifiez la déclaration de la table INDEX BY
afin de stocker temporairement le numéro, le nom et l'emplacement des départements.
Utilisez l'attribut %ROWTYPE.
c. Modifiez l'instruction SELECT afin d'extraire toutes les informations relatives aux
départements, actuellement contenues dans la table departments, et stockez celles-ci
dans la table INDEX BY.
d. A l'aide d'une autre boucle, extrayez les informations relatives aux départements de la table
INDEX BY et affichez-les. Voici un exemple de résultat :
Objectifs
But du chapitre
Nous avons étudié les curseurs implicites créés automatiquement par le compilateur PL/SQL
lors de l'exécution d'une instruction SQL SELECT ou d'une instruction LMD. Dans ce
chapitre, vous découvrirez les curseurs explicites. Vous apprendrez à faire la distinction entre
les curseurs implicites et les curseurs explicites. Vous apprendrez également à déclarer et à
contrôler des curseurs simples et des curseurs avec paramètres.
Curseurs
Curseurs
Le serveur Oracle utilise des zones de travail (nommées zones de mémoire SQL privées) pour
exécuter les instructions SQL et assurer le stockage des informations de traitement. Vous
pouvez utiliser des curseurs explicites pour nommer ces zones et accéder aux informations
qu'elles contiennent.
Type de curseur Description
Le serveur Oracle ouvre implicitement un curseur pour traiter chaque instruction SQL non
associée à un curseur explicitement déclaré. Le langage PL/SQL permet de référencer le
curseur implicite le plus récent en tant que curseur SQL.
Table
100 King AD_PRES
101 Kochhar AD_VP
Ensemble actif
102 De Haan AD_VP
. . .
. . .
Non
Oui
DECLARE OPEN FETCH VIDE? CLOSE
1 Ouverture du
curseur
Pointeur
de curseur
2 Extraction
d'une ligne
Pointeur
de curseur
Déclarer un curseur
Syntaxe :
CURSOR cursor_name IS
select_statement;
Exemples :
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
Déclarer un curseur
La syntaxe permettant de déclarer un curseur est présentée dans la diapositive ci-dessus. Dans
la syntaxe :
cursor_name Identificateur PL/SQL.
select_statement Instruction SELECT sans clause INTO.
L'ensemble actif d'un curseur est déterminé par l'instruction SELECT dans la déclaration du
curseur. La clause INTO est obligatoire dans une instruction SELECT en langage PL/SQL.
Cependant, notez que l'instruction SELECT dans la déclaration de curseur ne peut pas
comporter de clause INTO. Cela est dû au fait que vous définissez uniquement un curseur
dans la section déclarative et que vous n'extrayez aucune ligne dans le curseur.
Remarque
• N'incluez pas de clause INTO dans la déclaration du curseur, car elle apparaît plus tard
dans l'instruction FETCH.
• S'il existe un ordre précis de traitement des lignes, utilisez la clause ORDER BY dans
l'interrogation.
• Le curseur peut contenir n'importe quelle instruction SELECT valide, notamment des
jointures, des sous-interrogations, etc.
Ouvrir le curseur
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
...
BEGIN
OPEN c_emp_cursor;
Ouvrir le curseur
L'instruction OPEN exécute l'interrogation associée au curseur, identifie l'ensemble actif et
positionne le pointeur de curseur sur la première ligne. L'instruction OPEN est incluse dans
la section exécutable du bloc PL/SQL.
OPEN est une instruction exécutable qui effectue les opérations suivantes :
1. Elle alloue de manière dynamique de la mémoire pour une zone de contexte.
2. Elle analyse (parse) l'instruction SELECT.
3. Elle attache les variables d'entrée (en d'autres termes, elle fixe la valeur des variables
d'entrée en obtenant leurs adresses mémoire).
4. Elle identifie l'ensemble actif (c'est-à-dire l'ensemble des lignes qui satisfont aux critères
de recherche). Les lignes de l'ensemble actif ne sont pas extraites pour être placées dans
des variables lors de l'exécution de l'instruction OPEN. L'instruction FETCH extrait les
lignes du curseur dans les variables.
5. Elle positionne le pointeur sur la première ligne dans l'ensemble actif.
Remarque : Si une interrogation ne renvoie aucune ligne lorsque le curseur est ouvert,
le code PL/SQL ne déclenche pas d'exception. Vous pouvez connaître le nombre de lignes
renvoyées par un curseur explicite en utilisant l'attribut <cursor_name>%ROWCOUNT.
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN c_emp_cursor;
FETCH c_emp_cursor INTO v_empno, v_lname;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
END;
Vous avez extrait avec succès les valeurs du curseur dans les variables. Cependant, le
département 30 compte six employés alors qu'une seule ligne a été extraite. Pour extraire
toutes les lignes, vous devez utiliser des boucles. La diapositive qui suit montre comment
utiliser une boucle pour extraire toutes les lignes.
L'instruction FETCH effectue les opérations suivantes :
1. Elle lit les données de la ligne en cours et les stocke dans les variables de sortie PL/SQL.
2. Elle fait passer le pointeur à la ligne suivante de l'ensemble actif.
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN c_emp_cursor;
LOOP
FETCH c_emp_cursor INTO v_empno, v_lname;
EXIT WHEN c_emp_cursor%NOTFOUND;
Fermer le curseur
...
LOOP
FETCH c_emp_cursor INTO empno, lname;
EXIT WHEN c_emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
END LOOP;
CLOSE c_emp_cursor;
END;
Fermer le curseur
L'instruction CLOSE désactive le curseur, libère la zone de contexte et annule la définition de
l'ensemble actif. Fermez le curseur après avoir terminé le traitement de l'instruction FETCH.
Vous pouvez rouvrir le curseur si nécessaire. Un curseur ne peut être rouvert que s'il est
fermé. Si vous tentez d'extraire (fetch) des données à partir d'un curseur fermé, une exception
INVALID_CURSOR est générée.
Remarque : Bien qu'il soit possible de terminer le bloc PL/SQL sans fermer les curseurs,
prenez l'habitude de fermer les curseurs que vous déclarez explicitement, afin de libérer
les ressources.
Il existe une limite maximale quant au nombre de curseurs ouverts par session, lequel est
déterminé par le paramètre OPEN_CURSORS dans le fichier de paramètres de la base de
données. (OPEN_CURSORS = 50 par défaut)
Curseurs et enregistrements
Curseurs et enregistrements
Vous venez de voir comment définir des enregistrements possédant la structure des colonnes
d'une table. Vous pouvez également définir un enregistrement en fonction de la liste précise
des colonnes d'un curseur explicite. Cela est très pratique pour traiter les lignes de l'ensemble
actif, car il vous suffit de placer le résultat de l'extraction dans l'enregistrement. Ainsi, les
valeurs de la ligne sont chargées directement dans les champs correspondants de
l'enregistrement.
Syntaxe :
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
BEGIN
FOR emp_record IN c_emp_cursor
LOOP
DBMS_OUTPUT.PUT_LINE( emp_record.employee_id
||' ' ||emp_record.last_name);
Attribut %ISOPEN
• Vous ne pouvez extraire des lignes que lorsque le curseur est ouvert. Utilisez l'attribut de
curseur %ISOPEN pour déterminer si le curseur est ouvert.
• Procédez à l'extraction des lignes à l'aide d'une boucle. Utilisez des attributs de curseur
pour déterminer dans quels cas la sortie de la boucle doit s'effectuer.
• Utilisez l'attribut de curseur %ROWCOUNT pour effectuer les tâches suivantes :
- Traiter un nombre exact de lignes
- Extraire des lignes avec une boucle et déterminer dans quels cas la sortie de la
boucle doit s'effectuer
Remarque : %ISOPEN renvoie l'état du curseur (TRUE s'il est ouvert et FALSE s'il est
fermé).
DECLARE
CURSOR c_emp_cursor IS SELECT employee_id,
last_name FROM employees;
v_emp_record c_emp_cursor%ROWTYPE;
BEGIN
OPEN c_emp_cursor;
LOOP
FETCH c_emp_cursor INTO v_emp_record;
EXIT WHEN c_emp_cursor%ROWCOUNT > 10 OR
c_emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_emp_record.employee_id
||' '||v_emp_record.last_name);
des sous-interrogations
Syntaxe :
CURSOR cursor_name
[(parameter_name datatype, ...)]
IS
select_statement;
• Transmettez des paramètres au curseur au moment de
son ouverture et de l'exécution de l'interrogation.
• Ouvrez un curseur explicite à plusieurs reprises, en
renvoyant un ensemble actif différent à chaque fois.
DECLARE
CURSOR c_emp_cursor (deptno NUMBER) IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = deptno;
...
BEGIN
OPEN c_emp_cursor (10);
...
Syntaxe :
SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
L'instruction SELECT ... FOR UPDATE identifie les lignes qui doivent être mises à jour ou
supprimées, puis verrouille chaque ligne de l'ensemble de résultats. Cela s'avère utile lorsque vous
souhaitez qu'une mise à jour soit basée sur les valeurs existantes d'une ligne. Dans ce cas, vous devez
vous assurer que cette ligne n'est pas modifiée par une autre session avant la mise à jour.
Le mot-clé facultatif NOWAIT indique au serveur Oracle de ne pas attendre si les lignes demandées
sont verrouillées par un autre utilisateur. Le programme reprend immédiatement le contrôle. Il peut
ainsi effectuer d'autres travaux avant de réessayer d'obtenir le verrouillage. Si vous omettez le
mot-clé NOWAIT, le serveur Oracle attend que les lignes soient disponibles.
Exemple :
DECLARE
CURSOR c_emp_cursor IS
SELECT employee_id, last_name, FROM employees
WHERE department_id = 80 FOR UPDATE OF salary NOWAIT;
Syntaxe :
WHERE CURRENT OF cursor ;
• Utilisez des curseurs pour mettre à jour ou supprimer
la ligne en cours.
• Incluez la clause FOR UPDATE dans l'interrogation
du curseur pour verrouiller au préalable les lignes.
• Utilisez la clause WHERE CURRENT OF pour référencer
la ligne en cours à partir d'un curseur explicite.
Exemple :
DECLARE
CURSOR my_cursor IS
SELECT t1.department_id, t1.department_name,
t2.staff
FROM departments t1, (SELECT department_id,
COUNT(*) AS staff
FROM employees
GROUP BY department_id) t2
Synthèse
Synthèse
Le serveur Oracle utilise des zones de travail pour exécuter les instructions SQL et assurer le
stockage des informations relatives au traitement. Vous pouvez utiliser une structure PL/SQL
appelée curseur pour nommer une zone de travail et accéder aux informations qu'elle
contient. Il existe deux types de curseur : les curseurs implicites et les curseurs explicites.
Le compilateur PL/SQL déclare implicitement un curseur pour toutes les instructions SQL de
manipulation de données, y compris pour les interrogations ne renvoyant qu'une seule ligne.
Pour les interrogations renvoyant plusieurs lignes, vous pouvez explicitement déclarer un
curseur afin de traiter les lignes individuellement.
Les curseurs explicites et les variables de curseur admettent quatre attributs : %FOUND,
%ISOPEN %NOTFOUND et %ROWCOUNT. Une fois associés au nom d'une variable de curseur,
ces attributs renvoient des informations utiles sur l'exécution d'une instruction SQL. Vous
pouvez utiliser les attributs de curseur dans les instructions procédurales, mais pas dans les
instructions SQL.
Utilisez des boucles simples ou des boucles FOR de curseur pour opérer sur les différentes
lignes extraites par un curseur. Si vous utilisez des boucles simples, vous devez ouvrir,
extraire (fetch) et fermer le curseur. En revanche, les boucles FOR de curseur effectuent ces
opérations implicitement. Lorsque vous procédez à la mise à jour ou à la suppression de
lignes, verrouillez ces lignes à l'aide d'une clause FOR UPDATE. De la sorte, les données que
vous utilisez ne risquent pas d'être mises à jour par une autre session après l'ouverture du
curseur. Utilisez une clause WHERE CURRENT OF avec la clause FOR UPDATE afin de
référencer la ligne actuelle extraite par le curseur.
Présentation de l'exercice 7
Présentation de l'exercice 7
Dans cet exercice, vous allez mettre en pratique vos connaissances sur les curseurs pour traiter
un certain nombre de lignes à partir d'une table. Les résultats seront ensuite utilisés pour
remplir une autre table à l'aide d'une boucle FOR de curseur. Enfin, vous écrirez un curseur
avec des paramètres.
Exercice 7
1. Créez un bloc PL/SQL qui détermine les n salaires les plus élevés parmi les employés.
a. Exécutez le script lab_07_01.sql afin de créer une nouvelle table nommée
top_salaries, pour le stockage des salaires des employés.
b. Dans la section déclarative, déclarez une variable v_num de type NUMBER contenant un
nombre n qui représente le nombre n d'employés ayant les salaires les plus élevés dans la
table employees. Par exemple, pour afficher les cinq salaires les plus élevés, entrez 5.
Déclarez une autre variable sal de type employees.salary. Déclarez le curseur
c_emp_cursor qui extrait les salaires des employés par ordre décroissant.
c. Dans la section exécutable, ouvrez la boucle, extrayez les n salaires les plus élevés et
insérez-les dans la table top_salaries. Vous pouvez utiliser une boucle simple pour
opérer sur les données. Essayez également d'utiliser les attributs %ROWCOUNT et %FOUND
pour la condition de sortie.
d. Après l'insertion dans la table top_salaries, affichez les lignes avec une instruction
e. Testez les cas particuliers tels que v_num = 0 ou v_num supérieur au nombre d'employés
de la table employees. Videz la table top_salaries après chaque test.
2. Créez un bloc PL/SQL pour effectuer les tâches suivantes :
a. Dans la section déclarative, déclarez une variable v_deptno de type NUMBER et
affectez-lui la valeur contenant le numéro du département.
b. Déclarez un curseur nommé c_emp_cursor qui extrait les valeurs last_name,
salary et manager_id pour les employés qui travaillent dans le département indiqué
par v_deptno.
Exercice 7 (suite)
c. Dans la section exécutable, utilisez la boucle FOR de curseur pour opérer sur les données
extraites. Si le salaire de l'employé est inférieur à 5 000 et que l'ID du manager est 101 ou
124, affichez le message suivant : <<last_name>> Due for a raise. Dans le cas
contraire, affichez le message suivant : <<last_name>> Not due for a raise.
d. Testez les cas suivants à l'aide du bloc PL/SQL :
Numéro de Message
département
10 Whalen Due for a raise
20 Hartstein Not Due for a raise
Fay Not Due for a raise
50 Weiss Not Due for a raise
Fripp Not Due for a raise
Exercice 7 (suite)
3. Ecrivez un bloc PL/SQL qui déclare et utilise des curseurs avec des paramètres.
Dans une boucle, utilisez un curseur pour extraire, à partir de la table departments, le
numéro et le nom de tous les départements pour lesquels la valeur department_id est
inférieure à 100. Transmettez le numéro du département à un autre curseur en tant que
paramètre pour extraire de la table employees les informations (nom de famille, poste, date
d'embauche et salaire) concernant les employés travaillant dans ce département et dont la
valeur employee_id est inférieure à 120.
a. Dans la section déclarative, déclarez un curseur nommé dept_cursor afin d'extraire les
valeurs department_id et department_name pour les départements dont la valeur
department_id est inférieure à 100. Triez le résultat en fonction de la valeur
department_id.
b. Déclarez un autre curseur nommé emp_cursor, qui accepte le numéro de département
comme paramètre et qui extrait les valeurs last_name, job_id, hire_date et
Exercice 7 (suite)
Le résultat est présenté ci-après.
Objectifs
But du chapitre
Vous avez appris à écrire des blocs PL/SQL contenant une section déclarative et une section
exécutable. Tout le code SQL et PL/SQL à exécuter est écrit dans le bloc exécutable.
Jusqu'à présent, il a été considéré que le code fonctionnait correctement dès lors que les
erreurs détectées au moment de la compilation étaient corrigées. Cependant, le code peut
provoquer des erreurs non prévues lors de l'exécution. Dans ce chapitre, vous allez apprendre
à gérer ce type d'erreur dans un bloc PL/SQL.
Exemple d'exception
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees
WHERE first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is :'
||v_lname);
END;
Exemple d'exception
Examinez l'exemple de la diapositive ci-dessus. Le code ne présente aucune erreur de syntaxe,
ce qui veut dire que vous devez pouvoir exécuter avec succès le bloc anonyme. L'instruction
SELECT du bloc extrait le nom de famille de John. Lorsque vous exécutez le code, vous
obtenez la sortie ci-après :
Le code ne fonctionne pas comme prévu. Vous aviez prévu que l'instruction SELECT
n'extrairait qu'une seule ligne. Or, elle en a extrait plusieurs. Ce type d'erreur qui se produit
lors de l'exécution est appelé une exception. Lorsqu'une exception se produit, l'exécution du
bloc PL/SQL prend fin. Vous pouvez gérer ce type d'exception dans le bloc PL/SQL.
Exemple d'exception
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees
WHERE first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is :'
||v_lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
L'exception Interrompre
est-elle brutalement
interceptée ? Non l'exécution
Oui
Interrompre
correctement
l'exécution
Types d'exception
}
• Exception prédéfinie du serveur Oracle Exception
• Exception non prédéfinie du serveur Oracle déclenchée
implicitement
Exception
• Exception définie par l'utilisateur déclenchée
explicitement
Types d'exception
Il existe trois types d'exception.
Remarque : Certains outils applicatifs dotés d'une interface PL/SQL côté client (par exemple
Oracle Developer Forms) possèdent leurs propres exceptions.
Syntaxe :
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
statement2;
. . .
[WHEN exception3 [OR exception4 . . .] THEN
statement1;
statement2;
Exceptions prédéfinies
SQLCODE Renvoie la valeur numérique du code d'erreur (que vous pouvez affecter
à une variable NUMBER).
SQLERRM Renvoie une donnée de type caractère contenant le message associé au
code d'erreur.
Exemple
DECLARE
error_code NUMBER;
error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
error_code := SQLCODE ;
DECLARE
v_deptno NUMBER := 500;
v_name VARCHAR2(20) := 'Testing';
e_invalid_department EXCEPTION;
1
BEGIN
UPDATE departments
SET department_name = v_name
WHERE department_id = v_deptno;
IF SQL % NOTFOUND THEN
RAISE e_invalid_department; 2
END IF;
DECLARE
. . .
e_no_rows exception;
e_integrity exception;
PRAGMA EXCEPTION_INIT (e_integrity, -2292);
BEGIN
FOR c_record IN emp_cursor LOOP
BEGIN
Des sous-blocs
SELECT ...
peuvent traiter UPDATE ...
une exception ou IF SQL%NOTFOUND THEN
la transmettre à RAISE e_no_rows;
un bloc englobant. END IF;
Syntaxe :
raise_application_error (error_number,
message[, {TRUE | FALSE}]);
Procédure RAISE_APPLICATION_ERROR
Grâce à la procédure RAISE_APPLICATION_ERROR, générez de manière interactive une
exception prédéfinie en renvoyant un code et un message d'erreur non standard. La procédure
RAISE_APPLICATION_ERROR permet de signaler les erreurs à l'application et d'éviter le
renvoi d'exceptions non traitées.
Dans la syntaxe :
error_number Valeur numérique définie par l'utilisateur pour l'exception, comprise
entre –20 000 et –20 999.
message Message défini par l'utilisateur pour l'exception. Il s'agit d'une chaîne
de caractères pouvant contenir jusqu'à 2 048 octets.
TRUE | FALSE Paramètre booléen facultatif. Si la valeur est TRUE, l'erreur est
placée dans 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.
Section exécutable :
BEGIN
...
DELETE FROM employees
WHERE manager_id = v_mgr;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,
'This is not a valid manager');
END IF;
...
Synthèse
Synthèse
Dans ce chapitre, vous avez appris à traiter différents types d'exception. En langage PL/SQL,
une exception est une condition d'avertissement ou d'erreur. Les exceptions prédéfinies sont
des conditions d'erreur définies par le serveur Oracle. Les exceptions non prédéfinies peuvent
être n'importe quelle erreur standard du serveur Oracle. Les exceptions définies par
l'utilisateur sont des exceptions propres à une application. La fonction PRAGMA
EXCEPTION_INIT peut être utilisée pour associer un nom d'exception déclaré à une erreur
du serveur Oracle.
Vous pouvez définir vos propres exceptions dans la section déclarative d'un bloc PL/SQL.
Par exemple, vous pouvez définir une exception nommée INSUFFICIENT_FUNDS pour
mettre en évidence les comptes bancaires à découvert.
Lorsqu'une erreur se produit dans un programme, une exception est déclenchée. L'exécution
normale est interrompue et le contrôle est transféré à la section de traitement des exceptions
du bloc PL/SQL. Les exceptions internes sont générées implicitement (automatiquement) par
le système d'exécution. En revanche, les exceptions définies par l'utilisateur doivent être
générées explicitement. Pour traiter des exceptions déclenchées, vous devez écrire des
sous-programmes distincts appelés gestionnaires d'exceptions.
Présentation de l'exercice 8
Présentation de l'exercice 8
Dans cet exercice, vous allez créer des gestionnaires d'exceptions pour des situations
particulières.
Exercice 8
1. Ce point illustre l'utilisation des exceptions prédéfinies. Ecrivez un bloc PL/SQL permettant de
sélectionner le nom d'un employé en fonction de son salaire.
a. Supprimez tous les enregistrements de la table messages.
b. Dans la section déclarative, déclarez deux variables : v_ename de type
employees.last_name et v_emp_sal de type employees.salary. Initialisez
cette dernière variable avec la valeur 6000.
c. Dans la section exécutable, extrayez le nom des employés dont le salaire est égal à la valeur
de v_emp_sal.
Remarque : N'utilisez pas de curseurs explicites.
Si une seule ligne est renvoyée pour le salaire entré, insérez dans la table messages le
nom de l'employé et le montant de son salaire.
d. Si aucune ligne n'est renvoyée pour le salaire entré, traitez l'exception à l'aide d'un
gestionnaire approprié et insérez dans la table messages le message "No employee with a
2. Ce point montre comment déclarer des exceptions avec une erreur standard du serveur Oracle.
Utilisez l'erreur ORA-02292 du serveur Oracle (integrity constraint violated –
child record found).
a. Dans la section déclarative, déclarez l'exception e_childrecord_exists. Associez
l'exception déclarée au code d'erreur standard –02292 du serveur Oracle.
b. Dans la section exécutable, affichez "Deleting department 40.....". Incluez une instruction
DELETE afin de supprimer le département dont la valeur department_id est 40.
Exercice 8 (suite)
c. Incluez une section de traitement des exceptions afin de traiter l'exception
e_childrecord_exists et d'afficher le message approprié. Voici un exemple
de résultat :
Objectifs
But du chapitre
Nous avons précédemment étudié les blocs anonymes. Nous allons maintenant étudier
les blocs nommés, également appelés sous-programmes. Les procédures et les fonctions sont
des sous-programmes PL/SQL. Dans ce chapitre, vous apprendrez à faire la distinction entre
les blocs anonymes et les sous-programmes.
Procédures et fonctions
Procédures et fonctions
Les seuls exemples de code PL/SQL étudiés jusqu'à présent dans ce cours sont les blocs
anonymes. Comme leur nom l'indique, les blocs anonymes sont des blocs PL/SQL
exécutables non nommés. Etant donné qu'ils n'ont pas de nom, ils ne peuvent être ni réutilisés,
ni stockés pour une utilisation ultérieure.
Les procédures et les fonctions sont des blocs PL/SQL nommés. Elles sont également
appelées sous-programmes. Les sous-programmes sont compilés et stockés dans la base de
données. La structure de bloc des sous-programmes est semblable à la structure des blocs
anonymes. Les sous-programmes peuvent être déclarés non seulement au niveau schéma,
mais également dans n'importe quel autre bloc PL/SQL. Un sous-programme contient les
sections suivantes :
Section déclarative : Les sous-programmes peuvent comporter une section déclarative
facultative. En revanche, cette section ne commence pas par le mot-clé DECLARE,
contrairement à celle des blocs anonymes. La section déclarative facultative suit le mot-clé
IS ou AS dans la déclaration du sous-programme.
Section exécutable : Il s'agit d'une section obligatoire du sous-programme, qui contient
l'implémentation de la logique métier. L'examen de son code permet de déterminer facilement
les fonctionnalités métier du sous-programme. Cette section commence et se termine
respectivement par les mots-clés BEGIN et END.
Section de traitement des exceptions : Il s'agit d'une section facultative permettant de traiter
les exceptions.
Procédure : Syntaxe
Procédure : Syntaxe
La diapositive ci-dessus présente la syntaxe permettant de créer des procédures. Dans la
syntaxe :
procedure_name Nom de la procédure à créer.
argument Nom affecté au paramètre de la procédure. Chaque argument est
associé à un mode et à un type de données. Vous pouvez indiquer
un nombre quelconque d'arguments, séparés par des virgules.
mode Mode de l'argument :
IN (par défaut)
OUT
IN OUT
datatype Type de données du paramètre associé. Le type de données des
paramètres ne peut pas présenter de taille explicite. Utilisez
%TYPE.
Procedure_body Bloc PL/SQL qui constitue le code.
La liste des arguments est facultative dans la déclaration d'une procédure. Pour en savoir plus
sur les procédures, reportez-vous au cours intitulé Oracle Database 10g : Objets procéduraux
basés d'Oracle.
Procédure : Exemple
...
CREATE TABLE dept AS SELECT * FROM departments;
CREATE PROCEDURE add_dept IS
v_dept_id dept.department_id%TYPE;
v_dept_name dept.department_name%TYPE;
BEGIN
v_dept_id:=280;
v_dept_name:='ST-Curriculum';
Procédure : Exemple
Examinez le code de la diapositive ci-dessus. La procédure add_dept insère un nouveau
département avec le numéro de département 280 et le nom de département
ST-Curriculum. Elle déclare deux variables, à savoir dept_id et dept_name, dans la
section déclarative. La section déclarative d'une procédure commence immédiatement après
la déclaration de celle-ci. Elle ne commence pas par le mot-clé DECLARE. La procédure
utilise l'attribut de curseur implicite ou l'attribut SQL SQL%ROWCOUNT pour vérifier si la
ligne a été insérée avec succès. SQL%ROWCOUNT doit renvoyer la valeur 1 dans ce cas.
Remarque : Lorsque vous créez un objet quelconque (tel qu'une table, une procédure ou une
fonction), les entrées correspondantes sont créées dans la table user_objects. Lorsque le
code de la diapositive est exécuté avec succès, vous pouvez examiner le contenu de la table
user_objects en exécutant la commande suivante :
SELECT object_name,object_type FROM user_objects;
Appeler la procédure
BEGIN
add_dept;
END;
/
SELECT department_id, department_name FROM dept
WHERE department_id=280;
Appeler la procédure
La diapositive ci-dessus montre comment appeler une procédure à partir d'un bloc anonyme.
Vous devez inclure l'appel de la procédure dans la section exécutable du bloc anonyme. De la
même façon, vous pouvez appeler la procédure à partir de n'importe quelle application, telle
qu'une application Forms, une application Java, etc. L'instruction SELECT du code vérifie si
la ligne a été insérée avec succès.
Vous pouvez également appeler une procédure avec l'instruction SQL CALL
<procedure_name>.
Fonction : Syntaxe
Fonction : Syntaxe
La diapositive ci-dessus présente la syntaxe de création d'une fonction. Dans la syntaxe :
function_name Nom de la fonction à créer.
argument Nom affecté au paramètre de la fonction (chaque argument est
associé à un mode et à un type de données). Vous pouvez indiquer
un nombre quelconque d'arguments, séparés par des virgules.
Vous transmettez l'argument lors de l'appel de la fonction.
mode Type de paramètre (seuls les paramètres IN doivent être déclarés.)
datatype Type de données du paramètre associé.
Fonction : Exemple
CREATE FUNCTION check_sal RETURN Boolean IS
v_dept_id employees.department_id%TYPE;
v_empno employees.employee_id%TYPE;
v_sal employees.salary%TYPE;
v_avg_sal employees.salary%TYPE;
BEGIN
v_empno:=205;
SELECT salary,department_id INTO v_sal,v_dept_id FROM
employees
WHERE employee_id = v_empno;
SELECT avg(salary) INTO v_avg_sal FROM employees WHERE
department_id=v_dept_id;
IF v_sal > v_avg_sal THEN
RETURN TRUE;
Fonction : Exemple
La fonction check_sal permet de déterminer si le salaire d'un employé est supérieur ou
inférieur au salaire moyen de tous les employés travaillant dans le même département. La
fonction renvoie TRUE si le salaire de l'employé est supérieur au salaire moyen des employés
du département. Sinon, elle renvoie FALSE. La fonction renvoie NULL si une exception
NO_DATA_FOUND est générée.
Notez que la fonction effectue la vérification pour l'employé dont l'ID est 205. La vérification
est codée en dur pour cet ID uniquement. Si vous souhaitez effectuer la vérification pour tout
autre employé, vous devez modifier la fonction proprement dite. Vous pouvez résoudre ce
problème en déclarant la fonction de sorte qu'elle accepte un argument. Vous pouvez ensuite
transmettre l'ID de l'employé en tant que paramètre.
BEGIN
IF (check_sal IS NULL) THEN
DBMS_OUTPUT.PUT_LINE('The function returned
NULL due to exception');
ELSIF (check_sal) THEN
DBMS_OUTPUT.PUT_LINE('Salary > average');
ELSE
DBMS_OUTPUT.PUT_LINE('Salary < average');
END IF;
Synthèse
Synthèse
Vous pouvez utiliser des blocs anonymes pour inclure des fonctionnalités en langage PL/SQL.
Cependant, la principale contrainte des blocs anonymes est qu'ils ne sont pas stockés et ne
peuvent donc pas être réutilisés.
Plutôt que de créer des blocs anonymes, vous pouvez créer des sous-programmes PL/SQL.
Les procédures et les fonctions sont appelées des sous-programmes, lesquels sont des blocs
PL/SQL nommés. La logique des sous-programmes peut être réutilisée grâce aux paramètres.
La structure d'une procédure ou d'une fonction est semblable à la structure d'un bloc anonyme.
Ces sous-programmes sont stockés dans la base de données et peuvent donc être réutilisés.
Présentation de l'exercice 9
Exercice 9
1. Chargez le script lab_02_04_soln.sql que vous avez créé au point 4 de l'exercice 2.
a. Modifiez le script afin de convertir le bloc anonyme en procédure nommée greet.
b. Exécutez le script afin de créer la procédure.
c. Enregistrez le script sous le nom lab_09_01_soln.sql.
d. Cliquez sur le bouton Clear afin de vider l'espace de travail.
e. Créez et exécutez un bloc anonyme afin d'appeler la procédure greet. Voici un exemple
de résultat :
__________________
__________________
A
Solutions des exercices
Le dossier labs est le répertoire de travail où vous sauvegardez vos scripts. Demandez au
formateur de vous aider à localiser le dossier labs pour ce cours. Les solutions de tous les
exercices se trouvent dans le dossier soln.
a. BEGIN
END;
b. DECLARE
amount INTEGER(10);
END;
c. DECLARE
d. DECLARE
amount INTEGER(10);
BEGIN
DBMS_OUTPUT.PUT_LINE(amount);
END;
2. Créez et exécutez un bloc anonyme simple qui affiche "Hello World". Exécutez ce script
et enregistrez-le sous le nom lab_01_02_soln.sql.
a. Démarrez SQL Developer. Les informations nécessaires vous seront fournies par
votre formateur.
b. Activez la sortie dans SQL Developer en cliquant sur le bouton Enable DBMS
Output, dans l'onglet DBMS Output.
Enable DBMS
DBMS Output
Output
Tab
BEGIN
DBMS_OUTPUT.PUT_LINE(' Hello World ');
END;
f. Cliquez sur le bouton Save. Sélectionnez le dossier dans lequel vous souhaitez
enregistrer le fichier. Entrez le nom lab_01_02_soln.sql et cliquez sur le
bouton Save.
La déclaration b n'est pas valide, car les variables de type constante doivent être
initialisées lors de la déclaration.
La déclaration c n'est pas valide, car les littéraux de type chaîne doivent être indiqués
entre apostrophes.
DECLARE
v_today DATE:=SYSDATE;
v_tomorrow v_today%TYPE;
BEGIN
v_tomorrow:=v_today +1;
DBMS_OUTPUT.PUT_LINE(' Hello World ');
DBMS_OUTPUT.PUT_LINE('TODAY IS : '|| v_today);
DBMS_OUTPUT.PUT_LINE('TOMORROW IS : ' || v_tomorrow);
END;
c. Terminez le bloc PL/SQL avec "/" et affichez la valeur des variables attachées à
l'aide de la commande PRINT.
OU
DECLARE
v_weight NUMBER(3) := 600;
v_message VARCHAR2(255) := 'Product 10012';
BEGIN
DECLARE
v_weight NUMBER(3) := 1;
v_message VARCHAR2(255) := 'Product 11001';
v_new_locn VARCHAR2(50) := 'Europe';
BEGIN
v_weight := v_weight + 1;
v_new_locn := 'Western ' || v_new_locn;
1
END;
v_weight := v_weight + 1;
v_message := v_message || ' is in stock';
2. Dans le bloc PL/SQL qui précède, déterminez les valeurs et les types de données pour
chacun des cas suivants.
3. Utilisez la même session que celle qui a servi à exécuter les exercices du chapitre
"Déclarer des variables PL/SQL". Si vous avez ouvert une nouvelle session, exécutez le
script lab_02_05_soln.sql. Editez le fichier lab_02_05_soln.sql.
a. Mettez en commentaire les lignes de création des variables attachées (bind
variables), en utilisant la syntaxe de commentaire monoligne.
/*:b_basic_percent:=45;
:b_pf_percent:=12;*/
DECLARE
v_basic_percent NUMBER:=45;
v_pf_percent NUMBER:=12;
v_fname VARCHAR2(15);
e. Modifiez la ligne qui affiche "Hello World" afin d'afficher "Hello" et le prénom.
Si vous le souhaitez, vous pouvez mettre en commentaire les lignes qui affichent
les dates et afficher les variables attachées.
1. Créez un bloc PL/SQL qui sélectionne l'ID de département le plus grand dans la table
departments et qui le stocke dans la variable v_max_deptno. Affichez l'ID de
département le plus élevé.
a. Déclarez une variable nommée v_max_deptno de type NUMBER dans la section
déclarative.
DECLARE
v_max_deptno NUMBER;
BEGIN
v_dept_id := 10 + v_max_deptno;
…
…
INSERT INTO departments (department_id, department_name,
location_id)
VALUES (v_dept_id,v_dept_name, NULL);
…
/
SELECT * FROM departments WHERE department_id= 280;
3. Dans l'exercice 2, vous avez affecté la valeur NULL à location_id. Créez un bloc
PL/SQL qui met à jour location_id avec la valeur 3000 pour le nouveau
département. Utilisez la variable attachée dept_id pour mettre à jour la ligne.
a. Si vous avez démarré une nouvelle session, supprimez le département que vous
avez ajouté à la table departments et exécutez le script
lab_04_02_soln.sql.
BEGIN
UPDATE departments SET location_id=3000 WHERE
department_id=280;
c. Terminez le bloc exécutable par le mot-clé END. Terminez le bloc PL/SQL par "/"
et incluez une instruction SELECT afin d'afficher le département que vous avez
mis à jour.
END;
/
SELECT * FROM departments WHERE department_id=280;
1 rows selected
1 rows deleted
BEGIN
FOR i in 1..10 LOOP
IF i = 6 or i = 8 THEN
null;
ELSE
INSERT INTO messages(results)
VALUES (i);
END IF;
END LOOP;
2. Exécutez le script lab_05_02.sql. Ce script crée une table emp qui est une réplique
de la table employees. Il modifie la table emp afin d'ajouter une nouvelle colonne,
stars, de type VARCHAR2 et de taille 50. Créez un bloc PL/SQL qui insère un
astérisque dans la colonne stars pour chaque tranche de 1000 $ du salaire de l'employé.
Enregistrez le script sous le nom lab_05_02_soln.sql.
a. Dans la section déclarative du bloc, déclarez la variable v_empno de type
emp.employee_id et initialisez-la avec la valeur 176. Déclarez la variable
v_asterisk de type emp.stars et initialisez-la à NULL. Créez la variable
sal de type emp.salary.
FOR i IN 1..v_sal
LOOP
v_asterisk := v_asterisk ||'*';
d. Affichez la ligne de la table emp afin de vérifier que le bloc PL/SQL s'est exécuté
correctement.
1. Ecrivez un bloc PL/SQL permettant d'afficher les informations relatives à un pays donné.
a. Déclarez un enregistrement PL/SQL conforme à la structure de la table
countries.
b. Déclarez une variable v_countryid. Affectez CA à v_countryid.
v_country_record countries%ROWTYPE;
BEGIN
SELECT *
INTO v_country_record
FROM countries
WHERE country_id = UPPER(v_countryid);
END;
e. Vous pouvez exécuter et tester le bloc PL/SQL pour les pays dont l'ID est DE, UK
et US.
DECLARE
TYPE dept_table_type is table of departments.department_name%TYPE
INDEX BY PLS_INTEGER;
my_dept_table dept_table_type;
DEPARTMENT_ID DEPARTMENT_NAME
10 Administration
20 Marketing
30 Purchasing
40 Human Resources
50 Shipping
60 IT
70 Public Relations
80 Sales
90 Executive
100 Finance
BEGIN
FOR i IN 1..f_loop_count
LOOP
v_deptno:=v_deptno+10;
SELECT department_name
INTO my_dept_table(i)
FROM departments
WHERE department_id = v_deptno;
END LOOP;
FOR i IN 1..f_loop_count
LOOP
DBMS_OUTPUT.PUT_LINE (my_dept_table(i));
END LOOP;
END;
c. Modifiez l'instruction SELECT afin d'extraire toutes les informations relatives aux
départements, actuellement contenues dans la table departments, et stockez
celles-ci dans la table INDEX BY.
BEGIN
FOR i IN 1..f_loop_count
LOOP
v_deptno := v_deptno + 10;
SELECT *
FOR i IN 1..f_loop_count
LOOP
DBMS_OUTPUT.PUT_LINE ('Department Number: ' ||
my_dept_table(i).department_id
|| ' Department Name: ' || my_dept_table(i).department_name
|| ' Manager Id: '|| my_dept_table(i).manager_id
|| ' Location Id: ' || my_dept_table(i).location_id);
END LOOP;
END;
1. Créez un bloc PL/SQL qui détermine les n salaires les plus élevés parmi les employés.
a. Exécutez le script lab_07_01.sql afin de créer une nouvelle table nommée
top_salaries, pour le stockage des salaires des employés.
b. Dans la section déclarative, déclarez une variable v_num de type NUMBER
contenant un nombre n qui représente le nombre n d'employés ayant les salaires
les plus élevés dans la table employees. Par exemple, pour afficher les cinq
salaires les plus élevés, entrez 5. Déclarez une autre variable sal de type
employees.salary. Déclarez le curseur c_emp_cursor qui extrait les
salaires des employés par ordre décroissant. Rappelez-vous que les salaires ne
doivent pas être dupliqués.
DECLARE
v_num NUMBER(3) := 5;
c. Dans la section exécutable, ouvrez la boucle, extrayez les n salaires les plus élevés
et insérez-les dans la table top_salaries. Vous pouvez utiliser une boucle
simple pour opérer sur les données. Essayez également d'utiliser les attributs
%ROWCOUNT et %FOUND pour la condition de sortie.
BEGIN
OPEN c_emp_cursor;
FETCH c_emp_cursor INTO v_sal;
WHILE c_emp_cursor%ROWCOUNT <= v_num AND c_emp_cursor%FOUND LOOP
INSERT INTO top_salaries (salary)
VALUES (v_sal);
FETCH c_emp_cursor INTO v_sal;
END LOOP;
CLOSE c_emp_cursor;
END;
la table employees.
/
SELECT * FROM top_salaries;
e. Testez les cas particuliers tels que v_num = 0 ou v_num supérieur au nombre
DECLARE
v_deptno NUMBER := 10;
CURSOR c_emp_cursor IS
SELECT last_name, salary,manager_id
FROM employees
WHERE department_id = v_deptno;
c. Dans la section exécutable, utilisez la boucle FOR de curseur pour opérer sur les
données extraites. Si le salaire de l'employé est inférieur à 5 000 et que l'ID du
manager est 101 ou 124, affichez le message suivant : <<last_name>> Due for a
raise. Dans le cas contraire, affichez le message suivant : <<last_name>> Not due
for a raise.
Department ID Message
3. Ecrivez un bloc PL/SQL qui déclare et utilise des curseurs avec des paramètres.
Dans une boucle, utilisez un curseur pour extraire, à partir de la table departments, le
numéro et le nom de tous les départements pour lesquels la valeur department_id est
inférieure à 100. Transmettez le numéro du département à un autre curseur en tant que
paramètre pour extraire de la table employees les informations (nom de famille, poste,
date d'embauche et salaire) concernant les employés travaillant dans ce département et
dont la valeur employee_id est inférieure à 120.
DECLARE
CURSOR c_dept_cursor IS
SELECT department_id,department_name
FROM departments
WHERE department_id < 100
ORDER BY department_id;
c. Déclarez des variables contenant les valeurs extraites de chaque curseur. Utilisez
l'attribut %TYPE dans la déclaration des variables.
v_current_deptno departments.department_id%TYPE;
v_current_dname departments.department_name%TYPE;
v_ename employees.last_name%TYPE;
v_job employees.job_id%TYPE;
v_hiredate employees.hire_date%TYPE;
v_sal employees.salary%TYPE;
BEGIN
OPEN c_dept_cursor;
LOOP
FETCH c_dept_cursor INTO v_current_deptno,v_current_dname;
EXIT WHEN c_dept_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ('Department Number : ' ||
v_current_deptno || ' Department Name : ' || v_current_dname);
END IF;
OPEN c_emp_cursor (v_current_deptno);
LOOP
FETCH c_emp_cursor INTO v_ename,v_job,v_hiredate,v_sal;
EXIT WHEN c_emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (v_ename || ' ' || v_job
|| ' ' || v_hiredate || ' ' || v_sal);
END LOOP;
DBMS_OUTPUT.PUT_LINE('-----------------------------------------------
-----------------------------------------');
CLOSE c_emp_cursor;
f. Fermez toutes les boucles et tous les curseurs, puis terminez la section exécutable.
Exécutez le script.
1. Cet exercice illustre l'utilisation des exceptions prédéfinies. Ecrivez un bloc PL/SQL
permettant de sélectionner le nom d'un employé en fonction de son salaire.
a. Supprimez tous les enregistrements de la table messages.
DECLARE
v_ename employees.last_name%TYPE;
v_emp_sal employees.salary%TYPE := 6000;
BEGIN
SELECT last_name
INTO v_ename
FROM employees
WHERE salary = v_emp_sal;
INSERT INTO messages (results)
VALUES (v_ename || ' - ' || v_emp_sal);
EXCEPTION
WHEN no_data_found THEN
INSERT INTO messages (results)
VALUES ('No employee with a salary of '|| TO_CHAR(v_emp_sal));
e. Si plusieurs lignes sont renvoyées pour le salaire entré, traitez l'exception à l'aide
d'un gestionnaire approprié et insérez dans la table messages le message "More
than one employee with a salary of <salary>".
WHEN too_many_rows THEN
INSERT INTO messages (results)
VALUES ('More than one employee with a salary of '||
TO_CHAR(v_emp_sal));
/
SELECT * FROM messages;
DECLARE
e_childrecord_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);
BEGIN
DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
delete from departments where department_id=40;
EXCEPTION
WHEN e_childrecord_exists THEN
DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There are
employees in this department (child records exist.) ');
END;
BEGIN
greet;
END;
BEGIN
tomorrow:=today +1;
DBMS_OUTPUT.PUT_LINE(' Hello '|| p_name);
BEGIN
greet('Neema');
END;
DIAGRAMME ENTITE/RELATION
Tables du schéma
SELECT * FROM tab;
Table regions
DESCRIBE regions
Table countries
DESCRIBE countries
Table locations
DESCRIBE locations;
Table departments
DESCRIBE departments
Table jobs
DESCRIBE jobs
Table employees
DESCRIBE employees
Table job_history
DESCRIBE job_history
Objectifs
Objectifs
Cette annexe présente SQL Developer, outil graphique qui simplifie les tâches de
développement de base de données. Elle explique comment utiliser SQL Worksheet pour
exécuter des instructions et des scripts SQL. Elle explique également comment modifier et
déboguer du code PL/SQL.
2 4 6
1 3 5
2 4 6
1 5 7 8
3
Avant mise
en forme
Insérer
un snippet
Modifier
le snippet
Utiliser SQL*Plus
Utiliser SQL*Plus
SQL Worksheet prend en charge certaines instructions SQL*Plus. Celles-ci doivent être
interprétées par SQL Worksheet avant d'être transmises à la base de données. Toute
instruction SQL*Plus qui n'est pas prise en charge par SQL Worksheet est ignorée et n'est pas
transmise à la base. Par exemple, les instructions SQL*Plus suivantes ne sont pas prises en
charge par SQL Worksheet :
• append
• archive
• attribute
• break
Pour connaître la liste complète des instructions SQL*Plus prises en charge et non prises en
charge par SQL Worksheet, reportez-vous à l'aide en ligne de SQL Developer.
Pour afficher la fenêtre de commande SQL*Plus, sélectionnez SQL*Plus dans le menu Tools.
Pour que cette fonctionnalité soit disponible, il faut que le système sur lequel vous utilisez
SQL Developer dispose d'un répertoire d'origine ou d'un dossier Oracle Home dans lequel
l'exécutable SQL*Plus est installé. Si l'emplacement du fichier exécutable SQL*Plus n'est pas
indiqué dans vos préférences SQL Developer, vous êtes invité à le préciser.
Synthèse
Synthèse
SQL Developer est un outil graphique gratuit conçu pour simplifier les tâches de
développement d'une base de données. Ainsi, à l'aide de cet outil, vous pouvez consulter,
créer et modifier des objets de base de données. Vous pouvez utiliser SQL Worksheet pour
exécuter des instructions et des scripts SQL. Vous pouvez éditer et déboguer du code
PL/SQL. SQL Developer permet en outre de créer et d'enregistrer des jeux d'états
personnalisés en vue de leur réutilisation.
Utiliser SQL*Plus
Objectifs
Objectifs
Cette annexe montre comment créer des instructions SELECT réutilisables plusieurs fois. Elle
explique également comment utiliser les commandes SQL*Plus pour exécuter des instructions
SQL. Enfin, elle présente la mise en forme d'une sortie à l'aide de commandes SQL*Plus,
l'édition de commandes SQL et l'enregistrement de scripts dans SQL*Plus.
Instructions SQL
Serveur
SQL*Plus
Résultats d'interrogation
Tampon
SQL et SQL*Plus
SQL est un langage de commande qui permet de communiquer avec le serveur Oracle à partir
de n'importe quel outil ou application. Oracle SQL contient de nombreuses extensions.
Lorsque vous entrez une instruction SQL, elle est stockée dans une région de la mémoire
appelée tampon SQL (SQL Buffer) jusqu'à ce que vous entriez une nouvelle instruction SQL.
SQL*Plus est un outil Oracle qui reconnaît les instructions SQL et les soumet à Oracle9i
Server en vue de leur exécution. Cet outil possède son propre langage de commande.
Caractéristiques du langage SQL
• Il est à la portée de nombreux utilisateurs, y compris de ceux ayant peu ou pas
d'expérience en programmation.
• Ce n'est pas un langage procédural.
• Il réduit le temps nécessaire à la création et à la gestion des systèmes.
• Il s'agit d'un langage proche de l'anglais.
Caractéristiques de l'environnement SQL*Plus
• Il accepte la saisie ad hoc d'instructions.
• Il accepte en entrée des instructions SQL stockées dans un fichier.
• Il fournit un éditeur de ligne permettant la modification d'instructions SQL.
• Il contrôle les paramètres d'environnement.
• Il met en forme les résultats des interrogations de manière à générer des états de base.
• Il donne accès à des bases de données locales et distantes.
SQL SQL*Plus
Il s'agit d'un langage permettant de Il reconnaît les instructions SQL et les envoie
communiquer avec le serveur Oracle pour au serveur.
accéder aux données.
Il est basé sur la norme SQL définie par l'ANSI Il s'agit de l'interface propriétaire d'Oracle
(American National Standards Institute). qui permet l'exécution d'instructions SQL.
Il manipule les données et les définitions Il ne permet pas la manipulation de valeurs
de table dans la base de données. dans la base de données.
Les instructions SQL sont placées dans Les commandes sont saisies une ligne à la fois
le tampon SQL sur une ou plusieurs lignes. et ne sont pas stockées dans le tampon SQL.
Il n'offre pas de caractère de suite. Le tiret (–) est utilisé en tant que caractère
de suite si la commande excède une ligne.
Les mots-clés ne peuvent pas être abrégés. Les mots-clés peuvent être abrégés.
Il utilise un caractère de fin pour exécuter Il ne requiert pas de caractère de fin pour
les commandes immédiatement. exécuter les commandes immédiatement.
Il utilise des fonctions pour la mise en forme Il utilise des commandes pour la mise en forme
des données. des données.
• Se connecter à SQL*Plus
• Afficher la structure d'une table
• Editer des instructions SQL
• Exécuter du code SQL à partir de SQL*Plus
• Sauvegarder des instructions SQL dans des fichiers
et ajouter des instructions SQL à la fin de ces fichiers
• Exécuter des fichiers sauvegardés
• Charger les commandes d'un fichier dans le tampon
SQL*Plus
SQL*Plus est un environnement dans lequel vous pouvez effectuer les opérations suivantes :
• Exécuter des instructions SQL pour extraire, modifier, ajouter ou supprimer des données
dans la base.
• Mettre en forme les résultats des interrogations, effectuer des calculs sur ces résultats,
les stocker et générer des états.
• Créer des fichiers script afin d'enregistrer des instructions SQL pour une utilisation
ultérieure.
Les commandes SQL* Plus se répartissent dans les catégories principales suivantes :
Catégorie Fonction
Environnement Définition du comportement général des instructions SQL
pour la session.
Mise en forme Mise en forme des résultats des interrogations.
Manipulation de Sauvegarde, chargement et exécution de fichiers script.
fichiers
Exécution Envoi des instructions SQL du tampon SQL au serveur Oracle.
Edition Modification des instructions SQL dans le tampon.
Interaction Création de variables et transmission à des instructions SQL,
affichage des valeurs des variables et affichage des messages à l'écran.
Divers Connexion à la base de données, manipulation de l'environnement
SQL*Plus et affichage des définitions de colonne.
Se connecter à SQL*Plus
sqlplus [username[/password[@database]]]
Se connecter à SQL*Plus
Le mode d'appel de SQL*Plus dépend du type de système d'exploration ou d'environnement
Windows utilisé.
Pour vous connecter à partir d'un environnement Windows :
1. Sélectionnez Démarrer (Start) > Programmes (Programs) > Oracle > Application
Development > SQL*Plus.
2. Entrez le nom utilisateur, le mot de passe et le nom de base de données.
Pour vous connecter à partir d'un environnement de ligne de commande :
1. Ouvrez une session sur votre ordinateur.
2. Entrez la commande sqlplus comme indiqué dans la diapositive ci-dessus.
Dans la syntaxe :
username Votre nom utilisateur de base de données
password Votre mot de passe de base de données (il est visible dans ce cas)
@database Chaîne de connexion de base de données
Remarque : Pour préserver la confidentialité de votre mot de passe, ne le saisissez pas à
l'invite du système d'exploitation. Entrez uniquement votre nom utilisateur. Entrez votre mot
de passe lorsque vous êtes invité à le saisir.
DESC[RIBE] tablename
DESCRIBE departments
• A[PPEND] text
• C[HANGE] / old / new
• C[HANGE] / text /
• CL[EAR] BUFF[ER]
• DEL
• DEL n
• DEL m n
Indications
• Si vous appuyez sur [Entrée] avant de terminer une commande, SQL*Plus affiche un
numéro de ligne.
• Vous indiquez la fin de la saisie dans le tampon SQL en entrant l'un des caractères de fin
(point-virgule ou barre oblique) ou en appuyant deux fois sur [Entrée]. L'invite SQL
apparaît alors.
• I[NPUT]
• I[NPUT] text
• L[IST]
• L[IST] n
• L[IST] m n
• R[UN]
• n
• n text
Commande Description
I[NPUT] Insère un nombre de lignes indéfini.
I[NPUT] text Insère une ligne contenant text.
L[IST] Liste toutes les lignes du tampon SQL.
L[IST] n Liste la ligne n.
L[IST] m n Liste la fourchette de lignes m à n (incluse).
R[UN] Affiche et exécute l'instruction SQL en cours dans le tampon.
n Indique la ligne devant être la ligne en cours.
n text Remplace la ligne n par text.
0 text Insère une ligne avant la ligne 1.
Remarque : En regard d'une invite SQL, vous ne pouvez entrer qu'une seule commande
SQL*Plus. Les commandes SQL*Plus ne sont pas stockées dans le tampon. Pour continuer
une commande SQL*Plus sur la ligne suivante, terminez la première ligne par un tiret (-).
LIST
1 SELECT last_name
2* FROM employees
1
1* SELECT last_name
A , job_id
1* SELECT last_name, job_id
LIST
1* SELECT * from employees
c/employees/departments
1* SELECT * from departments
LIST
1 SELECT last_name, manager_id, department_id
2* FROM employees
SAVE my_query
Created file my_query
START my_query
EDIT my_query
Option Description
Synthèse
Synthèse
SQL*Plus est un environnement d'exécution qui permet d'envoyer des commandes SQL
au serveur de base de données, ou encore d'éditer et de sauvegarder des commandes SQL.
Vous pouvez exécuter des commandes à partir de l'invite SQL ou d'un fichier script.
Utiliser JDeveloper
Oracle JDeveloper
Oracle JDeveloper
Oracle JDeveloper est un environnement IDE (Integrated Development Environment)
permettant de développer et de déployer des applications Java et des services Web. Il prend en
charge chaque étape du cycle de développement des logiciels (SDLC - Software Development
Life Cycle), de la modélisation au déploiement. Il comporte des fonctionnalités permettant
d'utiliser les dernières normes de l'industrie informatique pour les langages Java, XML et SQL
lors du développement d'une application.
Oracle JDeveloper 10g fournit une nouvelle approche pour le développement J2EE en
proposant des fonctionnalités qui permettent un développement graphique et déclaratif. Grâce
à cette approche novatrice, le développement J2EE est simple et efficace.
Navigateur de connexions
(Connections Navigator)
Navigateur d'applications
(Applications Navigator)
Fenêtre Structure
Fenêtre Structure
La fenêtre Structure offre une vue structurelle des données figurant dans le document
sélectionné dans la fenêtre active parmi les fenêtres contribuant à la gestion de la structure :
les navigateurs, les éditeurs et les visualiseurs, et le gestionnaire de propriétés.
Dans la fenêtre Structure, vous pouvez afficher les données du document de différentes
manières. Les structures disponibles pour affichage sont basées sur le type de document. Pour
un fichier Java, vous pouvez afficher la structure du code, la structure de l'interface utilisateur
ou les données du modèle d'interface utilisateur. Pour un fichier XML, vous pouvez afficher
la structure du code XML, la structure de conception ou les données du modèle d'interface
utilisateur.
La fenêtre Structure est dynamique : elle reflète toujours la sélection en cours de la fenêtre
active (sauf si vous gelez le contenu de la fenêtre sur une vue particulière) de façon pertinente
pour l'éditeur actif. Lorsque la sélection en cours est un noeud dans le navigateur, l'éditeur par
défaut est utilisé. Pour modifier la vue de la structure pour la sélection en cours, sélectionnez
un autre onglet de structure.
Fenêtre de l'éditeur
Fenêtre de l'éditeur
Vous pouvez afficher l'ensemble des fichiers de projet dans une même fenêtre de l'éditeur,
ouvrir plusieurs vues du même fichier ou ouvrir plusieurs vues de différents fichiers.
Les onglets figurant en haut de la fenêtre de l'éditeur sont les onglets de document. Lorsque
vous sélectionnez un onglet de document, cela entraîne la sélection du fichier correspondant,
qui est amené au premier plan de la fenêtre de l'éditeur en cours.
Les onglets figurant au bas de la fenêtre de l'éditeur pour un fichier donné sont les onglets
d'éditeur. Lorsque vous sélectionnez un de ces onglets, le fichier est ouvert dans l'éditeur
correspondant.
Squelette de la fonction
Compilation
Compilation
Après avoir modifié la définition de squelette, vous devez compiler le programme. Dans le
navigateur de connexions, cliquez avec le bouton droit de la souris sur l'objet PL/SQL à
compiler, puis sélectionnez Compile. Vous pouvez également procéder à la compilation
à l'aide de la combinaison de touches [CTRL] + [MAJ] + [F9].
Exécuter un programme
Exécuter un programme
Pour exécuter un programme, cliquez avec le bouton droit de la souris sur l'objet et
sélectionnez Run. La boîte de dialogue Run PL/SQL apparaît. Vous devez éventuellement
remplacer les valeurs NULL par des valeurs acceptables qui sont transmises au programme.
Après avoir modifié les valeurs, cliquez sur OK. Le résultat apparaît dans la fenêtre
Message-Log.
Supprimer un programme
Supprimer un programme
Pour supprimer un programme, cliquez avec le bouton droit de la souris sur l'objet et
sélectionnez Drop. La boîte de dialogue Drop Confirmation apparaît. Cliquez sur Yes. L'objet
est supprimé de la base de données.
Débogage Reprise
Fenêtre Data
Fenêtre Watches
Fenêtre Stack
Curseurs REF
Variables de curseur
Variables de curseur
Les variables de curseur sont semblables aux pointeurs C ou Pascal, lesquels conservent
l'emplacement en mémoire (adresse) d'un élément à la place de l'élément proprement dit.
Par conséquent, la déclaration d'une variable de curseur permet de créer un pointeur, et non un
élément. En langage PL/SQL, un pointeur présente le type de données REF X, où REF
représente l'abréviation de REFERENCE et X une classe d'objets. Une variable de curseur
présente le type de données REF CURSOR.
A l'image d'un curseur, une variable de curseur pointe vers la ligne en cours de l'ensemble de
résultats d'une interrogation dont les résultats comportent plusieurs lignes. Cependant, les
curseurs se distinguent des variables de curseur de la même façon que les constantes se
différencient des variables. Un curseur est statique, tandis qu'une variable de curseur est
dynamique. En effet, cette dernière n'est pas liée à une interrogation précise. Vous pouvez
ouvrir une variable de curseur pour exécuter n'importe quelle interrogation dont le type est
compatible. Ainsi, vous bénéficiez d'une souplesse d'utilisation accrue.
Les variables de curseur sont accessibles par n'importe quel client PL/SQL. Par exemple, vous
pouvez déclarer une variable de curseur dans un environnement hôte PL/SQL, tel qu'un
programme OCI ou Pro*C, puis transmettre celle-ci au compilateur PL/SQL en tant que
variable hôte d'entrée (variable attachée (bind variable)). De plus, les outils de développement
d'applications tels que Oracle Forms et Oracle Reports, qui disposent d'un moteur PL/SQL,
peuvent utiliser les variables de curseur intégralement côté client. Le serveur Oracle possède
également un moteur PL/SQL. Vous pouvez transmettre les variables de curseur entre une
application et un serveur, et vice versa, via les appels RPC.
Exemple :
Les types REF CURSOR forts sont moins sujets aux erreurs, car le compilateur PL/SQL ne permet
d'associer une variable de curseur de type fort qu'aux interrogations dont le type est compatible.
Cependant, les types REF CURSOR faibles sont plus souples d'utilisation, car le compilateur permet
d'associer une variable de curseur de type faible à n'importe quelle interrogation.
Déclarer des variables de curseur
Après avoir défini un type REF CURSOR, vous pouvez déclarer des variables de curseur du même
type dans n'importe quel bloc ou sous-programme PL/SQL. Dans l'exemple suivant, vous déclarez la
variable de curseur DEPT_CV :
DECLARE
TYPE DeptCurTyp IS REF CURSOR RETURN departments%ROWTYPE;
dept_cv DeptCurTyp; -- declare cursor variable
et CLOSE
• L'instruction OPEN-FOR associe une variable de curseur
à une interrogation dont les résultats comportent plusieurs
lignes. Elle exécute l'interrogation, identifie l'ensemble de
résultats et fait pointer le curseur vers la première ligne de
cet ensemble de résultats.
• L'instruction FETCH renvoie une ligne à partir de l'ensemble
de résultats d'une interrogation dont les résultats
comportent plusieurs lignes. Elle affecte les valeurs des
colonnes renvoyées par l'instruction SELECT aux variables
L'exemple suivant déclare une variable de curseur, puis associe cette dernière à une instruction
SELECT dynamique qui renvoie des lignes à partir de la table employees :
DECLARE
TYPE EmpCurTyp IS REF CURSOR; -- define weak REF CURSOR
type
emp_cv EmpCurTyp; -- declare cursor variable
my_ename VARCHAR2(15);
my_sal NUMBER := 1000;
BEGIN
OPEN emp_cv FOR -- open cursor variable
'SELECT last_name, salary FROM employees WHERE salary >
:s'
USING my_sal;
Exemple d'extraction
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
emp_cv EmpCurTyp;
emp_rec employees%ROWTYPE;
sql_stmt VARCHAR2(200);
my_job VARCHAR2(10) := 'ST_CLERK';
BEGIN
sql_stmt := 'SELECT * FROM employees
WHERE job_id = :j';
OPEN emp_cv FOR sql_stmt USING my_job;
LOOP
FETCH emp_cv INTO emp_rec;
Exemple d'extraction
L'exemple de la diapositive ci-dessus montre que vous pouvez extraire (fetch) des lignes de
l'ensemble de résultats d'une interrogation dynamique dont les résultats comportent plusieurs
lignes, et placer cette extraction dans un enregistrement. Vous devez définir au préalable un
type REF CURSOR, à savoir EmpCurTyp. Ensuite, vous devez définir une variable de
curseur emp_cv, de type EmpcurTyp. Dans la section exécutable du bloc PL/SQL,
l'instruction OPEN-FOR associe la variable de curseur EMP_CV à une interrogation dont les
résultats comportent plusieurs lignes, à savoir sql_stmt. L'instruction FETCH renvoie une
ligne à partir de l'ensemble de résultats de cette interrogation, puis affecte les valeurs des
colonnes renvoyées par l'instruction SELECT à EMP_REC dans la clause INTO. Une fois la
dernière ligne traitée, vous devez fermer la variable de curseur EMP_CV.
Exercices
complémentaires
Exercices complémentaires 1 et 2
Remarque : Les exercices suivants complètent les exercices relatifs à la déclaration de variables
et à l'écriture d'instructions exécutables.
1. Evaluez chacune des déclarations suivantes. Déterminez celles qui ne sont pas valides et
expliquez pourquoi.
a. DECLARE
name,dept VARCHAR2(14);
b. DECLARE
test NUMBER(5);
c. DECLARE
MAXSALARY NUMBER(7,2) = 5000;
d. DECLARE
JOINDATE BOOLEAN := SYSDATE;
Exercice complémentaire 3
3. DECLARE
v_custid NUMBER(4) := 1600;
v_custname VARCHAR2(300) := 'Women Sports Club';
v_ new_custid NUMBER(3) := 500;
BEGIN
DECLARE
v_custid NUMBER(4) := 0;
v_custname VARCHAR2(300) := 'Shape up Sports Club';
v_new_custid NUMBER(3) := 300;
v_new_custname VARCHAR2(300) := 'Jansports Club';
BEGIN
1
END;
v_custid := (v_custid *12) / 10;
2
END;
/
Observez le bloc PL/SQL ci-dessus et déterminez le type de données et la valeur de chacune des
variables suivantes d'après les règles de portée :
a. La valeur de v_custid à la position 1 est la suivante :
b. La valeur de v_custname à la position 1 est la suivante :
c. La valeur de v_new_custid à la position 2 est la suivante :
d. La valeur de v_new_custname à la position 1 est la suivante :
e. La valeur de v_custid à la position 2 est la suivante :
f. La valeur de v_custname à la position 2 est la suivante :
Exercices complémentaires 4 et 5
Remarque : Les exercices suivants complètent les exercices relatifs à l'interaction avec le serveur
Oracle et à l'écriture de structures de contrôle.
4. Ecrivez un bloc PL/SQL qui accepte une année en tant que donnée d'entrée, et qui vérifie s'il
s'agit d'une année bissextile. Par exemple, si l'année entrée est 1990, le résultat doit être
"1990 is not a leap year".
Indice : L'année doit être divisible par 4, mais pas par 100, ou bien elle doit l'être par 400.
Exercices complémentaires 4 et 5
Testez la solution en utilisant les années suivantes :
1990 Année non bissextile
2000 Année bissextile
1996 Année bissextile
1886 Année non bissextile
1992 Année bissextile
1824 Année bissextile
Exercices complémentaires 6 et 7
6. a. Stockez un numéro de département dans une variable de substitution.
b. Ecrivez un bloc PL/SQL pour afficher le nombre de personnes travaillant dans ce
département.
7. Ecrivez un bloc PL/SQL qui déclare une variable nommée sal, contenant le salaire d'un
employé. Dans la section exécutable du programme, effectuez les opérations suivantes :
a. Stockez un nom d'employé dans une variable de substitution.
b. Stockez son salaire dans la variable v_sal.
Greenberg 12000
Ernst 6000
Exercices complémentaires 8 et 9
8. Ecrivez un bloc PL/SQL permettant le stockage du salaire d'un employé dans une variable
de substitution PL/SQL.
Dans la section exécutable du programme, effectuez les opérations suivantes :
- Calculez le salaire annuel de la façon suivante : salaire * 12.
- Calculez la prime comme indiqué ci-après :
Salaire annuel Prime
>= 20 000 2 000
1000 1000
15000 2000
Remarque : Les exercices suivants complètent les exercices relatifs à l'utilisation des types de
données composites et des curseurs, et au traitement des exceptions.
9. a. Exécutez le script lab_ap_09_a.sql afin de créer une table temporaire nommée
emp. Ecrivez un bloc PL/SQL permettant le stockage d'un numéro d'employé, du
nouveau numéro de département et du pourcentage d'augmentation de salaire dans des
variables de substitution.
b. Mettez à jour le numéro de département et le salaire de l'employé en utilisant les
nouvelles valeurs correspondantes. Utilisez la table emp pour effectuer les mises à jour.
Une fois celles-ci terminées, affichez le message "Update complete" dans la fenêtre. Si
aucun enregistrement correspondant n'est trouvé, affichez le message "No Data Found".
Testez le bloc PL/SQL avec les cas suivants :
ID EMPLOYE NOUVEL ID % AUGMENT. MESSAGE
DEPARTEMENT
100 20 2 Update
Complete
10 30 5 No Data
found
126 40 3 Update
Complete
Exercices complémentaires 10 et 11
10. Créez un bloc PL/SQL qui déclare le curseur EMP_CUR et permet de sélectionner le nom,
le salaire et la date d'embauche d'un employé, à partir de la table employees. Traitez
chaque ligne à partir du curseur. Si le salaire est supérieur à 15 000 et que la date
d'embauche est postérieure à 01-FEB-1988, affichez le nom, le salaire et la date
d'embauche de l'employé dans la fenêtre, en respectant le format de l'exemple de résultat
ci-après :
11. Créez un bloc PL/SQL permettant d'extraire, à partir de la table EMPLOYEES, le nom de
famille et le numéro de département de chaque employé dont la valeur EMPLOYEE_ID est
inférieure à 114. A l'aide des valeurs extraites de la table employees, remplissez deux
13. Exécutez le script lab_ap_09_a.sql afin de recréer la table emp. Créez un bloc
PL/SQL permettant d'accorder une promotion aux employés gagnant plus de 3 000, en
14. a. Pour effectuer l'exercice suivant, vous devez disposer d'une table où seront stockés les
résultats. Vous pouvez créer la table analysis vous-même ou exécuter le script
lab_ap_14_a.sql qui le fera à votre place. Créez une table nommée analysis
qui comporte les trois colonnes suivantes :
Nom de colonne ENAME YEARS SAL
Type de clé
Valeurs
Nulls/uniques
Table de clé
étrangère
Colonne de clé
étrangère
Type de données VARCHAR2 Number Number
Longueur 20 2 8,2
Solutions
des exercices
complémentaires
2 END;
Observez le bloc PL/SQL ci-dessus et déterminez le type de données et la valeur de chacune des
variables suivantes d'après les règles de portée.
a. La valeur de v_custid à la position 1 est la suivante :
300, et le type de données est NUMBER.
b. La valeur de v_custname à la position 1 est la suivante :
Shape up Sports Club Jansports Club, et le type de données est VARCHAR2.
c. La valeur de v_new_custid à la position 1 est la suivante :
500, et le type de données est NUMBER (ou INTEGER).
d. La valeur de v_new_custname à la position 1 est la suivante :
Jansports Club, et le type de données est VARCHAR2.
e. La valeur de v_custid à la position 2 est la suivante :
1920, et le type de données est NUMBER.
f. La valeur de v_custname à la position 2 est la suivante :
Women Sports Club, et le type de données est VARCHAR2.
END IF;
END;
/
DECLARE
V_HOWMANY NUMBER(3);
V_DEPTNO DEPARTMENTS.department_id%TYPE := &P_DEPTNO;
BEGIN
SELECT COUNT(*) INTO V_HOWMANY FROM employees
WHERE department_id = V_DEPTNO;
Greenberg 12000
Ernst 6000
8. Ecrivez un bloc PL/SQL permettant le stockage du salaire d'un employé dans une variable
de substitution. Dans la section exécutable du programme, effectuez les opérations
suivantes :
• Calculez le salaire annuel de la façon suivante : salaire * 12.
• Calculez la prime comme indiqué ci-après :
Salaire annuel Prime
>= 20 000 2 000
1000 1000
15000 2000
DECLARE
CURSOR C_EMP_CUR IS
SELECT last_name,salary,hire_date FROM EMPLOYEES;
V_ENAME VARCHAR2(25);
V_SAL NUMBER(7,2);
V_HIREDATE DATE;
BEGIN
OPEN C_EMP_CUR;
FETCH C_EMP_CUR INTO V_ENAME,V_SAL,V_HIREDATE;
WHILE C_EMP_CUR%FOUND
LOOP
IF V_SAL > 15000 AND V_HIREDATE >=
TO_DATE('01-FEB-1988','DD-MON-YYYY') THEN
DBMS_OUTPUT.PUT_LINE (V_ENAME || ' earns '
|| TO_CHAR(V_SAL)|| ' and joined the organization on '
|| TO_DATE(V_HIREDATE,'DD-Mon-YYYY'));
END IF;
12. a. Créez un bloc PL/SQL qui déclare un curseur nommé C_DATE_CUR. Transmettez un
paramètre de type DATE au curseur et affichez les détails relatifs aux employés
embauchés après cette date.
DEFINE B_HIREDATE = 08-MAR-00
DECLARE
CURSOR C_DATE_CURSOR(JOIN_DATE DATE) IS
SELECT employee_id,last_name,hire_date FROM employees
WHERE HIRE_DATE >JOIN_DATE ;
V_EMPNO employees.employee_id%TYPE;
V_ENAME employees.last_name%TYPE;
V_HIREDATE employees.hire_date%TYPE;
V_HDATE employees.hire_date%TYPE := '&B_HIREDATE';
BEGIN
OPEN C_DATE_CURSOR(V_HDATE);
LOOP
FETCH C_DATE_CURSOR INTO V_EMPNO,V_ENAME,V_HIREDATE;
EXIT WHEN C_DATE_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (V_EMPNO || ' ' || V_ENAME || ' '
|| V_HIREDATE);
END LOOP;
END;
/
DECLARE
CURSOR C_Senior_Clerk IS
SELECT employee_id,job_id FROM emp
WHERE job_id = 'ST_CLERK' AND salary > 3000
FOR UPDATE OF job_id;
BEGIN
FOR Emrec IN C_Senior_Clerk
EXCEPTION
WHEN E_DUE_FOR_RAISE THEN
INSERT INTO ANALYSIS(ENAME,YEARS,SAL)
VALUES (V_ENAME,V_YEARS,V_SAL);
END;
/