Vous êtes sur la page 1sur 314

Oracle 11g 

SQL, PL/SQL, SQL*Plus

Jérôme GABILLAUD  

Résumé
Ce livre sur Oracle s’adresse à tout informaticien désireux de maîtriser la gestion d’une base de données Oracle.
L’auteur reprend les concepts, définitions et règles du modèle relationnel et détaille son utilisation dans le cadre des outils proposés en standard
avec Oracle Database 11g, c’est-à-dire SQL, SQL*PLUS, PL/SQL et Java.
Les techniques de programmation en PL/SQL sont étudiées afin de pouvoir utiliser toute la puissance du serveur de bases de données Oracle
11g ainsi que les nouveautés apportées par cette version : colonne virtuelle, table en lecture seule, pivot, trigger composé, cache de résultat pour
les fonctions, etc. Par ailleurs, cet ouvrage présente l’outil SQL Developer et l’environnement de développement d’application Web Oracle
Application Express (APEX).
Des exemples nombreux et précis aident le lecteur à maîtriser ces langages de référence dans le monde des bases de données relationnelles.
Ces exemples sont en téléchargement sur cette page.
L'auteur
Ingénieur en Informatique pour l'Industrie, consultant, Jérôme Gabillaud est également responsable pédagogique dans un grand centre de
formation informatique. Spécialiste des systèmes d'accès aux données Microsoft ou Oracle, il est déjà auteur de nombreux ouvrages sur ce
sujet, reconnus pour leurs qualités techniques et pédagogiques.

Ce livre numérique a été conçu et est diffusé dans le respect des droits d’auteur. Toutes les marques citées ont été déposées par leur éditeur respectif. La loi du 11 Mars
1957 n’autorisant aux termes des alinéas 2 et 3 de l’article 41, d’une part, que les “copies ou reproductions strictement réservées à l’usage privé du copiste et non destinées
à une utilisation collective”, et, d’autre part, que les analyses et les courtes citations dans un but d’exemple et d’illustration, “toute représentation ou reproduction intégrale,
ou partielle, faite sans le consentement de l’auteur ou de ses ayants droit ou ayant cause, est illicite” (alinéa 1er de l’article 40). Cette représentation ou reproduction, par
quelque procédé que ce soit, constituerait donc une contrefaçon sanctionnée par les articles 425 et suivants du Code Pénal. Copyright Editions ENI

© ENI Editions - All rigths reserved - 1-


Introduction 
Oracle 11g est un puissant Système de Gestion de Bases de Données Relationnelles proposant, en plus du moteur de 
la base, de nombreux outils à l’utilisateur, au développeur et à l’administrateur. 

Ces outils ont un langage commun : le SQL. 
Oracle  permet  de  gérer  les  données  d’une  application  en  respectant  une  logique,  devenue  standard,  le  modèle 
relationnel.  Les  fondements  de  ce  modèle  ont  été  établis  au  début  des  années  70,  par  E.F.  CODD  et  restent  une 
référence pour la gestion des données. 
La logique d’extraction des données d’une base conforme au modèle relationnel, constitue l’algèbre relationnelle. Elle 
permet aux utilisateurs une approche indépendante du système physique pour arriver à un résultat. 
Le  SQL  est  un  langage  de  requêtes  descriptif,  standard  pour  toutes  les  bases  de  données  qui  suivent  le  modèle 
relationnel. Ce langage permet toutes les opérations sur les données dans tous les cas d’utilisation de la base. 
Avec Oracle, on peut associer au langage SQL un langage procédural, le PL/SQL, qui ajoute de nombreuses possibilités 
dans la manipulation des données. 

Depuis  la  version  8i,  le  SGBD  Oracle  propose,  une  nouvelle  méthode  de  gestion  des  informations  dans  l’entreprise à 
travers l’implémentation du modèle objet ­ relationnel. L’objectif de cette approche est de simplifier la modélisation des 
données en permettant le stockage et la manipulation de nouveaux types d’informations. Ces objets métiers, propres 
à chaque secteur d’activité ou à chaque entreprise doivent permettre une modélisation plus efficace. 

La  mise  en  œ uvre  de  ce  modèle  à  travers  les  extensions  du  langage  SQL  autorise  une  migration  souple  entre  le 
modèle  relationnel  pur  des  versions  précédentes  et  ce  nouveau  modèle  objet  ­  relationnel.  Le  présent  ouvrage 
s’intéresse à l’approche relationnelle classique. 

© ENI Editions - All rigths reserved - 1-


La gestion des données 
Dans  toutes  les  applications  de  gestion,  il  faut  stocker  des  données  afin  de  les  réutiliser  à  volonté  sous  différentes 
formes.  La  plupart  des  systèmes  d’exploitation  (MS/DOS,  UNIX,  VMS,  GCOS...)  fournissent  des  outils  permettant  ce 
stockage. Ces logiciels gèrent des fichiers selon des principes différents. 

1. Généralités sur les fichiers 

Un fichier informatique est un ensemble d’informations de même nature (texte, code exécutable, données...), portant 
un nom et situé sur un support physique (disque dur, disquette, bande, CD­Rom...). 
Un fichier peut avoir différentes fonctions : 

● fichier programme : contient du code exécutable par le système d’exploitation. 

● fichier texte : contient des caractères ASCII. 

● bibliothèque de fonctions : contient du code exécutable pouvant être utilisé par un programme. 

● fichier périphérique : permet l’adressage des périphériques (UNIX). 

● fichier de données : permet le stockage d’informations d’une application, etc. 

Les fichiers de données se distinguent par leur utilité au sein de l’application : le type de fichier. Ce type permettra de 
choisir à la fois le support physique du fichier et son organisation. 

Types de fichiers de données

Les  fichiers  permanents  contiennent  les  données  de  base  de  l’application.  Leurs  enregistrements  sont, 
généralement,  composés  de  nombreuses  rubriques  et  sont  de  taille  importante.  La  durée  de  vie  de  ces 
enregistrements  est  longue.  Quelques  exemples  de  fichiers  permanents  :  les  fichiers  de  clients,  les  catalogues 
d’articles, les fiches salariés. 

Les  fichiers  de  mouvement  contiennent  des  données  se  référant  aux  fichiers  permanents,  en  apportant  des 
informations supplémentaires, en général ponctuelles. Les enregistrements sont composés principalement des codes 
identifiant les enregistrements des fichiers de base. Le nombre d’enregistrements de ces fichiers peut être important 
mais  leur  durée  de  vie  est  courte.  On  peut  citer  dans  ce  type,  le  fichier  commandes  d’une  gestion  commerciale  qui 
stocke la quantité d’articles commandés par un client, ou les fiches de temps d’une gestion de salariés qui stockent le 
nombre d’heures travaillées par un salarié sur un poste. 

Les fichiers de travail sont créés en général par des applications. Ils contiennent toutes les informations des fichiers 
permanents et de mouvement regroupées dans des enregistrements composés. Leur durée de vie est la même que 
celle du traitement. Ces fichiers occupent, en général, beaucoup de place. Ce type de fichier comporte, par exemple, 
les fichiers d’édition, les résultats de requêtes. 
Les fichiers historiques contiennent des données archivées. Elles proviennent, après calcul ou épuration, des fichiers 
permanents et des fichiers de mouvement, pour des enregistrements inactifs, ou à mettre en statistique. 

2. Organisations classiques de fichiers 

L’analyste pourra choisir l’organisation de fichiers à adopter en fonction du type de fichier, du support, de l’application 
et, bien sûr, des contraintes du cahier des charges ! 
Les  principaux  choix  d’organisation  de  fichiers  sont  l’organisation  séquentielle,  le  séquentiel  indexé,  les  bases  de 
données navigationnelles et évidemment les bases de données relationnelles. 

Séquentiel

Le principe de cette organisation est de gérer les enregistrements comme des suites d’octets structurées (par des 
caractères délimiteurs ou des tailles fixes). 
L’avantage réside dans la simplicité d’utilisation, la standardisation des structures et dans l’optimisation de l’espace 
de stockage. 
Par contre, les fichiers sont indépendants les uns des autres dans l’application et les lectures ne peuvent se faire que 

© ENI Editions - All rigths reserved - 1-


séquentiellement (octet après octet). 

Séquentiel indexé

C’est  une  amélioration  de  l’organisation  séquentielle,  par  l’ajout  d’un  fichier  de  clés  (ou  d’index),  lié  au  fichier 
séquentiel. 
Ce fichier d’index contient des critères de recherche triés (index) et l’adresse de la donnée correspondante dans le 
fichier séquentiel. 

En  plus  des  avantages  du  système  séquentiel  (simplicité,  standardisation),  on  peut  donc  retrouver  rapidement  un 
enregistrement en fonction de la clé. 

Le  principal  inconvénient  reste  l’indépendance  des  fichiers  dans  l’application,  d’où  la  nécessité  de  beaucoup  de 
programmation  pour  gérer  l’intégrité  des  données.  On  peut  également  noter  un  gaspillage  de  place  dû  à  la 
redondance des données (notamment les clés). 

Bases navigationnelles

Ce sont des collections de fichiers, logiquement appareillés entre eux. Ces bases ont été créées sur des systèmes 
propriétaires  afin  de  compenser  la  faiblesse  des  organisations  précédentes,  en  ce  qui  concerne  la  traduction  du 
dictionnaire des données de l’analyse. 

Les avantages de ces bases sont nombreux, notamment la sécurité d’accès avec connexion d’utilisateurs à la base 
protégée  par  mot  de  passe  ;  le  respect,  au  niveau  des  structures  même,  de  l’intégrité  de  données  ;  de  nouvelles 
possibilités  de  lecture  de  données  grâce  à  des  liens  directs  entre  enregistrements  de  fichiers  différents  (lectures 
chaînées). 

De  gros  inconvénients  découlent  de  ces  systèmes.  Parmi  ceux­ci  on  peut  citer  la  complexité  de  maintenance  et 
d’utilisation, la "gourmandise" en espace disque, mémoire et CPU, et enfin la spécificité de ces bases par rapport au 
système d’exploitation. 

- 2- © ENI Editions - All rigths reserved


Le modèle relationnel 
Une base de données relationnelle est une collection de données mises en relation dans des tables logiques ; une table 
étant un ensemble de lignes et de colonnes. 
Les Systèmes de Gestion de Bases de Données Relationnelles (SGBDR ou RDBMS en anglais) gèrent indépendamment le 
niveau logique (objets ou entités) et le niveau physique (fichiers). 
Le succès des SGBDR provient notamment de cette caractéristique. En effet, la gestion par l’utilisateur du niveau logique 
uniquement, donne une grande simplicité dans la gestion des données, même pour des utilisateurs non informaticiens. 

1. Concepts et définitions 

Le  modèle  relationnel  repose  sur  des  concepts  de  base  simples  (domaine,  relation,  attribut),  auxquels  s’appliquent 
des règles précises. 

La mise en œ uvre de la base est facilitée par un langage assertionnel (non procédural) simple, basé sur une logique 
ensembliste. 

a. Domaine 

C’est un ensemble de valeurs caractérisées par un nom. 

Cardinal

C’est le nombre d’éléments d’un domaine. 

Exemple 
Le dictionnaire des données de l’analyse d’une gestion commerciale peut comporter, entre autres, des spécifications sur la 
gestion  des  états  de  commande  ou  des  numéros  d’ordre  à  afficher.  Le  modèle  relationnel  les  traduira  de  la  manière 
suivante : 

États des commandes =


{"EC","LI", "FA", "SO"};cardinal 4
Numéros d’ordre =
{n | 1<=n<=9999};cardinal 9999

b. Produit cartésien 

Le produit cartésien P entre plusieurs domaines D1, D2,..., Dn noté P = D1 X D2 X ... X Dn est l’ensemble des n­uplets 
(tuples) (d1, d2, ..., dn) où chaque di est un élément du domaine Di. 

Exemple 
Si on veut gérer deux domaines (codes et taux), on pourra obtenir des doublets composés d’un code et d’un taux. 

Codes = {1,2,3,4}
Taux de TVA = {0,5.5,19.6}
Codes X Taux de TVA ={(1,0),(1,5.5),(1,19.6),
(2,0),(2,5.5),(2,19.6),(3,0),(3,5.5),(3,19.6),
(4,0),(4,5.5),(4,19.6)}

c. Relation 

Une  relation  définie  sur  les  domaines  D1,  D2,...  ,  Dn  est  un  sous­ensemble  du  produit  cartésien  de  ces  domaines 
caractérisé par un nom. 

Attribut

C’est une colonne d’une relation caractérisée par un nom. 

Degré

C’est le nombre d’attributs d’une relation. 

© ENI Editions - All rigths reserved - 1-


Exemple 
Pour associer un seul taux par code, seuls trois doublets doivent être concernés. 

Relation TVA = {(1,0),(2,5.5),(3,19.6)}

Représentation

Elle se fait sous forme de tableau (table), en extension : 

ou en compréhension : 

TVA (CODE:codes, VALEUR:Taux de TVA)


ou
TVA (CODE, VALEUR)

2. Principales règles 

Le modèle relationnel gère donc un objet principal, la relation, associée aux concepts de domaine et d’attribut. 
Des règles s’appliquent à cette relation afin de respecter les contraintes liées à l’analyse. 
Quelques­unes de ces règles sont : 

Cohérence

Toute valeur prise par un attribut doit appartenir au domaine sur lequel il est défini. 

Unicité

Tous les éléments d’une relation doivent être distincts. 

Identifiant

Attribut ou ensemble d’attributs permettant de caractériser de manière unique chaque élément de la relation. 

Clé primaire

Identifiant minimum d’une relation. 

Clés secondaires

Autres identifiants de la relation. 

Intégrité référentielle

Cette  règle  impose  qu’un  attribut  ou  ensemble  d’attributs  d’une  relation  apparaisse  comme  clé  primaire  dans  une 
autre relation. 

Clé étrangère

Attribut ou ensemble d’attributs vérifiant la règle d’intégrité référentielle. 

Exemple 

L’analyse  d’une  gestion  commerciale  nous  impose  de  gérer  des  clients  ayant  des  caractéristiques  (Nom,  adresse)  et  des 
commandes que passent ces clients. 

On pourra proposer le modèle suivant : 

- 2- © ENI Editions - All rigths reserved


 

CLIENTS (NUMEROCLI,NOMCLI,ADRESSECLI)
NUMEROCLI identifiant clé primaire de CLIENTS
(NOMCLI,ADRESSECLI) identifiant clé secondaire de CLIENTS
COMMANDES (NUMEROCDE,DATECDE,NUMEROCLI,ETATCDE)
NUMEROCDE identifiant clé primaire de COMMANDES
NUMEROCLI clé étrangère de COMMANDES, référençant NUMEROCLI de CLIENTS

Valeur nulle

Dans le modèle relationnel, la notion de nullité est admise. C’est une valeur représentant une information inconnue ou 
inapplicable dans une colonne. 
Elle est notée _ , ^ ou NULL. 

Contrainte d’entité

Toute valeur participant à une clé primaire doit être non NULL. 
Exemple 
Dans  la  relation  article,  on  admet  que  le  prix  ou  le  code  TVA  peuvent  être  inconnus,  mais  la  référence  de  l’article  (clé 
primaire) doit être renseignée. 

© ENI Editions - All rigths reserved - 3-


L’algèbre relationnelle 
C’est  une  méthode  d’extraction  permettant  la  manipulation  des  tables  et  des  colonnes.  Son  principe  repose  sur  la 
création  de  nouvelles  tables  (tables  résultantes)  à  partir  des  tables  existantes,  ces  nouvelles  tables  devenant  des 
objets utilisables immédiatement. 
Les  opérateurs  de  l’algèbre  relationnelle  permettant  de  créer  les  tables  résultantes  sont  basés  sur  la  théorie  des 
ensembles. 

1. Opérateurs 

a. Union 

L’union entre deux relations de même structure (degré et domaines) donne une table résultante de même structure 
ayant comme éléments l’ensemble des éléments distincts des deux relations initiales. 

Notation : Rx = R1 ∪ R2 

Exemples 
Soient les tables CLIOUEST et CLICENTRE : 

Clients des deux régions : 

∪ CLICENTRE 
CLIENTS=CLIOUEST ∪

b. Intersection 

L’intersection  entre  deux  relations  de  même  structure  (degré  et  domaines)  donne  une  table  résultante  de  même 
structure ayant comme éléments l’ensemble des éléments communs aux deux relations initiales. 
Notation : Rx = R1 ∩ R2 

Exemple 

Clients communs aux deux régions : 

CLICOMMUN=CLIOUEST ∩ CLICENTRE

c. Différence 

© ENI Editions - All rigths reserved - 1-


La  différence  entre  deux  relations  de  même  structure  (degré  et  domaines)  donne  une  table  résultante  de  même 
structure ayant comme éléments l’ensemble des éléments de la première relation qui ne sont pas dans la deuxième. 
Notation : Rx = R1 ­ R2 

Exemple 
Clients gérés uniquement par la région OUEST : 

CLIOUESTSEUL=CLIOUEST - CLICENTRE

d. Restriction 

La  restriction  selon  une  condition  produit,  à  partir  d’une  relation,  une  relation  de  même  schéma  n’ayant  que  les 
éléments de la relation initiale qui répondent à la condition. 

Notation : Rx = σ (condition) R1 

La condition s’exprime sous la forme : 

[NON] [(] attribut opérateur valeur [)] [{ET/OU}condition]

opérateur 

un opérateur de comparaison : =, <>, >, <, >=, <= 

valeur  

une constante ou un autre attribut. 

Exemples 

Clients de NANTES : 

CLI44=σ(ADRESSE="NANTES")CLIOUEST

Articles de la famille AB : 

ART1=σ(REFART>="AB" ET REFART<"AC")ARTICLES

Tapis "pas chers" : 

ART2=σ(PRIX<=1000)ART1

e. Projection 

- 2- © ENI Editions - All rigths reserved


La  projection  d’une  relation  sur  un  groupe  d’attributs  donne  une  relation  résultante  ayant  comme  schéma 
uniquement  ces  attributs,  et  comme  éléments  les  n­uplets  distincts  composés  par  les  valeurs  associées  de  ces 
attributs. 
Notation : Rx = π R (A1, A2,.. An). 

Exemples 
Commandes et états de commande : 

CDE= π COMMANDES(NUMEROCDE,NUMEROCLI,ETATCDE)

Clients ayant des commandes : 

CLICDE1= π COMMANDES(NUMEROCLI)

Clients et états de commande : 

CLIDE2= π COMMANDES(NUMEROCLI,ETATCDE)

f. Produit cartésien 

Le  produit  cartésien  entre  deux  relations  produit  une  relation  ayant  comme  schéma  tous  les  attributs  des  deux 
relations existantes et comme éléments l’association de chaque ligne de la première table avec chaque ligne de la 
deuxième. 
Notation : Rx = S1 X S2 
Exemple 

Soient les tables : 

INVENTAIRE = DEPOT X ART2

© ENI Editions - All rigths reserved - 3-


 

g. Jointures 

La jointure entre deux relations selon une condition est produite par la restriction sur le produit cartésien. 

Notation : Rx = S1 JOIN (condition) S2 
Exemple 

Soient les tables : 

LIGCDEEC = CDEEC JOIN (CDEEC.NUMEROCDE =  


LIGNESCDE.NOCDE) LIGNESCDE

Theta­jointure

La condition est une comparaison entre deux attributs. 

Equi­jointure

La condition porte sur l’égalité entre deux attributs. 

Jointure naturelle

Équi­jointure entre les attributs portant le même nom. 

h. Calculs élémentaires 

Projection  sur  une  relation  associée  à  un  calcul  portant  sur  chaque  ligne  pour  créer  un  ou  plusieurs  nouveaux 
attributs. 

Notation : Rx = π S (A1,...,N1 = expression calculée...) 
L’expression calculée peut être : 

● une opération arithmétique, 

- 4- © ENI Editions - All rigths reserved


● une fonction mathématique, 

● une fonction portant sur une chaîne. 

Exemple 
On veut obtenir le montant d’une ligne de commande (Prix * Quantité). 

LIGCDEVALO = π LIGCDE(NOCDE,NOLIG,REFART, 
VALOLIG=QTECDE*PRIXHT)

i. Calcul d’agrégats 

Projection sur une relation associée à un ou des calculs statistiques portant sur un attribut pour tous les éléments 
de la relation ou du regroupement lié à la projection afin de créer un ou plusieurs nouveaux attributs. 

Notation : Rx = π S (A1,...,N1= fonction statistique (Ax),...) 

Les fonctions statistiques sont : 

COUNT (*) 

nombre de lignes. 

COUNT (attribut) 

nombre de valeurs non nulles. 

SUM (attribut) 

somme des valeurs non nulles. 

AVG (attribut) 

moyenne des valeurs non nulles. 

MAX (attribut) 

valeur maximum (non nulle). 

MIN (attribut) 

valeur minimum (non nulle). 

Exemples 

Nombre total de clients dans la table. 
NBCLI=π CLIENTS(N=COUNT(*)) 

Total des montants de la ligne par commande : 

© ENI Editions - All rigths reserved - 5-


CDEVALO=πLIGCDEVALO(NOCDE,TOTCDE=SUM(VALOLIG)) 

Prix les plus élevés, les moins élevés et moyenne des prix par catégorie d’articles : 
STATART=π ARTICLES(CATEGORIE,PLUSCHER=MAX(PRIX), 

MOINSCHER=MIN(PRIX),MOYENNE=AVG(PRIX)) 

2. Étapes de résolution d’un problème 

À partir d’une base de données connue (schémas, domaines, relations, éléments), la résolution d’un problème se fait 
en trois étapes. 

a. Analyser le besoin 

● Transcrire sous forme de relation résultante des besoins exprimés par le prescripteur. 

● Déterminer les attributs et les relations à utiliser. 

● Exprimer les calculs élémentaires et d’agrégats pour créer les attributs inexistants. 

b. Établir la "vue" 

La  vue  est  une  relation  intermédiaire  contenant  tous  les  attributs  permettant  de  réaliser  l’extraction,  avec  leurs 
relations d’origine, leurs classes d’utilité, et les opérations à appliquer. 

Classes d’attribut

Classe a : attribut participant à la relation résultante. 

Classe b : attribut participant à un calcul. 

Classe c : attribut participant à une restriction. 

Classe d : attribut participant à une jointure. 

c. Ordonnancer et exprimer les opérations 

D’une façon générale, et sauf exception, l’ordonnancement des opérations peut s’exprimer de la façon suivante : 
 Relations concernées. 

 Restrictions (pour éliminer les lignes inutiles). 

 Jointures, Produits cartésiens, Unions, Intersections, Différences (pour associer les lignes restantes). 

 Calculs élémentaires (pour créer les nouvelles colonnes). 

 Calculs d’agrégats (pour les colonnes statistiques). 

 Jointure entre la table obtenue en   et la table initiale en   (pour ajouter les colonnes statistiques aux autres). 

 Répéter les étapes du   pour les autres regroupements. 

 Restrictions par rapport aux attributs calculés. 

- 6- © ENI Editions - All rigths reserved


 Projections pour éliminer les doublons. 

 Projection finale pour éliminer les attributs inutiles dans la table résultante. 

Exemple 

Soit la base de données composée des tables suivantes : 

CLIENTS (NOCLI,NOMCLI,ADRESSE) 
ARTICLES (REFART,DESIGNATION,PRIXHT) 
COMMANDES (NOCDE,NOCLI,DATECDE,ETATCDE) 
LIGNESCDE (NOCDE,NOLIG,REFART,QTECDE)

On veut obtenir l’édition de la confirmation de la commande N°1301. 
Maquette du document : 

À l’analyse de la maquette et des tables initiales, on déduit que : 

date du jour : information pouvant être placée lors de la 


mise en page. 
N° de commande = NOCDE de COMMANDES 
Date de la commande = DATECDE 
Nom du client = NOMCLI de CLIENTS 
Adresse du client = ADRESSE de CLIENTS 
Référence = REFART de LIGNESCDE 
Désignation = DESIGNATION de ARTICLES 
Qté commandée = QTECDE de LIGNESCDE 
Prix HT = PRIXHT de ARTICLES 
Montant HT = zone à calculer 
Total HT = zone à calculer

Pour établir le document, il faudrait donc la table suivante : 

CONFCDE (NOCDE,DATECDE,NOMCLI,ADRESSE,REFART, 
DESIGNATION,PRIXHT,QTECDE,MTHT,TOTHT)

avec MTHT = PRIXHT*QTECDE par ligne de commande et TOTHT = SUM(MTHT) pour la commande. 

Vue

© ENI Editions - All rigths reserved - 7-


 

Opérations

Restriction sur le numéro de commande : 

T1=σ(NOCDE=1301) COMMANDES

T2=σ(NOCDE=1301) LIGNESCDE

Jointure naturelle COMMANDES et LIGNESCDE : 

T3=T1 JOIN (T1.NOCDE=T2.NOCDE) T2

Jointure naturelle COMMANDES et CLIENTS : 

T4=T3 JOIN (T3.NOCLI=CLIENTS.NOCLI) CLIENTS

Jointure naturelle LIGNESCDE et ARTICLES : 

T5=T4 JOIN (T4.REFART=ARTICLES.REFART) ARTICLES 

Projection de calcul élémentaire de MTHT et élimination des colonnes inutiles : 

T6=πT5(NOCDE,DATCDE,NOMCLI,ADRESSE,REFART, 
DESIGNATION,PRIXHT,QTECDE,MTHT=PRIXHT*QTECDE)

- 8- © ENI Editions - All rigths reserved


 

Projection de calcul d’agrégat pour TOTHT : 

T7=πT6(NOCDE,TOTHT=SUM(MTHT))

Jointure à effectuer pour avoir toutes les colonnes dans la table résultante : 

CONFCDE=T6 JOIN (T7.NOCDE=T6.NOCDE) T7

© ENI Editions - All rigths reserved - 9-


Généralités 
Le  SQL  (Structured  Query  Language)  est  un  langage  de  requête  utilisé  pour  la  manipulation  des  bases  de  données 
relationnelles. 
Il a été créé au milieu des années 70 par IBM et commercialisé par ORACLE en 1979. 

L’intérêt du SQL réside dans les caractéristiques suivantes : 

Normalisation

Il implémente le modèle relationnel, et les principaux organismes de normalisation le décrivent : 

● l’ANSI (American National Standards Institute) dans les documents ANSI 9075­1:1999, ANSI 9075­2:1999 et ANSI 
9075­5:1999. Il est possible d’obtenir plus de détails sur les documents qui définissent la norme en se rendant 
sur  le  site  Web  de  l’ANSI  (http://webstore.ansi.org)  ou  sur  le  site  Web  de  NCITS  (National  Comittee  for 
Information  Technology  Standards)  qui  reprend  une  partie  des  standards  ANSI  dont  le  SQL 
(http://www.ncits.org). 

● l’ISO  (International  Organisation  for  Standardization)  dans  les  documents  ISO/IEC  9075­1:1999,  ISO/IEC  9075­
2:1999 et ISO/IEC 9075­5:1999. Il est possible d’obtenir une copie des documents de normalisation sur le site 
Web de l’ISO : http://www.iso.ch/iso/iso_catalogue.htm. 

Standard

Du fait de cette normalisation, la plupart des éditeurs de SGBDR intègrent le SQL à leurs produits (INFORMIX, DB2, MS 
SQL Server, SYBASE...). 
Les données, requêtes et applications sont donc assez facilement portables d’une base à une autre. 

Non Procédural

Le SQL est un langage de requête qui permet à l’utilisateur de demander un résultat sans se préoccuper des moyens 
techniques pour trouver ce résultat. Un composant du moteur de la base (l’optimiseur) se charge de cette tâche. 
Les instructions sont écrites dans un langage courant (l’anglais !). 
Le  SQL  manipule  aussi  bien  des  ensembles  d’enregistrements  qu’un  seul  enregistrement,  et  permet  l’utilisation  du 
résultat  dans  une  autre  commande.  On  n’a  donc  pas  besoin  de  structures  de  contrôle  comme  dans  les  langages  de 
programmation courants (langages de 3ème génération). 

Universel

Le SQL peut être utilisé à tous les niveaux dans la gestion d’une base de données : 

● administration système, 

● administration de la base, 

● développement et application, 

● gestion de données simple. 

Tous les utilisateurs de la base ont donc un langage commun. 

Ce langage permet d’autre part d’effectuer toutes les opérations : 

● interrogation des données, 

● ajout, suppression, modification de données, 

● gestion des objets (structures), 

● gestion de la sécurité d’accès aux données. 

© ENI Editions - All rigths reserved - 1-


1. Composants de la base logique : objets SQL 

Une base de données relationnelle est composée d’entités logiques ou physiques manipulables par le langage SQL. 
Ces entités sont appelées objets SQL. 
Le premier est la base de données qui regroupe l’ensemble des autres objets. 

On peut regrouper ces objets en différentes catégories en fonction de leur utilité. 

a. La gestion des données 

table 

Ensemble de lignes (row) et de colonnes (column). 

index 

Colonne ou ensemble de colonnes permettant l’accélération des recherches. 

view 

Requête pouvant être manipulée comme une table (table virtuelle). 

synonym 

Nom alternatif pour une table ou une view. 

sequence 

Générateur de série de nombres. 

snapshots 

Table contenant le résultat d’une requête faite sur une table gérée dans une base distante. 

database links 

Lien avec des bases distantes. 

b. Le stockage physique 

cluster 

Regroupement physique de tables ayant des colonnes communes. 

tablespace 

Regroupement logique de fichiers. 

directory 

Représentation dans la base de données d’un répertoire du système d’exploitation hôte. 

c. Le stockage d’instructions 

schema 

Ensemble des objets de la base logique appartenant à un même utilisateur. 

procedure 

- 2- © ENI Editions - All rigths reserved


Ensemble de code procédural nommé. 

function 

Ensemble de code procédural nommé retournant une valeur. 

database trigger 

Ensemble de code procédural associé à une table. 

packages 

Collection d’objets (procédure, fonction...) stockés ensemble. 

library 

Représentation  d’une  collection  de  procédures  externes  à  Oracle,  stockées  dans  des  bibliothèques  partagées  du 
système hôte. 

d. La gestion des utilisateurs 

profile 

Ensemble nommé de limites système. 

role 

Ensemble de privilèges pouvant être attribués à des utilisateurs. 

user 

Utilisateur pouvant se connecter et accéder aux ressources de la base. 

Les objets créés par les utilisateurs du SGBDR Oracle doivent être nommés. 

e. Dénomination des objets 

Elle doit respecter les règles suivantes : 

● 1 à 30 caractères, sauf database (8) et database links (128). 

● Pas de distinction majuscule­minuscule. 

● Commencent par une lettre. 

● Caractères alphanumériques plus _ $ et # (plus @ et . pour les database links). 

● Ne doit pas être un mot réservé. 

● Doit être unique, à l’intérieur du SCHEMA d’un utilisateur, même pour des types d’objets différents. 

Conventions

Les noms utilisés doivent être significatifs, sans être trop longs. 

Il est recommandé d’utiliser des noms identiques pour désigner les mêmes entités dans des objets différents de la 
base de données (nom de colonne). 

Si  les  noms  d’objets  sont  donnés  sans  guillemets,  Oracle  ne  tient  pas  compte  de  la  casse  utilisée  (les  noms  sont 
stockés  en  majuscules  à  la  création  des  objets  et  lors  des  références  ultérieures,  Oracle  opère  automatiquement 
une conversion en majuscules). 

© ENI Editions - All rigths reserved - 3-


Les noms d’objets peuvent toutefois être cités entre guillemets doubles. Dans ce cas, Oracle utilise la casse donnée 
entre guillemets pour référencer l’objet. Il est déconseillé d’utiliser cette possibilité, du fait de la lourdeur d’écriture et 
des risques d’erreur de syntaxe qu’elle engendre. 

2. Catégories d’instructions 

Les instructions SQL sont regroupées en catégories en fonction de leur utilité et des entités manipulées. 

a. DDL (Data Definition Language) 

Il permet de gérer les "structures" des objets : 

● Créer, modifier, supprimer des objets. 

● Autoriser ou interdire l’accès aux données. 

● Activer, désactiver l’audit. 

● Commenter le dictionnaire des données. 

Les  instructions  du  DDL  sont  :  CREATE,  ALTER,  DROP,  GRANT,  REVOKE,  AUDIT,  NOAUDIT,  ANALYZE,  RENAME, 
TRUNCATE, COMMENT, FLASHBACK, PURGE. 

b. DML (Data Manipulation Language) 

Il permet la gestion des données des objets existants : 

● Ajout, suppression, modification des lignes. 

● Visualisation du contenu des tables. 

● Verrouillage des tables. 

Les instructions du DML sont : INSERT, UPDATE, DELETE, SELECT, EXPLAIN PLAN, LOCK TABLE, MERGE. 

c. Transaction Control language 

Il gère les modifications faites par le DML : 

● Caractéristiques des transactions. 

● Validation, annulation des modifications. 

Les instructions du Transaction Control sont : COMMIT, SAVEPOINT, ROLLBACK, SET TRANSACTION, SET CONSTRAINT. 

d. Session Control language 

Il permet la gestion d’une session utilisateur : 

● Modification des caractéristiques de session. 

● Activation, désactivation des privilèges utilisateurs. 

Les instructions du Session Control sont : ALTER SESSION, SET ROLE. 

- 4- © ENI Editions - All rigths reserved


e. Embedded SQL 

Il permet d’intégrer le DDL, le DML et le Transaction Control à un langage de programmation : 

● Déclarations d’objets ou d’instructions. 

● Exécutions d’instructions. 

● Gestions des variables et des cursors. 

● Traitement des erreurs. 

Les  instructions  du  Embedded  SQL  sont  :  DECLARE,  TYPE,  DESCRIBE,  VAR,  CONNECT,  PREPARE,  EXECUTE,  OPEN, 
FETCH, CLOSE, WHENEVER. 

© ENI Editions - All rigths reserved - 5-


Description des objets 
Dans l’utilisation d’une base de données, les premiers objets à manipuler sont les tables qui "contiennent" les données 
et les index qui permettent de meilleures performances aux requêtes. 
Ces deux objets doivent être créés avant de commencer à manipuler les données elles­mêmes. 

1. Les types de données 

CHAR (n) 

Chaîne de caractères de longueur fixe : n octets complétés à droite par des espaces (n <= 2000). 

VARCHAR2 (n) 

Chaîne de caractères de longueur variable : n octets au maximum (n <=4000) 

NCHAR (n) 

Chaîne de caractères de longueur fixe : n octets complétés à droite par des espaces (n <=2000). Les caractères sont 
codés suivant le jeu de caractères national actif. 

NVARCHAR2 (n) 

Chaîne de caractères de longueur variable : n octets au maximum (n <=4000). Les caractères sont codés suivant le 
jeu de caractères national actif. 

NUMBER (p,s) 

Numérique avec une précision de p chiffres dont s décimales avec (1 <= p <= 38 et ­84 <= s <= +127) 

DATE 

Date comprise entre 1er janvier 4712 avant JC et le 31 décembre 9999 après JC. 

TIMESTAMP (p) 

Données de type Date (Année, mois, jour, heure, minute et seconde) dans laquelle il est possible de préciser, à l’aide 
de la précision p, le nombre de chiffres significatifs pour les fractions de secondes. Par défaut ce nombre est 6. 

TIMESTAMP(p) WITH TIME ZONE 

Données de type TIMESTAMP avec le décalage horaire. 

TIMESTAMP(p) WITH LOCAL TIME ZONE 

Données de type TIMESTAMP WITH TIME ZONE qui sont stockées sur le serveur en tenant compte de la plage horaire 
du serveur, mais ces données sont affichées sur le poste client en tenant compte de la zone horaire définie au niveau 
de la session. 

BLOB 

Données binaires non structurées (jusqu’à 128 To selon la taille de bloc utilisé dans la base). 

CLOB 

Chaîne de caractères de longueur variable (jusqu’à 128 To selon la taille de bloc utilisé dans la base). Ne peut contenir 
que des caractères codés sur 1 octet. 

NCLOB 

Chaîne de caractères de longueur variable (jusqu’à 128 To selon la taille de bloc utilisé dans la base). Prend en charge 

© ENI Editions - All rigths reserved - 1-


les jeux de caractères de longueur variable. 

BFILE 

Données binaires stockées dans des fichiers extérieurs à la base de données (jusqu’à 2 64 ­1 octets, sauf limitation du 
système d’exploitation). 

Types assurant la compatibilité avec les versions antérieures : 

LONG 

Chaîne de caractères à longueur variable (2 Go au maximum). 

RAW (n) 

Données binaires de longueur variable (n octets maximum ; n<=2000) ; contenu non interprété par Oracle. 

LONG RAW (n) 

Données binaires de longueur variable (4 Go maximum) ; contenu non interprété par Oracle. 

2. Création d’une table 

Une table est un ensemble de lignes et de colonnes. La création consiste à définir (en fonction de l’analyse) le nom de 
ces colonnes, leur format d’utilisation (type), une valeur par défaut à la création de la ligne (DEFAULT), les règles de 
gestion s’appliquant à la colonne (CONSTRAINT). Si une règle de gestion concerne plusieurs colonnes de la ligne, on 
définit une contrainte de table. Il est possible de définir jusqu’à 1000 colonnes pour chaque table. 
Syntaxe 

CREATE TABLE nom (nomcolonne type [DEFAULT expr]


[[CONSTRAINT nom contrainte-de-colonne...],...
[,CONSTRAINT nom contrainte-de-table...]);

a. Contraintes de colonne 

NULL/NOT NULL 

Autorise (NULL) ou interdit (NOT NULL) l’insertion de valeur NULL pour cet attribut. 

PRIMARY KEY 

Désigne  l’attribut  comme  clé  primaire  de  la  table.  Cette  contrainte  ne  peut  apparaître  qu’une  seule  fois  dans 
l’instruction. 

UNIQUE 

Désigne l’attribut comme clé secondaire de la table. Dans le cas de contrainte UNIQUE portant sur une seule colonne, 
l’attribut peut prendre la valeur NULL. Cette contrainte peut apparaître plusieurs fois dans l’instruction. 

REFERENCES table [(colonne)] [ON DELETE {CASCADE | SET NULL}] 

Contrainte d’intégrité référentielle pour l’attribut dans la table détail en cours de définition. Les valeurs prises par cet 
attribut  doivent  exister  dans  l’attribut  colonne  qui  possède  une contrainte  PRIMARY  KEY  ou  UNIQUE  dans  la  table 
maître. 

CHECK (condition) 

Vérifie lors de l’insertion de lignes que l’attribut réalise la condition (pour la syntaxe de la condition, voir Manipulation 
des données). 

Attention,  il  n’est  pas  possible  dans  une  contrainte  CHECK  de  faire  référence  à  la  fonction  SYSDATE  ou  bien 
CURRENT_DATE pour comparer la valeur d’une colonne de type date avec le résultat de l’exécution de cette fonction. 
Il est par contre tout à fait possible, si on le souhaite, de comparer à l’aide d’une contrainte CHECK, les valeurs de 2 

- 2- © ENI Editions - All rigths reserved


colonnes de type date. 
Si l’on souhaite comparer la valeur d’une colonne de type date avec la date courante, il est nécessaire de passer par 
la mise en place d’un déclencheur de base de données. Une autre possibilité consiste à créer une colonne de type 
date  avec  une  valeur  par  défaut  égale  à  la  date  du  jour  plus  une  contrainte  CHECK  qui  compare  les  valeurs 
présentent dans les deux colonnes. 

b. Contraintes de table (portant sur plusieurs colonnes) 

PRIMARY KEY (colonne,...) 

Désigne  la  concaténation  des  attributs  cités  comme  clé  primaire  de  la  table.  Cette  contrainte  ne  peut  apparaître 
qu’une seule fois dans l’instruction. 

UNIQUE (colonne,...) 

Désigne  la  concaténation  des  attributs  cités  comme  clé  secondaire  de  la  table.  Dans  ce  cas  de  contrainte  UNIQUE 
portant sur des colonnes concaténées, au moins une des colonnes participant à cette clé secondaire doit permettre 
de distinguer la ligne. Cette contrainte peut apparaître plusieurs fois dans l’instruction. 

FOREIGN KEY (colonne, ...) REFERENCES table [(colonne, ...)] [ON DELETE {CASCADE | SET NULL}] 

Contrainte  d’intégrité  référentielle  pour  l’ensemble  des  attributs  dans  la  table  détail  en  cours  de  définition.  Les 
valeurs prises par ces attributs doivent exister dans l’attribut colonne qui possède une contrainte PRIMARY KEY ou 
UNIQUE dans la table maître table. 

CHECK (condition) 

Cette  contrainte  permet  d’exprimer  une  condition  qui  doit  exister  entre  plusieurs  attributs  de  la  ligne  (pour  la 
syntaxe de la condition, voir Manipulation des données). 

Les contraintes de tables portent sur plusieurs colonnes de la table sur laquelle elles sont définies. Il n’est 
pas  possible  de  définir  une  contrainte  d’intégrité  utilisant  des  colonnes  provenant  de  deux  ou  plusieurs 
tables. Ce type de contrainte sera mis en œ uvre par l’intermédiaire de déclencheurs de base de données (triggers) 
dont la définition est abordée plus loin dans cet ouvrage. 

c. Complément sur les contraintes 

ON DELETE CASCADE 

Demande  la  suppression  des  lignes  dépendantes  dans  la  table  en  cours  de  définition,  si  la  ligne  contenant  la  clé 
correspondante  dans  la  table  maître  est  supprimée.  Si  cette  option  n’est  pas  indiquée,  la  suppression  sera 
impossible dans la table maître s’il existe des lignes référençant cette valeur de clé. 

ON DELETE SET NULL 

Demande la mise à NULL des colonnes constituant la clé étrangère qui font référence à la ligne supprimée. Si cette 
option n’est pas indiquée, la suppression sera impossible dans la table maître s’il existe des lignes référençant cette 
valeur de clé. 

[NOT] DEFERRABLE 

Repousse ou non (NOT) la vérification de la contrainte au moment de la validation de la transaction. 

d. Dénomination des contraintes 

Les  contraintes  peuvent  être  nommées  afin  d’être  plus  facilement  manipulées  ultérieurement  (activation, 
suppression).  Dans  le  cas  où  aucun  nom  n’est  affecté  explicitement  à  une  contrainte,  Oracle  génère 
automatiquement un nom de la forme SYS_Cn (n est un nombre entier unique). 

Lors  de  l’affectation  explicite  d’un  nom  à  une  contrainte,  il  est  pratique  d’utiliser  la  convention  de  dénomination 
suivante : 

Table_Colonne_TypeDeContrainte 

© ENI Editions - All rigths reserved - 3-


Table  

nom de la table sur laquelle est définie la contrainte 

Colonne 

nom de la ou des colonne(s) sur laquelle (lesquelles) est (sont) définie(s) la contrainte. 

TypeDeContrainte : mnémonique associé au type de contrainte : 

PK Clé primaire 

UQ Unique 

NN Not Null 

CK Check 

RF Références 

FK Clé étrangère. 

Exemples 
Création d’une table ARTICLES avec comme seule contrainte la clé primaire REFART : 

SQL> create table ARTICLES(


2 REFART char(4) primary key,
3 DESIGNATION varchar2(30),
4 PRIX number(8,2),
5 CODETVA number(1),
6 CATEGORIE char(10),
7 QTESTK number(5)
8 );

Table créée.

SQL>

Dans ce cas, DESIGNATION, PRIX et QTESTK peuvent être NULL : PRIX et QTESTK peuvent être négatifs ! 
Création d’une table CLIENTS avec traduction des contraintes sur les colonnes : 

SQL> create table CLIENTS(


2 NOCLI number(4)
3 constraint CLIENTS_PK primary key
4 constraint CLIENTS_NOCLI_CK check (NOCLI>0),
5 NOMCLI varchar2(30)
6 constraint CLIENTS_NOMCLI_NN not null,
7 ADRCLI varchar2(60),
8 CODE_POSTAL number(5)
9 constraint CLIENTS_CODE_POSTAL_CK
10 check(CODE_POSTAL between 1000 and 99999),
11 VILLE char(30)
12 );

Table créée.

SQL>

Le NOCLI et le NOMCLI sont obligatoires ; 

Le NOCLI doit être strictement positif ; 
Le CODE_POSTAL doit être dans l’intervalle indiqué. 

Création  de  la  table  des  commandes  en  utilisant  une  syntaxe  de  type  contrainte  de  table  pour  définir  les  contraintes 
d’intégrité. 

- 4- © ENI Editions - All rigths reserved


SQL> create table COMMANDES(
2 NOCDE number(6),
3 NOCLI number(4),
4 DATECDE date,
5 ETATCDE char(2),
6 constraint PK_COMMANDES primary key (NOCDE),
7 constraint FK_COMMANDES_CLIENTS foreign key(NOCLI)
8 references CLIENTS(NOCLI),
9 constraint CK_COMMANDES_ETAT check (ETATCDE in (’EC’,’LI’,’SO’))
10 );

Table créée.

SQL>

Création d’une  table  LIGCDES  avec  des  contraintes  de  référence  sur  des  colonnes  et  une  contrainte  de  table  pour  la  clé 
primaire. 

SQL> create table LIGCDES(


2 NOCDE number(6)
3 constraint FK_LIGCDES_COMMANDES
4 references COMMANDES(NOCDE),
5 NOLIG number(2)
6 constraint CK_LIGCDES_NOLIG check (NOLIG>0),
7 REFART char(4)
8 constraint FK_LIGCDES_ARTICLES
9 references ARTICLES(REFART),
10 QTECDE number(5),
11 constraint PK_LIGCDES primary key(NOCDE,NOLIG)
12 );

Table créée.

SQL>

Quel  que  soit  le  mode  de  définition  des  contraintes  (niveau  colonne  ou  niveau  table),  le  résultat  est  le 
même.  Seules  les  contraintes  d’intégrité  portant  sur  plusieurs  colonnes  de  la  même  table  doivent  être 
définies en utilisant une syntaxe contrainte de table. 

e. Colonne virtuelle 

Une  colonne  virtuelle  est  une  colonne  définie  par  une  expression  qui  est  évaluée  lors  de  chaque  interrogation ; 
aucune valeur n’est stockée dans la table pour la colonne en question. Cette fonctionnalité est apparue en version 
11. 

Syntaxe 

nomcolonne [type] [GENERATED ALWAYS] AS (expression) [VIRTUAL]


[contrainte-de-colonne]

Le  type  de  données  est  optionnel  ;  s’il  n’est  pas  spécifié,  Oracle  le  détermine  à  partir  du  type  de  données  de 
l’expression. 

La clause AS permet de spécifier l’expression qui détermine la valeur de la colonne. Cette expression peut référencer 
d’autres colonnes réelles (non virtuelles) de la même table mais aucune colonne d’une autre table. 

Les  mots­clés  GENERATED  ALWAYS  et  VIRTUAL  sont  optionnels  ;  ils  peuvent  être  spécifiés  pour  rendre  la  syntaxe 
plus claire. 

Une contrainte de colonne peut être définie sur une colonne virtuelle. 
Exemple 

SQL> create table ARTICLES (


2 REFART char(4) primary key,
3 DESIGNATION varchar2(30),
4 PRIXHT number(8,2),
5 TAUXTVA number(4,2),

© ENI Editions - All rigths reserved - 5-


6 PRIXTTC number(8,2)
7 AS ( PRIXHT + round(PRIXHT * TAUXTVA/100,2) )
7 );

Table créée.

SQL>
SQL> insert into ARTICLES (REFART,DESIGNATION,PRIXHT,TAUXTVA)
2 values (’XT10’,’Lot de 10 crayons’,10,19.6);

1 ligne créée.

SQL> insert into ARTICLES (REFART,DESIGNATION,PRIXHT,TAUXTVA)


2 values (’AD23’,’Les Trois Mousquetaires’,10,5.5);

1 ligne créée.

SQL>
SQL> select DESIGNATION,PRIXHT,PRIXTTC from ARTICLES;

DESIGNATION PRIXHT PRIXTTC


------------------------------ ---------- ----------
Lot de 10 crayons 10 11,96
Les Trois Mousquetaires 10 10,55

3. Suppression d’une table 

Supprimer  une  table  revient  à  éliminer  sa  structure  et  toutes  les  données  qu’elle  contient  ;  les  index  associés  sont 
également  supprimés  ;  les  vues  construites  directement  ou  indirectement  sur  cette  table  sont  invalidées 
automatiquement par Oracle. 
Si la clé primaire de la table est référencée dans d’autres tables par des contraintes REFERENCES ou FOREIGN KEY, la 
clause CASCADE CONSTRAINTS permet de supprimer ces contraintes d’intégrité référentielle dans les tables "enfants". 
La clause PURGE permet de supprimer la table et de libérer l’espace physique occupée par cette table. En l’absence de 
cette  clause,  la  table  est  supprimée  logiquement  mais  pas  physiquement.  Il  est  alors  possible  d’utiliser  l’instruction 
FLASHBACK TABLE pour retrouver la table et ses données au moment de la suppression. 
Avec ce principe de fonctionnement, Oracle permet de ne plus rendre définitif une action de suppression de table et 
facilite ainsi la restauration des tables supprimées par erreur. 
Syntaxe 

DROP TABLE nom [CASCADE CONSTRAINTS] [PURGE];

Exemples 

Suppression d’une table CLIENTS dont la colonne NOCLI est clé étrangère dans la table COMMANDES : 

SQL>drop table CLIENTS;


drop table CLIENTS
*
ERREUR a la ligne 1:
ORA-02266: table a des cles primaires/uniques
referencees par des cles etrangeres

SQL>drop table CLIENTS cascade constraints;

Table supprimée.

Suppression de la table des clients avec demande de libération de l’espace physique. 

- 6- © ENI Editions - All rigths reserved


4. Modification d’une table 

Il est possible de modifier la structure d’une table à plusieurs niveaux : 

● ajout de colonnes (nom, type, valeur par défaut, contrainte NOT NULL), 

● ajout de contraintes de colonne (contrainte NOT NULL uniquement), 

● ajout de contraintes de table, 

● redéfinition d’une colonne (type, valeur par défaut), 

● activation, désactivation de contraintes de colonne ou de table, 

● suppression de contraintes de colonne ou de table, 

● changement du nom de la table. 

● autorisation ou non de modifications dans la table. 

a. Ajout ou modification de colonnes 

Syntaxe 

ALTER TABLE nom {ADD/MODIFY} ([colonne type [contrainte], ...])

Exemple 

SQL> describe CLIENTS


Name Null? Type
--------------------------- ---------- --------------
NOCLI NOT NULL NUMBER(4)
NOMCLI NOT NULL VARCHAR2(30)
ADRCLI VARCHAR2(60)
CODE_POSTAL NUMBER(5)
VILLE CHAR(30)

SQL> alter table CLIENTS add (TEL char(14));

Table modifiée.
SQL> alter table CLIENTS modify (ADRCLI char(30));

Table modifiée.
SQL> describe CLIENTS
Name Null? Type
------------------------------ --------- ------------
NOCLI NOT NULL NUMBER(4)
NOMCLI NOT NULL VARCHAR2(30)
ADRCLI CHAR(30)
CODE_POSTAL NUMBER(5)
VILLE CHAR(30)
TEL CHAR(14)
SQL>

b. Ajout d’une contrainte de table 

Syntaxe 

ALTER TABLE nom_table ADD[CONSTRAINT nom] contrainte

La syntaxe de déclaration de contrainte est identique à celle vue lors de la création de la table. 

© ENI Editions - All rigths reserved - 7-


Exemple 

L’exemple suivant permet d’ajouter une contrainte de validation à la table ARTICLES. 

SQL> alter table ARTICLES


2 add constraint ARTICLES_PRIX_CK check (PRIX >= 0) ;

Table modifiée.

SQL>

Il est également possible de définir une contrainte de non nullité par l’intermédiaire de la commande ALTER 
TABLE. 

Si des données sont déjà présentes dans la table au moment où la contrainte d’intégrité est ajoutée, alors toutes 
les lignes d’information doivent vérifier la contrainte. Dans le cas contraire, la contrainte n’est pas posée sur la table. 
La clause EXCEPTION INTO TABLE nom_table permet de connaître le rowid (l’identifiant de la ligne pour Oracle) des 
lignes qui violent la contrainte d’intégrité  que  l’on tente de poser ou de réactiver. Il est ainsi possible de résoudre 
facilement le problème. 

La  table  qui  va  recevoir  les  références  des  lignes  qui  empêchent  la  création  de  la  contrainte  d’intégrité  peut  être 
créée  par  l’intermédiaire  du  script  utlexcpt.sql  (utilisation  du  rowid  physique)  ou  utlexpt1.sql  (utilisation  du  rowid 
universel) situé dans le répertoire ORACLE_HOME\rdbms\admin. 
Création de la table des exceptions : 

Positionnez les références des lignes posant problème dans la table des exceptions. 
Tentative d’ajout d’une contrainte d’unicité sur l’adresse des clients : 

Il faut maintenant utiliser les rowids pour connaître les lignes qui empêchent l’ajout de la contrainte. 
Liste des numéros clients qui possèdent la même adresse : 

- 8- © ENI Editions - All rigths reserved


L’ajout  de  contrainte  sur  des  tables  existantes  est  une  méthode  pratique  car  associée  à  la  création  de  table,  elle 
permet de produire des scripts de création de tables sans fixer un ordre de création des tables pour tenir compte 
des contraintes de clé étrangère et de clé primaire. 

Structure d’un script de création de table 

c. Suppression d’une contrainte 

Syntaxe 

ALTER TABLE nom_table DROP{PRIMARY KEY/UNIQUE (colonne)/CONSTRAINT} nom

Exemple 

SQL> alter table ARTICLES


2 drop constraint ARTICLES_PRIX_CK;

Table modifiée.

SQL>

d. Activation, désactivation d’une contrainte 

La commande ALTER TABLE permet également d’activer et de désactiver les contraintes d’intégrité. Cette opération 
peut être intéressante lors d’un import massif de données afin, par exemple, de limiter le temps nécessaire à cette 
importation. 

Syntaxe 

ALTER TABLE nom_table {ENABLE VALIDATE/ENABLE NOVALIDATE/DISABLE}


nom_contrainte

ENABLE VALIDATE 

Active la contrainte si l’ensemble des lignes déjà présentes dans la table la respecte. 

ENABLE NOVALIDATE 

Active la contrainte pour les manipulations de données suivantes (ne vérifie pas les données actuelles). 

DISABLE 

Désactive la contrainte. 

© ENI Editions - All rigths reserved - 9-


Il  est  également  possible  de  travailler  avec  les  contraintes  de  clé  primaire  et  d’unicité  en  donnant 
simplement la définition de la contrainte. 

Exemple 
Désactivation de la contrainte sur la colonne CODE_POSTAL de la table CLIENTS. Insertion dans cette table d’une valeur 
incompatible  avec  la  contrainte  désactivée.  Tentative  de  réactivation  de  la  contrainte  avec  vérification  par  rapport  aux 
données présentes dans la table. 

SQL> alter table CLIENTS


2 disable constraint CLIENTS_CODE_POSTAL_CK;

Table modifiée.

SQL> insert into CLIENTS (NOCLI, NOMCLI, CODE_POSTAL, VILLE)


2 values (150, ’MARTIN Jean’, 999, ’MURUOA’) ;
1 ligne créée.

SQL> alter table CLIENTS


2 enable validate constraint CLIENTS_CODE_POSTAL_CK;
alter table CLIENTS
*

ERREUR à la ligne 1:
ORA-02293: impossible ajouter contrainte de vérification
[CLIENTS_CODE_POSTAL_CK] - valeurs non conf. trouvées

SQL>

e. Modification d’une contrainte 

Il n’est pas possible de modifier la définition d’une contrainte. Par contre, il est tout à fait possible de modifier l’état 
d’une contrainte. 
Syntaxe 

ALTER TABLE nom_table MODIFY CONSTRAINT nom_contrainte


etat_contrainte;

Les états possibles pour la contrainte sont : 
DEFERRABLE 

La validation de la contrainte peut être reportée à la fin de la transaction. 

NOT DEFERRABLE 

La contrainte est vérifiée à la fin de chaque instruction du DML. Cette option est activée par défaut. 

INITIALLY IMMEDIATE 

Pour  chaque  nouvelle  transaction,  le  fonctionnement  par  défaut  consiste  à  vérifier  la  contrainte  à  la  fin  de  chaque 
ordre du DML. Cette option est sélectionnée par défaut. 

INITIALLY DEFERRED 

Implique  que  la  contrainte  est  en  mode  DEFERRABLE  et  précise  que  par  défaut  cette  contrainte  est  vérifiée 
uniquement à la fin de la transaction. 

RELY ou NORELY 

La valeur RELY permet d’indiquer qu’une contrainte dans le mode NOVALIDATE peut être prise en compte par Oracle 
pour la réécriture de requête (query rewrite). La valeur par défaut est NORELY. 

USING INDEX 

- 10 - © ENI Editions - All rigths reserved


Permet  de  préciser  les  paramètres  des  index  utilisés  pour  mettre  en  place  les  contraintes  de  clés  primaire  et 
d’unicité. 

Exemple 

Modification de la contrainte de référence entre les tables LIGNESCDE et COMMANDES. 

f. Suppression de colonnes 

Il  est  possible  de  supprimer  une  colonne  en  utilisant  la  clause  DROP  COLUMN  de  l’instruction  ALTER  TABLE.  Cette 
opération permet de récupérer l’espace disque occupé par chaque colonne supprimée. 

Syntaxe 

ALTER TABLE nom_table DROP COLUMN nom_colonne;

ou 

ALTER TABLE nom_table DROP (nom_colonne, nom_colonne[,...]);

Exemple 
Suppression de la colonne TEL dans la table CLIENTS. 

Une  suppression  de  colonne  dans  une  table  existante  et  possédant  de  nombreuses  lignes  peut  s’avérer  une 
opération très longue. Il peut parfois être plus opportun de rendre la colonne inutilisable à l’aide de la clause SET 
UNUSED. Cette option ne permet pas de libérer l’espace disque occupé par la colonne, mais elle permet de planifier 
l’opération de suppression de la colonne à un moment où la charge de travail pour le serveur est moindre. 
Syntaxe 

ALTER TABLE nom_table SET UNUSED (nom_colonne[,...]);


ALTER TABLE nom_table DROP UNUSED COLUMNS [CHECKPOINT
nombre_lignes];

Exemple 

Rendre inutilisable la colonne TEL de la table CLIENT. Dans un premier temps, la colonne est masquée comme inutilisée. 

Dans  un  deuxième  temps,  il  faut  supprimer  toutes  les  colonnes  inutilisées  de  la  table  CLIENT.  Lors  de  cette 
opération,  on  demande  au  système  de  réaliser  un  point  de  synchronisation  (CHECKPOINT)  toutes  les  200 
suppressions.  Cette  précaution  évite  de  saturer  le  cache­buffer  de  données  avec  les  données  en  cours  de 
suppression et permet de réaliser très souvent des écritures disque. 

© ENI Editions - All rigths reserved - 11 -


 

Pour connaître les tables qui contiennent des colonnes inutilisées, il faut interroger la vue du dictionnaire de données 
intitulée DBA_UNUSED_COL_TABS. 

g. Changement de nom d’une table 

L’instruction  RENAME  permet  de  renommer  une  table  mais  également  les  vues,  les  séquences  et  les  synonymes 
privés. 
 
Les synonymes publics ne peuvent être renommés et doivent être supprimés puis recréés.

Syntaxe 

RENAME ancien_nom TO nouveau_nom;

Exemple 
Renommer la table ARTICLES en table PRODUITS. 

h. Mettre une table en lecture seule ou en lecture écriture 

Depuis  la  version  11,  il  est  possible  de  mettre  une  table  en  lecture  seule  pour  interdire  toute  modification  de 
données dans la table, puis de la remettre en lecture écriture ultérieurement. 
Syntaxe 

ALTER TABLE nom_table { READ ONLY / READ WRITE }

Exemple 

SQL> alter table ARTICLES read only;

Table modifiée.

SQL> delete from ARTICLES;


delete from ARTICLES
*
ERREUR à la ligne 1 :
ORA-12081: opération de mise à jour interdite sur la table
"HELIOS"."ARTICLES"

SQL> update ARTICLES set DESIGNATION = upper(DESIGNATION);


update ARTICLES set DESIGNATION = upper(DESIGNATION)
*
ERREUR à la ligne 1 :

- 12 - © ENI Editions - All rigths reserved


ORA-12081: opération de mise à jour interdite sur la table
"HELIOS"."ARTICLES"

SQL> alter table ARTICLES read write;

Table modifiée.

SQL> delete from ARTICLES;

2 ligne(s) supprimée(s).

La  structure  d’une  table  en  lecture  seule  ne  peut  pas  être  modifiée  (ajout,  modification,  suppression  de 
colonne). Par contre, une table en lecture seule peut être supprimée (DROP TABLE) ! 

5. Restauration d’une table 

L’instruction FLASHBACK TABLE permet de restaurer de façon automatique une table modifiée de façon accidentelle. Le 
laps de temps pendant lequel il est possible de revenir à la version précédente de la table est fonction de l’espace 
d’annulation réservé par la base. 
Il n’est pas possible d’inclure cette opération dans une transaction. 
Oracle ne peut pas exécuter l’instruction FLASHBACK TABLE si une modification de structure a eu lieu sur la table. 
Cette instruction permet d’annuler la suppression d’une table effectuée avec l’instruction DROP TABLE. 

Syntaxe 

FLASHBACK TABLE nomTable TO BEFORE DROP;

Exemple 
Dans l’exemple suivant, la table ligcdes est supprimée par mégarde et restaurée grâce à l’action de l’instruction FLASHBACK 
TABLE. 

L’instruction FLASHBACK TABLE permet d’annuler les modifications effectuées par les instructions INSERT, UPDATE ou 
DELETE sur une table. Il est même possible de restaurer les données d’une ou de plusieurs tables jusqu’à une date et 
heure précises. 
Pour  pouvoir  bénéficier  de  cette  fonctionnalité,  la  table  doit  être  configurée  de  façon  à  prendre  en  charge  les 
mouvements  de  lignes  dans  la  table.  Il  est  possible  de  lever  cette  option  soit  lors  de  la  création  de  la  table,  en 
utilisant la clause enable row movement, ou bien lors d’une modification de la table. 

Syntaxe 

© ENI Editions - All rigths reserved - 13 -


CREATE TABLE nomtable (....) ENABLE ROW MOVEMENT;
ALTER TABLE nomtable ENABLE ROW MOVEMENT;
FLASHBACK TABLE nomTable TO TIMESTAMP dateHeure;

Exemple 

Activer la prise en charge des mouvements de lignes sur la table des clients. 

Dans  l’exemple  suivant,  les  clients  dont  le  nom  commencent  par  E  ont  été  supprimés  par  mégarde.  La  transaction  est 
maintenant validée et les données modifiées sont visibles de tous les utilisateurs. 

Heureusement, l’utilisateur a noté l’heure à laquelle cette opération malencontreuse a été exécutée. Il est alors possible de 
restaurer les données supprimées sans pour autant faire une restauration complète de la base de données. 

 
 
Il existe également au niveau de la base de données l’instruction FLASHBACK DATABASE.

6. Gestion des index 

Les index ont pour but l’amélioration des performances des requêtes. Ils sont utilisés implicitement par l’optimiseur de 
requêtes ORACLE, et sont mis à jour automatiquement avec les lignes. 
On crée des index, de manière générale, sur toutes les clés étrangères et sur les critères de recherche courants. Une 
colonne virtuelle peut être indexée. 
Les index concernant les clés primaires et secondaires (index UNIQUE) sont créés automatiquement lors de la création 
de la contrainte avec comme nom, le nom de la contrainte. Pour les autres index, il faut utiliser le CREATE INDEX. 
 
La mise en place des contraintes de clés primaires et d’unicité passe par la création implicite d’un index.

- 14 - © ENI Editions - All rigths reserved


a. Création d’un index 

Syntaxe 

CREATE INDEX nom ON table (colonne [DESC] [, ...]);

Exemples 
Création d’un index sur les clés étrangères REFART de la table LIGNESCDE. 

SQL>create index FK_LIGART on LIGNESCDE (REFART);

Index créé.

Création d’un index sur la table CLIDIVERS sur les colonnes NOM et ADRESSE (critère de recherche) concaténées. 

SQL>create index IK_CLID on CLIDIVERS (NOMCLIENT, ADRESSE);

Index créé.

b. Suppression d’un index 

Syntaxe 

DROP INDEX nom ;

Il existe des index de différents types qui possèdent une incidence directe sur l’organisation physique des 
données et ces choix relèvent de l’administration. 

© ENI Editions - All rigths reserved - 15 -


Manipulation des données 
Les instructions du DML permettent l’ajout, la suppression, la modification et la visualisation des lignes dans les tables 
existantes. 

1. Les instructions 

Les instructions SQL manipulent des expressions. Ces expressions font référence à des noms d’objets de la base, à 
des  constantes,  comportent  des  appels  à  des  fonctions  standardisées  et  composent  ces  éléments  avec  des 
opérateurs. 

Des expressions logiques (conditions) permettent également de définir la portée des instructions. 

a. Expressions 

Les termes des expressions peuvent être : 

● constantes caractères 

exemple : ’chaîne de caractères’ ; ’Ecole Nantaise d’’Informatique’. 

● constantes littérales date (format dépendant de la langue configurée pour l’instance) 

exemple : ’15­JAN­94’ 

● constantes numériques 

exemple : 10 ; ­123.459 ; ­1.26e+6 

● noms d’attribut de table 

exemple : CLIENTS.NOCLI, ARTICLES.DESIGNATION 

● fonctions 

exemple : SQRT(81) ; REPLACE(’IAGADIGI’, ’I’, ’OU’);SYSDATE 

● pseudo­colonnes 

exemple : nomsequence.NEXTVAL ; ROWID. 

b. Opérateurs 

● arithmétiques + ­ / * ( ) 

exemple : 1.15 * PRIX ; (2 * MTLIG)/5 ; SYSDATE +15 

● sur les chaînes de caractères : concaténation || 

exemple : ’Monsieur’|| NOM 

c. Conditions 

Les conditions mettent en jeu des expressions, des opérateurs de comparaison et des opérateurs logiques. 

Opérateurs de comparaison

© ENI Editions - All rigths reserved - 1-


La  valeur  des  expressions  logiques  peut  être  VRAI,  FAUX  ou  INCONNU.  Une  comparaison  sera  évaluée  comme 
INCONNU si au moins un de ses termes est NULL. 

● Comparaison simple 

expression1 {=,!=,<>, <,<=, >, >=} expression2 

● Appartenance à un ensemble de valeurs 

expression1 IN (expression2,...) 

VRAI si expression1 apparaît au moins une fois dans la liste (expression2,...). 

● Appartenance à un intervalle de valeurs 

expression1 BETWEEN expression2 AND expression3 

VRAI si expression1 se situe entre les bornes expression2 et expression3, bornes comprises. 

● Comparaison par rapport à un format de chaîne de caractères 

expression1 LIKE ’format’ 

Le format peut inclure les méta­caractères : 

● "%" pour désigner une suite de 0 à n caractères 

● "_" pour désigner un et un seul caractère. 

Opérateurs logiques

Une expression NULL n’est ni VRAI ni FAUX. 

● Négation d’une expression logique 

NOT expression 

● Combinaison d’expressions logiques 

expression1 { AND / OR } expression2 

d. Fonctions 

Il existe deux types de fonctions : 

● Les fonctions scalaires (scalar function) qui portent sur une seule ligne : la fonction est exécutée et retourne 
un résultat pour chaque ligne de la requête. 

● Les fonctions sur un regroupement de lignes (group function) : la fonction est exécutée une fois et retourne 
un résultat pour un ensemble de lignes de la requête. Ces fonctions sont appelées fonctions d’agrégat. 

Si une fonction est appelée avec un argument NULL, la valeur retournée est NULL. Cette règle s’applique à 
toutes les fonctions à l’exception de CONCAT, NVL et REPLACE, et des fonctions d’agrégat. 

Notation des arguments des fonctions : 

n expression numérique. 

- 2- © ENI Editions - All rigths reserved


d expression date. 

c expression caractère. 

b expression logique. 

Fonctions scalaires mathématiques

ABS (n) 

valeur absolue de n. 

CEIL (n) 

premier entier supérieur ou égal à n. 

COS (n) 

cosinus. 

COSH (n) 

cosinus hyperbolique. 

EXP (n) 

e puissance n (e=2,71828183...). 

FLOOR (n) 
 
1 e r entier <=n.

LN (n) 

logarithme népérien de n. 

LOG (m,n) 

logarithme de n base m. 

MOD (n1,n2) 

reste de n1/n2. 

POWER (n1,n2) 

n1 exposant n2. 

ROUND (n1,[n2]) 

n1 arrondi à n2 positions décimales. 

SIGN (n) 

­1 si n<0; 0 si n=0; +1 si n>0. 

SIN (n) 

sinus de n. 

SINH (n) 

sinus hyperbolique de n. 

© ENI Editions - All rigths reserved - 3-


SQRT (n) 

racine carrée de n. 

TAN (n) 

tangente de n. 

TANH (n) 

tangente hyperbolique de n. 

TRUNC (n1,[n2]) 

n1 tronqué à n2 positions décimales. 

La  plupart  des  fonctions  numériques  retournent  une  valeur  avec  38  chiffres  significatifs.  Cependant  les 
fonctions COS, COSH, EXP, LN, LOG, SIN, SINH, SQRT, TAN et TANH retournent une valeur avec seulement 36 
chiffres significatifs. 

Fonctions scalaires chaînes de caractères

ASCII (c) 
 
code ASCII du 1e r caractère de c.

ASCIISTR (c) 

la chaîne de caractères passée en paramètre est convertie au format de la table ASCII de la base. 

CHR (n) 

caractère ASCII du code n. 

COMPOSE (c) 

la chaîne de caractères passée en paramètre est convertie en format UNICODE. 

CONCAT (c1, c2) 

concaténation de c1 et c2. 

DECOMPOSE (c) 

cette fonction est valide uniquement pour les chaînes au format unicode et elle retourne une chaîne contenant les 
différents caractères. 

INITCAP (c) 

renvoie c avec la première lettre de chaque mot en majuscule et les autres en minuscules. 

INSTR (c1,c2[,n1[n2]]) 
 
ère
position de la nème occurrence (défaut 1 ) de c2 dans c1 à partir de la position n1 (1 par défaut).

INSTRB (c1,c2,n1[,n2]) 

identique à INSTR avec n1 et n2 en octets. 

LENGTH (c) 

- 4- © ENI Editions - All rigths reserved


nombre de caractères de c. 

LENGTHB (c) 

identique à LENGTH retourne le nombre d’octets. 

LOWER (c) 

renvoie c en minuscules. 

LPAD (c1,n[,c2]) 

renvoie c1 sur une longueur n complété à gauche avec c2 (par défaut ’ ’). 

LTRIM (c1[,c2]) 

renvoie c1 avec suppression à gauche de tous les c2 (par défaut ’ ’). 

NLS_INITCAP (c,’param’) 

identique à INITCAP en tenant compte de param (code de pays). 

NLS_LOWER (c,’param’) 

identique à LOWER en tenant compte de param (code de pays). 

NLSSORT (c) 

séquence d’octets utilisés pour le tri de la chaîne c. 

NLS_UPPER (c,’param’) 

identique à UPPER en tenant compte de param (code de pays). 

REPLACE (c1,c2,c3) 

remplace dans c1 tous les c2 par c3 (c3 peut être nul). 

RPAD (c1,n[,c2]) 

renvoie c1 sur une longueur n complété à droite avec c2 (par défaut ’ ’). 

RTRIM (c1[,c2]) 

renvoie c1 avec suppression à droite de tous les c2 (par défaut ’ ’). 

SOUNDEX (c) 

représentation phonétique de c. 

SUBSTR (c,n1[,n2]) 

renvoie une chaîne formée par n2 caractères de c à partir de la position n1. 

SUBSTRB (c,n1[,n2]) 

identique à SUBSTR avec n1 et n2 en octets. 

TRANSLATE (c1,c2,c3) 

remplace dans c1 tous les c2 par c3 (c3 ne peut pas être nul). 

TRIM ({{LEADING |TRAILING|BOTH c1} | {c1}} FROM c2 ) 

© ENI Editions - All rigths reserved - 5-


le caractère c1 est supprimé de la chaîne c2 soit en tête de chaîne (LEADING), soit en fin de chaîne (TRAILING), soit 
les deux (BOTH ou aucun mot clé). 

UNISTR (c) 

la chaîne de caractères passée en paramètre est convertie au format unicode. 

UPPER(c) 

renvoie c en majuscules. 

Fonctions scalaires dates

ADD_MONTHS (d,n) 

date d plus n mois (n peut être négatif). 

CURRENT_DATE 

pour connaître la date et l’heure actuelle en prenant en compte le paramétrage de la zone horaire (TIME_ZONE) de 
la session. 

CURRENT_TIMESTAMP 

pour connaître la date et l’heure relative à la plage horaire de la session. Cette fonction retourne une valeur de type 
TIMESTAMP WITH TIME ZONE. 

DBTIMEZONE 

pour connaître la zone horaire en vigueur sur la base de données. 

EXTRACT (format FROM d) 

extrait  un  élément  (jour,  mois,  année,  heure,  minute,  seconde...)  depuis  un  élément  de  type  date  ou  bien  un 
intervalle de temps calculé à l’aide des fonctions NUMTODSINTERVAL ou NUMTOYMINTERVAL. 

FROM_TZ (t, zone_horaire) 

convertit une valeur de type TIMESTAMP en valeur de type TIMESTAMP WITH TIME ZONE. 

LAST_DAY (d) 

date du dernier jour du mois de d. 

LOCALTIMESTAMP 

pour connaître la date et heure courante par rapport à la zone horaire de la session. Cette fonction retourne une 
valeur de type TIMESTAMP. 

MONTHS_BETWEEN (d1,d2) 

différence en mois entre les deux dates. 

NEW_TIME (d,z1,z2) 

la date d de la zone z1 est convertie en date de la zone z2. 

NEXT_DAY (d,j) 

date du prochain jour j à partir de d. 

NUMTODSINTERVAL (n,format) 

convertit le nombre n passé en paramètre au format date. Le second argument représente l’unité dans laquelle n est 

- 6- © ENI Editions - All rigths reserved


exprimé. Les valeurs possibles sont ’DATE’, ’HOUR’, ’MINUTE’ et ’SECOND’. 

NUMTOYMINTERVAL (n, format) 

convertit le nombre n passé en paramètre au format mois, année. Le format indiqué en second paramètre permet de 
préciser si le premier paramètre représente des mois (’MONTH’) ou des années (’YEAR’). 

ROUND (d, format) 

arrondit la date d à la date de début de l’élément donné en format le plus proche (Année, Mois, Jour, Heure...). 

SESSIONTIMEZONE 

pour connaître la zone horaire active dans la session actuelle. 

SYSDATE 

date système. 

SYS_EXTRACT_UTC (d) 

convertit  une  date  et  heure  d’une  zone  horaire  spécifique  en  date  et  heure  au  format  UTC  (Universal  Time 
Coordinated) c’est­à­dire à l’heure de Greenwich. 

SYSTIMESTAMP 

pour connaître la date et l’heure, y compris les fractions de secondes, en s’appuyant sur la zone horaire configurée 
sur le serveur de base de données. 

TRUNC (d, format) 

tronque la date d au début de l’élément donné en format (Année, Mois, Jour, Heure...). 

TZ_OFFSET (zone|format) 

permet de connaître la zone horaire correspondant à la zone passée en paramètre. 

Les  formats  de  dates  sont  utilisés  par  les  fonctions  de  conversion  (TO_CHAR,  TO_DATE)  et  les  fonctions  qui 
manipulent  les  dates  (TRUNC,  ROUND).  On  trouve  ci­dessous  un  tableau  récapitulatif  des  principaux  indicateurs  de 
format de dates qui peuvent être utilisés. 

­ / ’ . ; : ’texte’  Éléments de séparation présents dans le résultat. 

D  Numéro du jour dans la semaine (1 à 7). Cet indicateur est à utiliser 
uniquement avec la fonction TO_DATE. 

DAY  Nom du jour de la semaine. 

DD  Numéro du jour dans le mois (1 à 31). 

DDD  Numéro du jour dans l’année (1 à 366). 

DY  Nom abrégé du jour de la semaine. 

HH, HH12  Heure du jour (1 à 12). 

HH24  Heure du jour (0 à 23). 

IW  Numéro de la semaine dans l’année (1 à 53) basé sur la norme ISO. 

MI  Minute (0 à 59). 

MM  Numéro du mois sur 2 caractères (1 à 12). 

© ENI Editions - All rigths reserved - 7-


MON  Nom abrégé du mois. 

MONTH  Nom du mois. 

Q  Numéro du trimestre (1 à 4). 

RM  Numéro du mois en chiffre romain (I à XII). 

SS  Secondes (0 à 59). 

SSSS  Nombre de secondes depuis minuit (0 à 86399). 

WW  Numéro de la semaine dans l’année. La semaine n°1 commence le premier jour 
de l’année et dure 7 jours. 

W  Numéro de la semaine dans le mois (1 à 5). La première semaine du mois 
commence le premier jour du mois et se termine le septième jour. 

YYYY  Année sur 4, 3, 2 ou 1 chiffre(s). 
YYY 
YY 

Fonctions scalaires de conversion

BIN_TO_NUM (expr[, ...]) 

conversion d’un ensemble de nombres binaires en son équivalent décimal. 

CHARTOROWID (char) 

conversion de chaîne de caractères de forme ’nobloc.nolig.nofich’ en type ROWID. Cette pseudo­colonne représente 
l’adresse physique de la ligne dans la base Oracle. 

CONVERT (char,destination[,source]) 

conversion de jeu de caractères. 

source ou destination 

US7ASCII (défaut), WE8DEC (Dec Europe), WE8JHP (HP Europe), F7DEC (français DEC), WE8EBDCIC500 (IBM Europe 
Code page 500), WE8PC850 (IBM PC Code page 850), WE8ISO8859P1 (ISO8859­1 Europe 8 bits). 

HEXTORAW (char) 

conversion d’une valeur hexadécimale contenue dans une chaîne de caractères en une expression binaire de type 
RAW. 

RAWTOHEX (raw), RAWTONHEX (raw) 

fonction inverse de la précédente. 

ROWIDTOCHAR(rowid), ROWIDTONCHAR (rowid) 

fonction inverse de CHARTOROWID. 

TO_CHAR (caractère) 

conversion  d’une  chaîne  de  caractères  au  format  NCHAR,  NVARCHAR2,  CLOB  ou  NCLOB  dans  le  jeu  de  caractères 
utilisée dans la base de données. 

- 8- © ENI Editions - All rigths reserved


TO_CHAR (n,[format[,’param’]]) 

conversion numérique en caractères. 

format  :  chaîne  de  caractères  représentant  le  format  numérique  (les  éléments  possibles  de  cette  chaîne  de 
caractères sont présentés dans le tableau des formats de date vu précédemment). 

param : convention de pays. 

TO_CHAR (d, format) 

conversion d’une date en chaîne de caractères. 

TO_CLOB (chaîne) 

conversion d’une chaîne de caractères ou de type LOB au format CLOB. 

TO_DATE (char, format) 

fonction inverse de TO_CHAR (caractère en date). 

TO_DSINTERVAL (chaîne) 

conversion d’une chaîne de caractères en données de type intervalle Jour/Seconde. 

TO_NCHAR (c) 

conversion d’une chaîne de caractères dans le jeu de caractères national (deuxième jeu de caractères de la base). 

TO_NCHAR (d,format) 

conversion d’une date en chaîne, dans le jeu de caractères national. 

TO_NCHAR (n) 

conversion d’un nombre en chaîne de caractères dans le jeu de caractères national. 

TO_NCLOB (c) 

conversion d’une chaîne de caractères en élément de type NCLOB. 

TO_NUMBER (char) 

conversion d’une chaîne de caractères en numérique. 

TO_TIMESTAMP (c[,format]) 

conversion d’une chaîne de caractères en élément de type TIMESTAMP en s’appuyant sur le format de la date indiqué 
en second paramètre. 

TO_TIMESTAMP_TZ (c[,format]) 

conversion d’une chaîne de caractères en élément de type TIMESTAMP WITH TIME ZONE en s’appuyant sur le format 
de la date indiqué en second paramètre. 

TO_YMINTERVAL (chaîne) 

conversion d’une chaîne de caractères en données de type intervalle Mois/Année. 

Exemple d’utilisation de fonctions de conversion 
Dans l’exemple ci­dessous, la fonction SYSDATE permet de connaître la date et l’heure actuelle puis ces informations sont 
affichées proprement à l’aide de la fonction de conversion de TO_CHAR. Pour convertir la date en chaîne de caractères, on 
utilise un format de conversion dont les indicateurs sont donnés dans le tableau précédent. 

© ENI Editions - All rigths reserved - 9-


 

Fonctions de comparaisons

NULLIF (expr1, expr2) 

Compare expr1 et expr2. Si les deux expressions sont égales, alors la valeur NULL est retournée, sinon expr1 est 
retournée. Il n’est pas possible de préciser la valeur NULL dans expr1. 

Fonctions scalaires diverses

BITAND (arg1, arg2) 

effectue une opération ET entre les deux arguments bit par bit. 

COALESCE (expr,[, ...]) 

retourne la première expression non nulle passée en paramètre. 

DECODE (colonne, valeur 1, resul1 [,valeur2, resul2 ...],[défaut]) 

si colonne a la valeur valeur 1, la forme sera resul1. 

DUMP (exp[,format[,départ[longueur]]]) 

les formats possibles sont : 

8 (le résultat est exprimé en octal), 

10 (le résultat est exprimé en décimal), 

16 (le résultat est exprimé en hexadécimal), 

17 (le résultat est exprimé en caractères). 

Les options départ et longueur permettent de préciser la partie de la chaîne à traiter. 

GREATEST (exp[,exp...]) 

renvoie la plus grande des expressions. 

LEAST (exp[,exp......]) 

renvoie la plus petite des expressions. 

NVL (exp1, exp2) 

si expression1 est NULL renvoie expression2. 

NVL2 (exp1, exp2, exp3) 

si expression1 est NULL, alors la fonction NVL2 retourne expression2, sinon c’est expression3 qui est retournée. Les 
expressions 2 et 3 peuvent être de n’importe quel type de données à l’exception du type LONG. 

UID 

numéro identificateur de l’utilisateur. 

- 10 - © ENI Editions - All rigths reserved


USER 

nom de l’utilisateur. 

USERENV (opt) 

renvoie des caractéristiques de l’environnement. 

opt : ENTRY ID ; SESSION ID ; TERMINAL ; LANGUAGE ; LANG ; ISDBA ; CLIENT_INFO. 

VSIZE (exp) 

nombre d’octets stockés pour exp. 

WIDTH_BUCKET (expr, mini, maxi, n) 

construit  n  intervalles  équivalents  sur  la  plage  mini  à  maxi  puis  indique  dans  quel  intervalle  se  trouve  chaque 
expression. 

2. Création de lignes 

L’ajout d’une  ligne  à  la  table  est  réalisé  si  les  contraintes  sont  respectées.  Si  les  noms  des  colonnes  à  valoriser  ne 
sont  pas  cités,  une  expression  doit  être  donnée  pour  chaque  colonne  dans  l’ordre des définitions de colonne faites 
lors de la création de la table. Aucune colonne ne peut être omise. 
Syntaxe 

INSERT INTO table [(colonne ,...)] VALUES (expression ,...) ;

Exemples 
Création d’un client (les colonnes non citées sont à NULL). 

SQL> insert into CLIENTS (NOCLI, NOMCLI)


2 values (37, ’Ets LAROCHE’);

1 ligne créée.

SQL>

Valorisation de toutes les colonnes pour un article : 

SQL> insert into ARTICLES


2 values (’AB03’, ’Carpettes’, 150, 2, ’IMPORT’, 80);

1 ligne créée.

SQL>

Valorisation  d’une  ligne  de  commande,  avec  saisie  de  variable  par  SQLPLUS  (première  colonne,  voir  chapitre  SQL*Plus)  et 
expression pour le calcul de la quantité (dernière colonne) : 

SQL> insert into LIGCDES


2 values (&NumCde, 1, ’AB10’, 2+6);
Entrez une valeur pour numcde: 1
ancien 2: values (&NumCde, 1, ’AB10’, 2+6)
nouveau 2: values (1, 1, ’AB10’, 2+6)

1 ligne créée.

SQL>

Pour insérer une valeur NULL dans une colonne, il faut remplir toutes les colonnes pour lesquelles on possède 
une  valeur,  à  l’aide  de  la  syntaxe  indiquée  dans  l’exemple  ci­dessus  (les  autres  colonnes  auront  la  valeur 
NULL). 

© ENI Editions - All rigths reserved - 11 -


Pour utiliser la valeur par défaut d’une colonne lors de l’insertion, il est possible d’utiliser le mot clé DEFAULT. 

L’instruction INSERT permet d’ajouter une ou plusieurs lignes dans la table de destination. 
Si  l’insertion  d’une  ligne  d’informations  est  le  fonctionnement  le  plus  fréquent,  il  est  également  possible  d’ajouter 
plusieurs  lignes  dans  la  table.  Ces  lignes  insérées  de  façon  massive  sont  extraites  de  la  base  de  données  par  une 
requête de type SELECT. 
Ce processus facilite le transfert de données d’une table à une autre. 

Syntaxe 

INSERT INTO table[(colonne, ...)] SELECT colonne,... .


FROM table ...;

Exemple 
Extraction de la liste des clients qui habitent Nantes vers une nouvelle table. 

3. Suppression de lignes 

Instruction DELETE

L’instruction  DELETE  supprime  toutes  les  lignes  d’une  table.  Si  la  clause  WHERE  est  utilisée,  seules  les  lignes  pour 
lesquelles la condition est vraie sont supprimées. 

Syntaxe 

DELETE FROM table [WHERE condition] ;

Exemples 

Suppression d’un article facture : 

SQL>delete from ARTICLES where REFART = ’ZZZZ’;

1 ligne supprimée.

Tentative de suppression d’articles  valant  entre  153  et  306  euros.  Certains  de  ces  articles  sont  référencés  dans  d’autres 
tables, d’où l’erreur : 

SQL> delete from ARTICLES


2 where PRIX >153 and PRIX <306;
delete from ARTICLES
*
ERREUR à la ligne 1 :
ORA-02292: violation de contrainte (JGABILLAUD.FK_LIGCDES_ARTICLES)
d’intégrité - enregistrement fils existant

- 12 - © ENI Editions - All rigths reserved


SQL>

Suppression des lignes référençant les articles : 

SQL> delete from LIGCDES;

1 ligne supprimée.

SQL>

Suppression des articles valant entre 153 et 306 euros (AB10, AB22) : 

SQL> delete from ARTICLES


2 where PRIX between 153 and 306;

2 ligne(s) supprimée(s).

SQL>

Suppression des articles dont la désignation commence par "Ca" (AA00;AB03) : 

SQL>delete from ARTICLES where DESIGNATION like ’Ca%’;


2 ligne(s) supprimée(s).

Suppression des articles dont la quantité en stock n’est pas valorisée : 

SQL>delete from ARTICLES where QTESTK is null;

2 ligne(s) supprimée(s).

Instruction TRUNCATE

L’instruction TRUNCATE permet de supprimer toutes les lignes d’une table et de reprendre les conditions de stockage 
adoptées lors de la création de la table. 
Syntaxe 

TRUNCATE TABLE table

Exemple 
Suppression des produits. 

4. Modification de lignes 

L’instruction UPDATE permet de remplacer, dans une table, la valeur des colonnes spécifiées par des expressions. Si 
aucune  clause  WHERE  n’est  spécifiée,  la  mise  à  jour  est  réalisée  pour  toutes  les  lignes  de  la  table.  Dans  le  cas 
contraire, seules les lignes pour lesquelles la condition spécifiée dans la clause WHERE est vérifiée sont mises à jour. 
Syntaxe 

UPDATE table SET colonne = expression, ... [WHERE condition];

Exemples 
Mise à jour de la quantité en stock à 15 pour l’article AB10 : 

SQL>update ARTICLES set QTESTK=15 where REFART=’AB10’;

© ENI Editions - All rigths reserved - 13 -


1 ligne mise à jour.

Augmentation de 10% du prix pour les articles dont la référence commence par AB : 

SQL> update ARTICLES


2 set PRIX=PRIX*1.1
3 where REFART like ’AB%’;

4 ligne(s) mise(s) à jour.

Passage de la désignation en majuscules et élimination des espaces en fin de référence pour tous les articles : 

SQL>update ARTICLES set DESIGNATION=UPPER(DESIGNATION),


REFART=rtrim (REFART);

8 ligne(s) mise(s) à jour.

5. Extraction des données 

L’instruction SELECT permet d’afficher les données d’une table, vue ou synonyme. 
Syntaxe 

SELECT {* | expression, ...} FROM table [WHERE condition];

* signifie toutes les colonnes. 
Exemple 
Visualisation de toute la table ARTICLES : 

SQL> select * from ARTICLES ;

Table initiale : 

SQL> select * from ARTICLES ;

REFA DESIGNATION PRIX CODETVA CATEGORIE QTESTK


------------------ ---------- -------- ---------- -----------
AB22 Tapis Persan 1250,1 2 IMPORT 5
CD50 Chaine HiFi 735,4 2 IMPORT 7
ZZZZ Article bidon DIVERS 25
AA00 CAdeau 0 DIVERS 8
AB03 Carpette 150 2 SOLDES 116
AB Tapis 2 DIVERS 2
ZZ01 Lot de tapis 500 2 DIVERS 0
AB10 Tapis de Chine 1500 2 IMPORT 10
8 ligne(s) sélectionnée(s).
SQL>

Références ayant moins de 20 unités en stock : 

SQL> select REFART from ARTICLES where QTESTK < 20 ;


REFA
----
AB22
CD50
AA00
AB
ZZ01
AB10
6 ligne(s) sélectionnée(s).
SQL>

6. Contrôle des transactions 

- 14 - © ENI Editions - All rigths reserved


Une transaction est un ensemble d’instructions du DML (INSERT, UPDATE, DELETE) exécutées entre deux commandes 
CONNECT, COMMIT et ROLLBACK. 

La transaction permet de s’assurer que l’ensemble des instructions incluses dans celle­ci sera réalisé dans sa totalité 
ou pas du tout. 

Une seule transaction est active à un instant donné. Cette transaction se termine lors de l’utilisation de l’instruction 
COMMIT ou ROLLBACK. Une nouvelle transaction débute lors de la première instruction DML suivante. 

Chaque transaction permet également d’assurer la cohérence des données vues par chaque utilisateur connecté au 
SGBDR. En effet toutes les modifications faites sur les données au cours d’une transaction se font par rapport à l’état 
de ces données au début de la transaction. Les modifications apportées sur les données au cours d’une transaction 
exécutée  par  un  utilisateur  ne  seront  visibles  des  autres  utilisateurs  qu’après  la  validation  (COMMIT)  de  cette 
transaction. 

a. Validation de la transaction 

Les modifications de lignes depuis le dernier COMMIT ou CONNECT deviennent définitives. 

Il est également possible de mettre fin à une transaction en succès simplement en exécutant une instruction du DDL, 
comme  par  exemple  une  commande  CREATE,  ALTER  ou  DROP.  En  effet,  les  instructions  du  DDL  ne  peuvent  pas 
participer à la transaction. La transaction en cours est donc finie avec succès, puis l’instruction DDL est exécutée et 
une  nouvelle  transaction  débute.  Cette  nouvelle  transaction  concernera  les  instructions  DML  qui  suivent.  Cette 
validation  de  transaction  est  faite  de  façon  implicite  et  peut  être  la  source  d’erreur  dans  la  compréhension  du 
mécanisme des transactions. 
Syntaxe 

COMMIT;

b. Annulation des modifications 

Les modifications de lignes faites depuis le dernier COMMIT, CONNECT ou le SAVEPOINT mentionné sont annulées. 
Si le ROLLBACK indique un SAVEPOINT, la transaction en cours est toujours active après l’exécution de l’instruction. 
Syntaxe 

ROLLBACK [TO savepoint];

c. Déclaration d’un point de contrôle 

Un point de contrôle permet de mémoriser un état des données au cours de la transaction. La pose d’un SAVEPOINT 
permet d’annuler les modifications faites après la pose de celui­ci. 

La transaction en cours est toujours active après la pose du SAVEPOINT. 

Syntaxe 

SAVEPOINT savepoint;

Exemple 

SQL> savepoint s1;

Savepoint créé.

SQL> select nocli, rtrim(nomcli), ville from clients;

NOCLI RTRIM(NOMCLI) VILLE


---------- --------------------------- ------------------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
36 Bernard S.A. PARIS
37 Ets LAROCHE
138 DUBOIS Jean TOURS
152 LAROCHE LE MANS

© ENI Editions - All rigths reserved - 15 -


7 ligne(s) sélectionnée(s).

SQL> delete from clients where nocli>35;

4 ligne(s) supprimée(s).

SQL> select nocli, rtrim(nomcli), ville from clients;

NOCLI RTRIM(NOMCLI) VILLE


---------- ------------------------------ ----------------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES

SQL> savepoint s2;

Savepoint créé.
SQL> insert into clients (nocli, nomcli, ville)
2 values (111,’DURAND’,’RENNES’);

1 ligne créée.

SQL> select nocli, rtrim(nomcli), ville from clients;

NOCLI RTRIM(NOMCLI) VILLE


---------- ------------------------------ ----------------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
111 DURAND RENNES

SQL> rollback to s2;

Annulation (rollback) effectuée.

SQL> select nocli, rtrim(nomcli), ville from clients;

NOCLI RTRIM(NOMCLI) VILLE


---------- ------------------------------ -----------------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES

SQL> rollback to s1;

Annulation (rollback) effectuée.

SQL> select nocli, rtrim(nomcli), ville from clients;

NOCLI RTRIM(NOMCLI) VILLE


---------- ------------------------------ ------------------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
36 Bernard S.A. PARIS
37 Ets LAROCHE
138 DUBOIS Jean TOURS
152 LAROCHE LE MANS

7 ligne(s) sélectionnée(s).

SQL> commit;

Validation effectuée.
SQL>

d. Accès simultané aux données 

- 16 - © ENI Editions - All rigths reserved


Lors  de  l’accès  aux  mêmes  données  (tables)  à  partir  de  plusieurs  transactions,  Oracle  garantit  la  cohérence  des 
données  dans  la  transaction  par  rapport  à  la  lecture  initiale.  Tant  qu’une  transaction  n’est  pas  validée  par  une 
instruction COMMIT, les modifications faites sur les données à l’intérieur de la transaction sont invisibles des autres 
utilisateurs. 
Exemple 

Deux sessions (session 1 et session 2) sont ouvertes sous le même nom d’utilisateur. 
Session 1 : insertion d’une ligne dans la table COMMANDES. La ligne insérée est visible dans la transaction. 

SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC

SQL>insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)


2 values (2000, 35, SYSDATE, ’EC’) ;

1 ligne créée.

SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2000 35 22/11/98 EC

SQL>

Session  2  :  Pas  de  COMMIT  dans  la  session  1  après  l’insertion.  La  ligne  insérée  n’est  pas  visible  dans  la  session  2. 
Insertion d’une ligne dans la table COMMANDES. 

SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC

SQL>insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)


2 values (2001, 15, SYSDATE, ’EC’) ;

1 ligne créée.
SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2001 15 22/11/98 EC

SQL>

Session 1 : COMMIT 

SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET

© ENI Editions - All rigths reserved - 17 -


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2000 35 22/11/98 EC

SQL>commit ;

Validation effectuée.
SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2000 35 22/11/98 EC

SQL>

Session 2 : la ligne insérée à l’étape 1 dans la transaction est maintenant visible dans la session 2. 

SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;

NOCDE NOCLI DATECDE ET


-------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2000 35 22/11/98 EC
2001 15 22/11/98 EC

6 ligne(s) sélectionnée(s).

SQL>commit ;
Validation effectuée.
SQL>select NOCDE, NOCLI, DATECDE, ETATCDE from COMMANDES ;
NOCDE NOCLI DATECDE ET
--------------------------------------
1301 15 20/11/98 EC
1210 15 12/11/98 SO
1250 35 14/11/98 EC
1230 35 14/11/98 EC
2000 35 22/11/98 EC
2001 15 22/11/98 EC
6 ligne(s) sélectionnée(s).
SQL>

e. Vérification des contraintes en fin de transaction 

Dans  certains  cas,  il  peut  être  nécessaire  de  vérifier  les  contraintes  d’intégrité  en  fin  de  transaction.  Pour  pouvoir 
profiter de cette fonctionnalité, il est nécessaire de préciser, lors de la mise en place de la contrainte d’intégrité, que 
sa  vérification  est  différée  en  fin  de  transaction  (INITIALLY  DEFERRED),  ou  bien  si,  au  contraire,  il  est  possible  de 
demander  dans  certains  cas  la  validation  de  la  contrainte  en  fin  de  transaction  (DEFERRABLE).  Par  défaut,  les 
contraintes  d’intégrité  sont  vérifiées  dès  la  mise  en  place  des  valeurs  dans  les  tables  et  il  n’est  pas  possible  de 
déplacer cette vérification en fin de transaction. 

La  syntaxe  exacte  de  mise  en  place  de  ces  états  de  contrainte  est  expliquée  dans  le  titre  Création  d’une 
table ­ Complément sur les contraintes dans ce chapitre. 

Ainsi, dans l’exemple présenté ci­après, il est nécessaire de posséder un abonnement pour pouvoir être membre et 
chaque abonnement doit être possédé par un et un seul membre. 
La  mise  en  place  de  cette  liaison  1­1  entre  les  2  tables  va  s’effectuer  en  mettant  en  place  une  contrainte  de 
référence entre les 2 tables. Chaque occurrence d’abonnement référence une et une seule occurrence de membre et 

- 18 - © ENI Editions - All rigths reserved


chaque occurrence de membre fait référence à une et une seule occurrence d’abonnement. 
Pour cet exemple, il est nécessaire d’ajouter, au cours de la même transaction, un membre et son abonnement puis 
de demander la vérification des contraintes de référence lors de la validation de la transaction. 
Création des tables avec les contraintes de clé primaire 

Mise en place des contraintes de clé étrangère 

Insertion de données 

© ENI Editions - All rigths reserved - 19 -


Traduction de l’algèbre relationnelle 
La  méthode  de  l’algèbre  relationnelle  permet  de  résoudre  des  extractions  de  données  en  créant  des  tables 
intermédiaires par l’utilisation d’opérateurs (UNION, RESTRICTION, JOINTURE, etc.). Cette méthode peut être traduite en 
SQL  grâce  à  l’instruction  SELECT  qui  permet  toutes  les  opérations  par  ses  différentes  clauses  (WHERE,  GROUP  BY, 
UNION, etc.), et par les instructions CREATE et INSERT qui permettent la gestion des tables intermédiaires. 

1. Opérations 

a. Restriction 

La restriction permet de n’obtenir que les lignes répondant à une condition. 
L’opération σ s (cond) se traduit par : 

SELECT * FROM S WHERE cond ;

Exemple 
Restriction sur le numéro de commande dans la table CDE = σ COMMANDES (NOCDE = 100) : 

SQL> select * from COMMANDES where NOCDE = 100 ;

NOCDE NOCLI DATECDE ET


--------------------------------------
100 15 18/11/98 EC

SQL>

b. Calculs élémentaires 

Le calcul élémentaire permet d’obtenir des colonnes calculées pour chaque ligne. L’opération π S (col, ..., nvcol = exp) 
se traduit par : 

SELECT col, ..., expression FROM S ;

Exemple 
Calcul de la valeur de stock π ARTICLES(REFART, DESIGNATION, VALSTK = (PRIXHT * QTESTK)) : 

SQL> select REFART, DESIGNATION, (PRIX * QTESTK) from ARTICLES ;

REFA DESIGNATION (PRIX*QTESTK)


---- --------------------------- ---------------------
AB22 Tapis Persan 6250,5
CD50 Chaine HiFi 5147,8

ZZZZ Article bidon


AA00 CAdeau 0
AB03 Carpette 17400
AB Tapis
ZZ01 Lot de tapis 0
AB10 Tapis de Chine 15000

8 ligne(s) sélectionnée(s).

SQL>

c. Projection 

La  projection  a  pour  but  d’éliminer  les  colonnes  inutiles.  Elle  se  fait  en  SQL  en  ne  citant  que  les  colonnes  voulues 
dans le SELECT. 

© ENI Editions - All rigths reserved - 1-


Exemple 
Simplification de la table CLI = π CLIENTS (NOCLI, NOMCLI) : 

SQL> SELECT NOCLI, NOMCLI from CLIENTS;

Les projections de regroupement peuvent s’effectuer à l’aide de deux syntaxes : 

SELECT DISTINCT {* | liste de colonnes} FROM table ;

ou 

SELECT liste de colonnes FROM table GROUP BY


liste de colonnes ;

La  première  syntaxe  (DISTINCT)  permet  de  n’afficher qu’une  occurence  de  ligne  dans  le  cas  où  la  requête  ramène 
plusieurs  lignes  identiques.  La  deuxième  syntaxe  (GROUP  BY)  est  utilisée  lorsque  l’on  souhaite  réaliser  une 
projection de groupe avec le calcul d’agrégats sur les lignes regroupées. 

Le mot clé DISTINCT permet uniquement d’effectuer l’affichage de valeurs distinctes, tandis que le mot clé GROUP BY 
effectue  en  premier  lieu  un  regroupement.  Cette  opération  de  regroupement  rend  possible  les  calculs  d’agrégats 
mais demande bien sûr un peu plus de temps au niveau du processeur du serveur. 

Exemples 
Affichage d’une ligne par nom client : 

SQL> select NOMCLI from CLIENTS ;

NOMCLI
------------------------------
DUPONT S.A.
Etb LABICHE
DUBOIS Jean
BERNARD S.A.
DUBOIS Jean
LAROCHE

6 ligne(s) sélectionnée(s).

SQL> select distinct NOMCLI from CLIENTS ;

NOMCLI
------------------------------
BERNARD S.A.
DUBOIS Jean
DUPONT S.A.
Etb LABICHE
LAROCHE
SQL> select NOMCLI from CLIENTS group by NOMCLI;
NOMCLI

------------------------------
BERNARD S.A.
DUBOIS Jean
DUPONT S.A.
Etb LABICHE
LAROCHE

SQL>

Regroupement par NOM et VILLE. 

SQL> select NOMCLI, VILLE from CLIENTS group by NOMCLI, VILLE;

NOMCLI VILLE
-----------------------------------------
BERNARD S.A. PARIS
DUBOIS Jean NANTES
DUBOIS Jean TOURS
DUPONT S.A. NANTES

- 2- © ENI Editions - All rigths reserved


Etb LABICHE NANTES
LAROCHE LE MANS

6 ligne(s) sélectionnée(s).

SQL>

d. Calculs d’agrégats 

Les projections de calcul d’agrégats permettent des calculs statistiques sur des regroupements introduits par GROUP 
BY. 

L’opération π S (col, ..., nvcol = calcul statistique) se traduit par : 

SELECT liste de colonnes, fonction groupe FROM S GROUP BY


liste colonnes ;

La  liste  de  colonnes  projetées  (derrière  le  SELECT)  doit  être  identique  à  la  liste  de  colonnes  de  regroupement 
(derrière le GROUP BY). 

Les noms des colonnes peuvent apparaître dans des calculs élémentaires ; dans ce cas le regroupement doit porter 
sur les mêmes expressions. 

e. Fonctions de GROUPE 

coln 

Colonne numérique. 

colonne 

Colonne de tout type. 

AVG (coln) 

Moyenne des valeurs de colonne. 

COUNT (colonne) 

Pour chaque regroupement, nombre de lignes regroupées où colonne est non NULL. 

COUNT (*) 

Pour chaque regroupement, nombre de lignes regroupées. 

MAX (colonne) 

Valeur maximum de la colonne pour chaque regroupement. 

MIN (colonne) 

Valeur minimum de la colonne pour chaque regroupement. 

STDDEV (coln) 

Écart­type des valeurs de colonne pour chaque regroupement. 

SUM (coln) 

Somme des valeurs de colonne pour chaque regroupement. 

VARIANCE (coln) 

Variance des valeurs de colonne pour chaque regroupement. 

© ENI Editions - All rigths reserved - 3-


CORR (col1, col2) 

Cœ fficient de corrélation entre les 2 colonnes. 

COVAR_POP (col1, col2) 

Covariance d’une population. 

COVAR_SAMP (col1, col2) 

Covariance d’un échantillon. 

CUME_DIST (col, pourcentage) 

Distribution cumulative. 

DENSE_RANK (col) 

Numéro d’ordre d’une ligne dans un ensemble ordonné de lignes. 

FIRST (col) LAST (col) 

Retourne la première (dernière) ligne ordonnée par rapport à un critère tri (DENSE_RANK par exemple). 

GROUP_ID 

Distingue les groupes dupliqués apparus suite à l’application de la clause GROUP BY. 

GROUPING (expr) 

Permet d’identifier les lignes de cumul lorsque les instructions ROLLUP ou CUBE sont utilisées. 

GROUPING_ID (expr) 

Comme pour la fonction GROUPING, permet d’identifier si la ligne est ou non le résultat d’une commande ROLLUP ou 
CUBE. 

PERCENTILE_CONT (expr) 

Distribution inverse continue. 

PERCENTILE_DISC (expr) 

Distribution inverse discrète. 

PERCENT_RANK (expr) 

Similaire à CUME_DIST. 

RANK (expr) 

Calcule le rang d’une valeur dans un groupe de valeurs. 

REGR_(expr) 

Calcul de la régression linéaire. 

STDDEV_POP (expr) 

Écart­type d’une population. 

STDDEV_SAMP (expr) 

- 4- © ENI Editions - All rigths reserved


Écart­type d’un échantillon. 

VAR_POP (expr) 

Variance d’une population. 

VAR_SAMP (expr) 

Variance d’un échantillon. 

Dans le cas où le calcul d’agrégats porte sur une colonne particulière, les valeurs NULL de cette colonne ne 
sont pas prises en compte pour les calculs. 

Oracle  dispose  de  quelques  autres  fonctions  de  calculs  d’agrégats  qui  sont  spécialisées  dans  le  calcul 
statistique. 

Exemples 

Nombre de clients par ville. L’attribut ville ayant été défini de type CHAR(30), il faut éliminer les éventuels espaces à droite 
pour que le regroupement se fasse bien sur les caractères significatifs de la valeur de la colonne. 

SQL> select rtrim(VILLE), count(*) from CLIENTS group by rtrim(VILLE);

RTRIM(VILLE) COUNT(*)
--------------------------------------------
LE MANS 1
NANTES 3
PARIS 1
TOURS 1

SQL>

Prix le plus élevé et moyenne des quantités en stock par famille d’articles (deux premiers caractères de la référence) : 

SQL> select * from articles;

REFA DESIGNATION PRIX CODETVA CATEGORIE QTESTK


--- ---------------------------- -------- ------- ---------- ----------
AB22 Taps Persan 1375,11 2 IMPORT 5
CD50 Chaine HiFi 2 IMPORT 7
CD21 Platine laser 500 2 IMPORT 20
ZZZZ Article bidon DIVERS 25
AA00 Cadeau 0 DIVERS 8
AB03 Carpette 165 2 SOLDES 116
AB Tapis 2 DIVERS 2
ZZ01 Lot de tapis 500 2 DIVERS 0
AB10 Tapis de chine 1650 2 IMPORT 10

9 ligne(s) sélectionnée(s).

SQL> select substr(refart,1,2), max(prix), avg(qtestk)


2 from articles
3 group by substr(refart,1,2);

SU MAX(PRIX) AVG(QTESTK)
-- ---------- -----------
AA 8
AB 1650 33,25
CD 500 13,5
ZZ 500 12,5

SQL>

f. Fonctions analytiques 

© ENI Editions - All rigths reserved - 5-


Les fonctions analytiques permettent d’extraire des résultats à partir d’un regroupement de lignes effectué à l’aide 
de l’instruction GROUP BY. Ces fonctions se différencient des fonctions d’agrégat car au lieu de retourner une seule 
valeur pour chaque groupe de valeurs, elles retournent plusieurs lignes de résultats pour chaque groupe. Ces lignes 
de résultat sont appelées fenêtres (windows). Pour chaque ligne analysée une fenêtre glissante est définie. La taille 
de la fenêtre détermine le nombre de lignes à prendre en compte pour le calcul de la ligne actuelle. 

AVG 

Moyenne. 

CORR 

Cœ fficient de corrélation. 

COVAR_POP 

Covariance d’une population. 

COVAR_SAMP 

Covariance d’un échantillon. 

COUNT 

Comptage. 

CUME_DIST 

Distribution cumulative. 

DENSE_RANK 

Calcule le rang d’une ligne dans un groupe ordonné de lignes. 

FIRST 

Permet d’obtenir la première ligne depuis un jeu de résultats trié. 

LAST 

Permet d’obtenir la dernière ligne depuis un jeu de résultats trié. 

FIRST_VALUE 

Première valeur d’un ensemble de résultats triés. 

LAST_VALUE 

Dernière valeur d’un ensemble de résultats triés. 

LAG 

Permet d’accéder à plus d’une ligne de façon simultanée. 

LEAD 

Fonction similaire à LAG. 

MAX 

Plus grand élément. 

MIN 

- 6- © ENI Editions - All rigths reserved


Plus petit élément. 

NTILE 

Permet de diviser une ligne de résultat en petits groupes parfaitement identifiés par leur numéro d’ordre. 

PERCENT_RANK 

Distribution cumulative. 

PERCENTILE_CONT 

Distribution inverse continue. 

PERCENTILE_DISC 

Distribution inverse discrète. 

RANK 

Rang d’une valeur au sein d’un groupe. 

RATIO_TO_REPORT 

Calcule le rapport entre une valeur et la somme d’un ensemble de valeurs. 

REGR 

Régression linéaire. 

ROW_NUMBER 

Permet de générer un numéro unique pour chaque ligne. 

STDDEV 

Ecart­type. 

STDDEV_POP 

Ecart­type sur une population. 

STDDEV_SAMP 

Ecart­type sur un échantillon. 

SUM 

Somme. 

VAR_POP 

Variance d’une population. 

VAR_SAMP 

Variance d’un échantillon. 

VARIANCE 

Variance. 

Dans l’exemple ci­après, la requête permet de lister tous les articles dont la référence commence par AB et d’afficher en 
face de chacun d’eux la référence de l’article le moins cher. 

© ENI Editions - All rigths reserved - 7-


SQL> select refart, prix,
2 FIRST_VALUE(refart)
3 OVER(order by prix asc rows unbounded preceding) as moins_cher
4 from articles
5 where upper(substr(refart,1,2))=’AB’;

REFA PRIX MOIN


---- ---------- ----
AB03 150 AB03
AB22 1250,1 AB03
AB10 1500 AB03
AB AB03

SQL>

g. Restrictions sur agrégat 

Lorsque l’on souhaite restreindre le nombre de lignes renvoyées par une requête comportant un calcul d’agrégats, il 
est possible d’utiliser la clause HAVING. La syntaxe est alors : 

SELECT liste de colonnes, fonctions groupe FROM S GROUP


BY liste de colonnes HAVING condition ;

La condition peut alors contenir une fonction statistique. Les expressions utilisées dans la clause HAVING peuvent 
faire référence à des critères de regroupement ou des calculs d’agrégats. 
Exemple 

Affichage des informations statistiques des familles d’articles dont le prix minimum est supérieur à 300 euros. 

SQL> select substr(REFART, 1, 2), max(PRIX), min(PRIX)


2 from ARTICLES group by substr(REFART, 1, 2)
3 having min(PRIX) > 300;

SU MAX(PRIX) MIN(PRIX)
-- --------- ---------
CD 735,4 735,4
ZZ 500 500

SQL>

h. Produit cartésien 

Le produit cartésien permet d’obtenir l’association de chaque ligne d’une table avec chaque ligne d’autres tables. 

L’opération S X T se traduit par : 

SELECT liste de colonnes FROM S, T ;

Si des colonnes portent le même nom dans les deux tables, on préfixe le nom de la colonne par le nom de la table. 

Le nom complet de la colonne est alors : nomtable.nomcolonne. 

Exemple 

Création et valorisation d’une table DEPOTS. Simulation de l’affectation de chaque article à chaque dépôt : 

SQL>create table DEPOTS (CODE char(2) primary key, ADRESSE


varchar2(60));
Table créée.
SQL>insert into DEPOTS values (’NA’, ’24 rue Crébillon 44000 NANTES’);
1 ligne créée.
SQL>insert into DEPOTS values (’PA’, ’PARIS’);
1 ligne créée.
SQL>insert into DEPOTS values (’BO’ , ’BORDEAUX’);
1 ligne créée.

- 8- © ENI Editions - All rigths reserved


SQL>commit;
Validation effectuée.
SQL>select CODE,REFART from DEPOTS,ARTICLES;
CO REFART
----------------
NA AB03
PA AB03
BO AB03
NA AB10
PA AB10
BO AB10
NA AB22
PA AB22
BO AB22
NA CD50
PA CD50
BO CD50
NA ZZZZ
PA ZZZZ
BO ZZZZ
NA AA00
PA AA00
BO AA00
NA AB
PA AB
BO AB
NA ZZ01
PA ZZ01
BO ZZ01
24 ligne(s) sélectionnée(s).

i. Jointures 

La  jointure  est  une  restriction  sur  le  produit  cartésien  afin  de  lier  chaque  ligne  d’une  table  avec  des  lignes  d’une 
autre table en respectant une condition. 
L’opération S JOIN (cond) T se traduit par : 

SELECT liste de colonnes FROM S, T WHERE cond ;

Exemple 
Jointure naturelle entre COMMANDES et CLIENTS : 

SQL> select NOCDE, COMMANDES.NOCLI, NOMCLI


2 from CLIENTS, COMMANDES
3 WHERE CLIENTS.NOCLI = COMMANDES.NOCLI ;

NOCDE NOCLI NOMCLI


--------- --------- ------------------------------
1301 15 DUPONT S.A.
1210 15 DUPONT S.A.
1250 35 DUBOIS Jean
1230 35 DUBOIS Jean

SQL>

Depuis la version 9i, Oracle supporte les jointures exprimées dans une syntaxe compatible avec la norme ANSI. Bien 
que cette façon d’écrire soit normalisée, elle est souvent moins utilisée que la syntaxe présentée précédemment car 
les informations sont moins lisibles. Néanmoins les générateurs de requêtes utilisent cette syntaxe normalisée. 

SELECT liste de colonnes


FROM table [NATURAL] INNER JOIN table ON
{condition_jointure|USING (colonne)}
WHERE conditions;

SQL> select nocde, commandes.nocli, nomcli


2 from clients inner join commandes on

© ENI Editions - All rigths reserved - 9-


3 clients.nocli=commandes.nocli;

NOCDE NOCLI NOMCLI


---------- ---------- ------------------------------
100 15 DUPONT S.A.
1301 15 DUPONT S.A.
1210 15 DUPONT S.A.
1250 35 DUBOIS Jean
1230 35 DUBOIS Jean

SQL>

L’avantage de la syntaxe normalisée est par contre très net lors de la mise en place des jointures naturelles entre 
les tables, car il n’est alors plus nécessaire de citer la condition de jointure. 

SQL> select nocde, nocli, nomcli


2 from clients natural inner join commandes;

NOCDE NOCLI NOMCLI


---------- ---------- ------------------------------
100 15 DUPONT S.A.
1301 15 DUPONT S.A.
1210 15 DUPONT S.A.
1250 35 DUBOIS Jean
1230 35 DUBOIS Jean

SQL>

j. Jointures externes 

La jointure externe (outer join) est une extension de la jointure, qui permet d’obtenir en plus des lignes répondant à 
la condition, les lignes de l’une des tables qui n’y répondent pas. Il suffit d’ajouter l’opérateur (+) dans la condition, 
derrière la colonne de la table dont les lignes peuvent ne pas apparaître dans le résultat. 
Exemple 
Liste des clients avec éventuellement leurs commandes. 

SQL> select NOCDE, COMMANDES.NOCLI, NOMCLI


2 from CLIENTS, COMMANDES
3 WHERE CLIENTS.NOCLI = COMMANDES.NOCLI (+) ;
NOCDE NOCLI NOMCLI
--------- --------- ------------------------------
1301 15 DUPONT S.A.
1210 15 DUPONT S.A.
Etb LABICHE
1250 35 DUBOIS Jean
1230 35 DUBOIS Jean
BERNARD S.A.
DUBOIS Jean
LAROCHE

8 ligne(s) sélectionnée(s).

SQL>

k. Union, intersection, différence 

Ces opérateurs permettent d’obtenir dans une requête des lignes provenant de requêtes distinctes mais de même 
forme (même nombre de colonnes, même type dans le même ordre). 

Les opérations S {∪/∩/­} T se traduisent par : 

SELECT liste colonnes FROM S {UNION/UNION ALL /INTERSECT/


MINUS} SELECT liste colonnes FROM T ;

L’opérateur UNION ALL permet de retrouver toutes les lignes issues des requêtes sans élimination des doublons. 

- 10 - © ENI Editions - All rigths reserved


Il est possible de faire l’union, l’intersection ou la différence entre des données issues de plusieurs requêtes 
SELECT,  mais  toutes  les  requêtes  doivent  posséder  la  même  liste  de  colonnes  (type  et  longueur)  et  ces 
colonnes doivent toujours être définies dans le même ordre. 

Exemple 

Regroupements des lignes de CLIENTS et CLIDIVERS : 

SQL> select NOCLI, NOMCLI from CLIENTS


2 UNION
3 select NOCLI, NOMCLI from CLIDIVERS ;

NOCLI NOMCLI
--------- ------------------------------
15 DUPONT S.A.
20 Etb LABICHE
35 DUBOIS Jean
36 BERNARD S.A.
123 DUPOND and Co
138 DUBOIS Jean
152 LAROCHE
556 DUBOIS Jean
567 OEYSTER Ltd

9 ligne(s) sélectionnée(s).

SQL> select NOMCLI from CLIENTS


2 UNION
3 select NOMCLI from CLIDIVERS ;

NOMCLI
------------------------------
BERNARD S.A.
DUBOIS Jean
DUPOND and Co
DUPONT S.A.
Etb LABICHE
LAROCHE
OEYSTER Ltd

7 ligne(s) sélectionnée(s).

SQL>

2. Traitement du résultat 

Le résultat des requêtes précédentes peut servir à plusieurs usages : 

● affichage trié ou non, 

● valorisation d’une table intermédiaire, 

● création d’un fichier externe à la base. 

a. Le tri 

Pour obtenir un résultat trié, on utilise la clause ORDER BY en fin de commande SELECT. 
Par  défaut,  le  tri  est  croissant  et  l’ordre  est  déterminé  par  les  paramètres  nationaux  de  l’environnement  de 
l’utilisateur (paramètre NLS_SORT). Le tri décroissant est obtenu à l’aide de l’option DESC de la clause ORDER BY. Il 
est possible pour l’utilisateur, s’il en possède le privilège, de modifier le paramètre NLS_SORT en cours de session. 

L’ordre de tri peut également être spécifié en indiquant dans la clause ORDER BY le numéro d’ordre correspondant 
dans la clause SELECT à la colonne servant au tri. 

© ENI Editions - All rigths reserved - 11 -


Syntaxe 

SELECT ..... ORDER BY exp [Desc][, ...] ;

Exemple 

Affichage des articles triés par famille et prix décroissant. 

SQL> select REFART, PRIX from ARTICLES


2 ORDER BY substr(REFART, 1, 2), PRIX desc ;

REFA PRIX
---- ---------------
0 0
AB
AB10 1500
AB22 1250,1
AB03 150
CD50 735,4
ZZZZ
ZZ01 500

8 ligne(s) sélectionnée(s).

SQL> select PRIX, substr(REFART, 1, 2) from ARTICLES


2 ORDER BY 2, 1 desc ;

PRIX SU
--------- --
0 AA
AB
1500 AB
1250,1 AB
150 AB
735,4 CD
ZZ
500 ZZ

8 ligne(s) sélectionnée(s).
SQL>

b. La sauvegarde 

Par SQL

Il  est  possible  de  sauvegarder  le  résultat  d’une  requête  dans  une  table,  afin  de  pouvoir  l’utiliser  dans  une  autre 
requête. 
Deux méthodes sont utilisables : 

● créer la table puis y insérer des lignes résultant de la requête, 

● créer la table à partir de la requête. 

Première méthode

Syntaxes 

CREATE TABLE nom (colonne type [DEFAULT expr]


[contrainte], ...) ;

INSERT INTO nom [(colonne, colonne,...)] SELECT ...;

Cette méthode permet de choisir les types de colonnes, les valeurs par défaut, et de mettre en place des contrôles 
en utilisant les contraintes. 

- 12 - © ENI Editions - All rigths reserved


Exemple 
Création d’une table simplifiée à partir de la table CLIENTS : 

SQL> create table CLI (NOCLI char(4), NOMCLI char(10));

Table créée.

SQL>
SQL> insert into CLI
2 select to_char(NOCLI, ’009’), substr(NOMCLI, 1, 10)
3 from CLIENTS where VILLE like ’PARIS%’;

1 ligne créée.

SQL> select * from CLI;

NOCL NOMCLI
---- ----------
036 BERNARD S.

SQL> drop table CLI ;

Table supprimée.

SQL>

Deuxième méthode

Syntaxe 

CREATE TABLE nom [(colonne, colonne, ....)] AS SELECT ...;

Par  cette  méthode  plus  rapide,  les  noms  et  les  types  des  colonnes  de  la  nouvelle  table  sont  dérivés  de  ceux  des 
colonnes projetées dans le SELECT. 
Exemple 

Sauvegarde de la restriction "Clients de Loire­Atlantique" dans une table CLI44 : 

SQL> create table CLI44 as


2 select NOCLI, NOMCLI from CLIENTS
3 where CODE_POSTAL between 44000 and 44999 ;

Table créée.

SQL> select * from CLI44;

NOCLI NOMCLI
--------- ------------------------------
15 DUPONT S.A.
20 Etb LABICHE
35 DUBOIS Jean
SQL> desc CLI44
Name Null? Type
------------------------- -------- --------------
NOCLI NUMBER(4)
NOMCLI NOT NULL VARCHAR2(30)

SQL> drop table CLI44 ;


Table supprimée.

SQL>

Par SQLPLUS

Sauvegarde du résultat de la requête dans un fichier ASCII. 

Syntaxe 

© ENI Editions - All rigths reserved - 13 -


SPOOL nom_fichier

Exemple 
Création d’un fichier séquentiel ASCII fic.lst contenant les données de la table CLIENTS. 

SQL>SET HEADING OFF


SQL>SPOOL fic
SQL>select * from CLIENTS;
SQL>SPOOL OFF

Les tables temporaires

En  plus  des  tables  permanentes,  Oracle  offre  la  possibilité  de  créer  des  tables  temporaires  pour  stocker  des 
informations le temps d’une session ou d’une transaction. Les données stockées dans une table temporaire créée 
avec  l’ordre  CREATE  GLOBAL  TEMPORARY  TABLE,  sont  accessibles  uniquement  depuis  la  session  qui  a  créé  les 
données. En fait chaque session ne voit que ses propres données et une instruction TRUNCATE TABLE sur une table 
temporaire permet simplement de supprimer toutes les données issues de la session qui lance l’ordre TRUNCATE. 

La  spécificité  de  cette  table  temporaire  réside  dans  le  fait  que  les  données  insérées  dans  cette  table  ne  restent 
présentes que le temps de la transaction. La table, quant à elle, reste bien sûr en place et il est possible de l’utiliser 
dans les autres transactions. Si l’on souhaite que les données insérées dans cette table soit stockées de façon plus 
persistante, il faut utiliser la clause ON COMMIT PRESERVE ROWS lors de la création de la table temporaire globale. 
Ainsi, les informations insérées dans cette table seront visibles à travers toutes les transactions pendant la durée de 
la session de l’utilisateur Oracle qui a inséré les informations dans la table. 
Syntaxe 

CREATE GLOBAL TEMPORARY TABLE table (nom_colonne type,...)


[ON COMMIT PRESERVE ROWS];

Exemple 
Création d’une table temporaire globale destinée à recevoir les numéro et nom de certains clients. 

Des  données  sont  ajoutées  à  la  table  temporaire.  Ces  données  sont  le  résultat  d’une  commande  de  type  SELECT,  qui 
permet de connaître le numéro et le nom des clients de chaque commande. 

Depuis la même session, on interroge la table temporaire pour connaître son contenu : 

Depuis une autre session, on interroge la même table temporaire pour connaître son contenu : 

- 14 - © ENI Editions - All rigths reserved


 

La création de la même table avec l’option ON COMMIT PRESERVE ROWS : 

c. Énumérer toutes les possibilités d’un calcul d’agrégats 

Un  calcul  d’agrégats  porte  toujours  sur  le  regroupement  indiqué  par  la  clause  GROUP  BY.  Il  est  parfois  nécessaire 
d’effectuer  un  regroupement  plus  large  afin  de  connaître  d’autres  valeurs.  Par  exemple,  on  souhaite  connaître  le 
montant de chaque commande et le montant de toutes les commandes passées par un client. Pour mener à bien ces 
calculs en une seule étape, il faut utiliser les mots clés ROLLUP et CUBE. 

ROLLUP 

Permet de faire des regroupements de plus en plus généraux. 

CUBE 

Permet de réaliser le calcul demandé sur tous les regroupements possibles. 

Syntaxe 

SELECT liste_colonne, calcul_agregat FROM table GROUP BY


{ROLLUP|CUBE} (liste_colonne)

Le fonctionnement de ces deux mots clés va être expliqué au travers des exemples suivants. 

Exemple 
Dans  l’exemple  ci­dessous,  ROLLUP  permet  de  calculer  le  total  pour  chaque  client  ainsi  que  le  montant  total  des 
commandes tous clients confondus : 

© ENI Editions - All rigths reserved - 15 -


 
 
En utilisant l’expression DECODE, il est possible d’obtenir une présentation plus soignée.

L’instruction CUBE permet quant à elle d’explorer toutes les combinaisons possibles. 

3. MERGE 

Cette instruction permet de fusionner, en une seule requête, une opération de mise à jour (INSERT, UPDATE, DELETE) 
sur une table. 
Les informations, qui servent de base à l’exécution de l’ordre DML, peuvent provenir d’une ou de plusieurs tables. 

Toutefois,  la  même  ligne  d’informations  ne  peut  pas  participer  en  tant  que  source  et  destination  de  l’instruction 
MERGE. 

- 16 - © ENI Editions - All rigths reserved


Cette  fonction  s’avère  très  intéressante  lorsque  l’on  souhaite  mettre  à  jour  les  données  d’une  table  de  façon 
conditionnelle. Par exemple dans la table des employés, on souhaite mettre à jour le salaire (+4%) des employés de 
plus de 40 ans et supprimer ceux de plus de 65 ans (retraite). 
Le contenu de la table employé est le suivant : 

Comme une ligne ne peut pas être à la fois source et destination de la commande MERGE, la première étape va consister à 
créer une table temporaire qui va contenir les numéros d’employés et leur âge. 

Enfin les données de la table des employés sont mises à jour. 

Le nouveau contenu de la table des employés est alors : 

L’utilisation  de  cette  instruction  permet  d’éviter  l’exécution  de  nombreuses  requêtes  telles  que  INSERT,  UPDATE  ou 
bien DELETE. 
 
Il n’est pas possible de mettre plusieurs fois à jour une ligne au cours d’une seule instruction MERGE.

Syntaxe 

MERGE INTO nomTable USING source


ON ( condition )
[WHEN MATCHED THEN UPDATE SET nomColonne=valeur
[WHERE condition] [DELETE WHERE condition] ]
[WHEN NOT MATCHED THEN INSERT (nomColonne, ...)

© ENI Editions - All rigths reserved - 17 -


values (valeur, ...) [WHERE condition]];

INTO 

Permet de spécifier la table cible de l’instruction MERGE et donc des opérations INSERT, UPDATE et DELETE. 

USING 

Permet  de  spécifier  la  façon  dont  les  données  qui  participent  à  cette  instruction  sont  sélectionnées  ;  il  s’agit  d’une 
requête de type SELECT ou d’un nom de table ou de vue. 

ON 

Permet de faire une jointure entre les informations déjà présentes dans la table cible et celles issues de la source. En 
fonction  de  cette  jointure,  l’action  sera  soit  une  mise  à  jour  (WHEN  MATCHED)  ou  bien  une  insertion  (WHEN  NOT 
MATCHED). 

WHEN MATCHED 

Permet de définir l’action de mise à jour à effectuer ou bien éventuellement de suppression. 

WHEN NOT MATCHED 

Permet de définir une insertion à réaliser sur la table cible. 

- 18 - © ENI Editions - All rigths reserved


SQL avancé 
Le SQL permet l’utilisation d’autres objets que les tables et les index, afin de gérer les données ou de manipuler des 
requêtes. 
La puissance de l’instruction SELECT permet d’autre part, de combiner les différentes clauses en une seule commande, 
et également d’imbriquer les requêtes. 
Enfin, le SQL permet dans un environnement multi­utilisateur, de verrouiller les tables afin de préserver l’intégrité des 
données. 

1. Les objets 

a. Les objets View (vue) 

Les vues sont des tables virtuelles présentant le résultat d’un SELECT. 
L’un des intérêts de l’utilisation des vues vient du fait que la vue ne stocke pas les données, mais fait référence à 
une ou plusieurs tables d’origine à travers une requête SELECT, requête qui est exécutée chaque fois que la vue est 
référencée. De ce fait, toute modification de données dans les tables d’origine est immédiatement visible dans la vue 
dès que celle­ci est à nouveau exécutée. 

Les cas d’utilisation des vues sont multiples : 

● Cacher  aux  utilisateurs  certaines  colonnes  ou  certaines  lignes  en  mettant  à  leur  disposition  des  vues  de 
projection ou de restriction. Ceci permet de fournir un niveau de sécurité supplémentaire. 

● Simplifier  l’utilisation  de  tables  comportant  beaucoup  de  colonnes,  beaucoup  de  lignes,  ou  des  noms 
complexes, en créant des vues avec des structures plus simples et des noms plus explicites. 

● "Sauvegarder" des requêtes fréquemment utilisées sous un nom. 

● Simplifier la saisie des instructions SQL pour les utilisateurs en masquant les jointures fréquemment utilisées. 

Les  vues,  une  fois  créées,  sont  utilisables  comme  des  tables  dans  les  instructions  DML,  INSERT,  SELECT,  UPDATE, 
DELETE. Toutefois les mises à jour ne sont pas possibles si la vue comporte : 

● des instructions ensemblistes (UNION, INTERSECT, MINUS), 

● des fonctions de groupe, 

● des clauses GROUP BY, CONNECT BY, START WITH. 

Une  vue  définie  par  une  jointure  supporte  les  instructions  INSERT,  UPDATE,  DELETE  si  elle  référence  dans  sa 
définition une table dont la (les) colonne(s) clé primaire apparaît (apparaissent) dans la liste des colonnes projetées 
de la jointure et si les instructions INSERT, UPDATE, DELETE portent sur cette table. 

Création

Syntaxe 

CREATE [OR REPLACE] [FORCE | NO FORCE] VIEW nom


[(colonnes, .....)] AS SELECT ..... [WITH CHECK OPTION |
WITH READ ONLY];

OR REPLACE 

Permet le remplacement de la description par la nouvelle requête si la vue existe déjà. En effet, la définition d’une 
vue ne peut être modifiée partiellement. 

FORCE | NO FORCE 

© ENI Editions - All rigths reserved - 1-


Permet de forcer/d’empêcher la création de la vue si un des éléments sous­jacents (table ou vue) n’est pas défini. 

READ ONLY 

Interdit toute insertion, modification, suppression de données à travers la vue. 

WITH CHECK OPTION 

Vérifie,  lors  de  l’insertion  ou  de  la  modification  de  lignes  dans  la  vue,  que  les  lignes  insérées  ou  modifiées  sont 
visualisables dans cette vue. 

Compilation

Syntaxe 

ALTER VIEW nom COMPILE ;

La compilation de la vue permet de valider la requête qui lui est associée et de détecter au plus tôt d’éventuelles 
références incorrectes dans celle­ci. Ceci est en particulier utile après modification de la structure d’une  des  tables 
sous­jacentes  de  la  vue.  Si  la  compilation  de  la  vue  provoque  une  erreur,  tous  les  autres  objets  de  la  base 
dépendant de cette vue deviennent invalides. 
Exemple 
Vue  retournant  les  clients  du  département  44.  L’option  WITH  CHECK  OPTION  empêche  toute  insertion  de  client 
n’appartenant pas à ce département. 

SQL> create or replace view V_CLI44 as


2 select NOCLI, NOMCLI, CODE_POSTAL, VILLE from CLIENTS
3 where CODE_POSTAL between 44000 and 44999
4 with check option;

Vue créée.
SQL> select NOCLI, substr(NOMCLI,1,12), CODE_POSTAL,
2 substr(VILLE,1,12) from V_CLI44;

NOCLI SUBSTR(NOMCL CODE_POSTAL SUBSTR(VILLE


----- ------------ ----------- -------------
15 DUPONT S.A. 44000 NANTES
20 Etb LABICHE 44100 NANTES
35 DUBOIS Jean 44300 NANTES

SQL> insert into V_CLI44 values


(255, ’ALAMBERT S.A.’, 22000, ’ST BRIEUC’) ;
insert into V_CLI44 values (255, ’ALAMBERT S.A.’, 22000,
’ST BRIEUC’)
*
ERREUR à la ligne 1:
ORA-01402: vue WITH CHECK OPTION - violation de clause WHERE

SQL> insert into V_CLI44 values (176, ’Ets GAZONAV’, 44500,


’ST NAZAIRE’) ;

1 ligne créée.

SQL> select NOCLI, substr(NOMCLI,1,12), CODE_POSTAL,


2 substr(VILLE,1,12) from V_CLI44;

NOCLI SUBSTR(NOMCL CODE_POSTAL SUBSTR(VILLE


------ ----------- ----------- ------------
15 DUPONT S.A. 44000 NANTES
20 Etb LABICHE 44100 NANTES
35 DUBOIS Jean 44300 NANTES
176 Ets GAZONAV 44500 ST NAZAIRE

SQL> select NOCLI, substr(NOMCLI,1,12), CODE_POSTAL,


2 substr(VILLE,1,12) from CLIENTS;

NOCLI SUBSTR(NOMCL CODE_POSTAL SUBSTR(VILLE

- 2- © ENI Editions - All rigths reserved


----- ------------ ----------- ------------
15 DUPONT S.A. 44000 NANTES
20 Etb LABICHE 44100 NANTES
35 DUBOIS Jean 44300 NANTES
36 BERNARD S.A. PARIS
138 DUBOIS Jean TOURS
152 LAROCHE LE MANS
176 Ets GAZONAV 44500 ST NAZAIRE

7 ligne(s) sélectionnée(s).

SQL>

La vue V_CLICMD sauvegarde la jointure CLIENTS/ COMMANDES. La vue V_CLICMD44 permet de faire une restriction sur 
les clients du département 44. La vue V_CLICMD est ensuite rendue invalide suite à la suppression d’une table référencée 
dans sa clause SELECT. La vue V_CLICMD44 est automatiquement invalidée. 

SQL> create or replace view V_CLICMD (NOCLIENT, NOM, COMMANDE,


2 CP) as select CLIENTS.NOCLI, NOMCLI, NOCDE,
3 CODE_POSTAL from CLIENTS, COMMANDES
4 where CLIENTS.NOCLI = COMMANDES.NOCLI ;

Vue créée.

SQL> select * from V_CLICMD order by NOCLIENT ;

NOCLIENT NOM COMMANDE CP


---------- ----------------------- ---------- ---------
15 DUPONT S.A. 1301 44000
15 DUPONT S.A. 1210 44000
35 DUBOIS Jean 1250 44300
35 DUBOIS Jean 1230 44300

SQL> create or replace view V_CLICMD44 as


2 select * from V_CLICMD
3 where CP between 44000 and 44999 ;

Vue créée.

SQL> select * from V_CLICMD44 order by NOCLIENT;

NOCLIENT NOM COMMANDE CP


--------- ----------------------- -------- -----------
15 DUPONT S.A. 1301 44000
15 DUPONT S.A. 1210 44000
35 DUBOIS Jean 1250 44300
35 DUBOIS Jean 1230 44300

SQL> drop table COMMANDES cascade constraints ;

Table supprimée.

SQL> alter view V_CLICMD compile ;

Attention: Vue modifiée avec erreurs de compilation.

SQL> select * from V_CLICMD44 order by NOCLIENT ;


select * from V_CLICMD44 order by NOCLIENT
*
ERREUR à la ligne 1:
ORA-04063: view "GILLES.V_CLICMD44" a des erreurs

SQL>

Insertion dans une vue basée sur une jointure. 

SQL> create or replace view V_CMDCLI (NOCDE, DATECDE, NOCLIENT,


2 NOMCLI) as select NOCDE, DATECDE, COMMANDES.NOCLI,
3 NOMCLI from CLIENTS, COMMANDES
4 where CLIENTS.NOCLI = COMMANDES.NOCLI ;

© ENI Editions - All rigths reserved - 3-


Vue créée.
SQL> select * from V_CMDCLI order by NOCLIENT ;

aucune ligne sélectionnée

SQL> insert into V_CMDCLI (NOCDE, DATECDE, NOCLIENT)


2 values (1501, SYSDATE, 176 );

1 ligne créée.

SQL> select * from V_CMDCLI order by NOCLIENT ;

NOCDE DATECDE NOCLIENT NOMCLI


--------- -------- --------- --------------
1501 20/11/98 176 Ets GAZONAV

SQL>

Suppression

Syntaxe 

DROP VIEW nom ;

Les objets qui référencent la vue supprimée deviennent invalides. 

Les vues en ligne

Il est possible de définir une vue directement à l’intérieur d’une requête sans qu’il soit nécessaire de passer par une 
commande  CREATE  VIEW.  Cette  possibilité  est  intéressante  car  elle  permet  de  définir  simplement  une  vue  dont 
l’utilisation est limitée. 
Exemple 
La vue définie en ligne permet de connaître le montant de chaque commande. Elle est référencée dans la requête par l’alias 
de table LCDE. La requête affiche les informations relatives à chaque client. 

b. Les objets Schema 

Un schéma est un ensemble de tables, vues et privilèges regroupés sous un même nom (celui de l’utilisateur). 

L’utilisation explicite d’un schéma avec l’instruction CREATE SCHEMA AUTHORIZATION permet d’étendre la notion de 
transaction aux instructions DDL de création de table, de vue et d’affectation de privilège GRANT. 

Si l’une des instructions DDL spécifiées dans le CREATE SCHEMA AUTHORIZATION échoue, l’ensemble des instructions 
est annulé. 
Le nom de SCHEMA utilisé dans l’instruction est celui associé à l’utilisateur (USER) qui a ouvert la session en cours. 

Syntaxe 

- 4- © ENI Editions - All rigths reserved


CREATE SCHEMA AUTHORIZATION nom
{CREATE {TABLE/VIEW}..../GRANT... }...;

Exemple 

Instruction  CREATE  SCHEMA  AUTHORIZATION  exécutée  sans  erreur.  Toutes  les  instructions  DDL  spécifiées  ont  été 
exécutées. 

SQL> drop view v_cdecli;

Vue supprimée.

SQL> drop table ligcdes;

Table supprimée.

SQL> drop table commandes;

Table supprimée.

SQL> drop table clients;

Table supprimée.

SQL> drop table articles;

Table supprimée.

SQL> create schema authorization LIVRE


2 create table clients(
3 nocli number(4)
4 constraint pk_clients primary key
5 constraint ck_clients_nocli check (nocli>0),
6 nomcli varchar2(30)
7 constraint nn_clients_nomcli not null,
8 adrcli varchar2(80),
9 code_postal number(5)
10 constraint ck_clients_codepostal check(code_postal between 1000 and
95999),
11 ville char(30)
12 )
13 create table articles(
14 refart char(4) primary key,
15 designation varchar2(30),
16 prix number(8,2),
17 codetva number(1),
18 categorie char(10),
19 qtestk number(5)
20 )
21 create table commandes(
22 nocde number(9),
23 nocli number(4),
24 datecde date,
25 etatcde char(2),
26 constraint pk_commandes primary key (nocde),
27 constraint fk_commandes_clients foreign key(nocli) references
clients(nocli),
28 constraint ck_commandes_etat check (etatcde in (’EC’,’LI’, ’SO’))
29 )
30 create table ligcdes(
31 nocde number(6)
32 constraint fk_ligcdes_commandes references commandes(nocde),
33 nolig number(2)
34 constraint ck_ligcdes_nolig check (nolig>0),
35 refart char(4)
36 constraint fk_ligcdes_articles references articles(refart),
37 qtecde number(5),
38 constraint pk_ligcdes primary key(nocde,nolig)
39 )
40 create view v_cdecli (nocde, datecde, noclient, nomcli) as

© ENI Editions - All rigths reserved - 5-


41 select nocde, datecde, commandes.nocli, nomcli
42 from commandes, clients
43 where commandes.nocli=clients.nocli
44 grant select on articles to public
45 ;

Schéma créé.

SQL> desc commandes


Nom NULL ? Type
----------------------------------------- -------- -------------------
NOCDE NOT NULL NUMBER(9)
NOCLI NUMBER(4)
DATECDE DATE
ETATCDE CHAR(2)

SQL> desc clients


Nom NULL ? Type
----------------------------------------- -------- -------------------
NOCLI NOT NULL NUMBER(4)
NOMCLI NOT NULL VARCHAR2(30)
ADRCLI VARCHAR2(80)
CODE_POSTAL NUMBER(5)
VILLE CHAR(30)

SQL> desc articles


Nom NULL ? Type
----------------------------------------- -------- -------------------
REFART NOT NULL CHAR(4)
DESIGNATION VARCHAR2(30)
PRIX NUMBER(8,2)
CODETVA NUMBER(1)
CATEGORIE CHAR(10)
QTESTK NUMBER(5)

SQL> desc ligcdes


Nom NULL ? Type
----------------------------------------- -------- -------------------
NOCDE NOT NULL NUMBER(6)
NOLIG NOT NULL NUMBER(2)
REFART CHAR(4)
QTECDE NUMBER(5)

SQL>

Une  des  instructions  DDL  spécifiées  (CREATE  VIEW)  contient  une  erreur  (nom  de  colonne  incorrect  ligne  18)  et  n’a  pu 
aboutir. L’autre instruction (CREATE TABLE) spécifiée dans le CREATE SCHEMA AUTHORIZATION a été annulée. 

SQL> drop table LIGCDES ;

Table supprimée.

SQL> drop view V_CLICDELIG ;

Vue supprimée.

SQL> create schema authorization GILLES


2 create table LIGCDES (
3 NOCDE number(6)
4 constraint LIGCDES_NOCDE_RF
5 references COMMANDES(NOCDE),
6 NOLIG number(2)
7 constraint LIGCDES_NOLIG_CK check(NOLIG 0),
8 REFART char(4)
9 constraint LIGCDES_refart_RF
10 references ARTICLES(REFART),
11 QTECDE number(5),
12 constraint LIGCDES_PK primary key (NOCDE, NOLIG))
13 create view V_CLICDELIG (NOCLIENT, NOMCLI, NOCDE, DATECDE,
14 NOLIG, REFART, QTECDE) as

- 6- © ENI Editions - All rigths reserved


15 select NOCLIENT, NOMCLI, LIGCDES.NOCDE, DATECDE, NOLIG,
16 REFART, QTECDE
17 from V_CDECLI, LIGCDES
18 where V_CDECLI.NOCDE = LIGCDES.NOCD ;
create schema authorization GILLES
*
ERREUR à la ligne 1:
ORA-02427: Echec de création de vue

SQL>
SQL> select * from LIGCDES ;
select * from LIGCDES
*
ERREUR à la ligne 1:
ORA-00942: Table ou vue inexistante

SQL>

c. Les objets Synonym 

Un synonyme est le nom alternatif donné à un objet TABLE, VIEW, SEQUENCE, SNAPSHOT, PROCEDURE, FUNCTION 
ou PACKAGE. 
Les synonymes apportent plus de souplesse dans la gestion des noms d’objets : 

● mise à disposition d’objets pour tous les utilisateurs sous le même nom, 

● masquage du nom du SCHEMA auquel appartient l’objet, 

● possibilité de référencer plusieurs fois un objet dans une requête, 

● simplification dans l’écriture des requêtes. 

Création

Syntaxe 

CREATE [PUBLIC] SYNONYM nom FOR objet ;

PUBLIC place le synonyme dans le schéma PUBLIC, le rendant ainsi visible de tout utilisateur défini sur la base de 
données (sans référence à un schéma). Sinon le synonyme reste local au SCHEMA de l’utilisateur propriétaire. 
Les  synonymes  offrent  la  possibilité  d’attribuer  plusieurs  noms  à  un  même  objet,  ce  qui  va  permettre  une 
simplification  lors  de  l’écriture  des  requêtes,  surtout  lorsque  la  même  table  doit  être  utilisée  plusieurs  fois  dans  le 
même ordre SELECT. 

Les  synonymes  PUBLIC  sont  très  utiles  car  ils  offrent  la  possibilité  à  une  application  de  travailler  avec  des  tables 
sans  tenir  compte  du  schéma  sur  lequel  les  objets  ont  été  créés.  Avec  ce  type  d’élément,  l’application  cliente  est 
totalement indépendante de la structure de la base et du propriétaire des éléments. 

Suppression

Syntaxe 

DROP [PUBLIC] SYNONYM nom ;

Exemple 

Jointure de la table NOMENCLATURE avec elle­même pour visualiser les articles composés : 

SQL>select * from NOMENCLATURE;

REFART DESIGNATION COMPOSANT NOMBRE


------- --------------- ---------- ----------
XX55 VELOCIPEDE 0
x133 Roues XX55 2
x520 Cadre XX55 1

© ENI Editions - All rigths reserved - 7-


x456 Guidon XX55 1
QD24 Lot de tapis 0
AB03 Carpettes QD24 10

6 ligne(s) selectionnée(s).

SQL>create synonym COMPOSE for NOMENCLATURE;

Synonyme créé.
SQL>select COMPOSE.REFART,COMPOSE.DESIGNATION,
2 NOMENCLATURE.NOMBRE,
3 NOMENCLATURE.DESIGNATION
4 from NOMENCLATURE,COMPOSE
5 where NOMENCLATURE.COMPOSANT=COMPOSE.REFART
6 order by COMPOSE.REFART;

REFART DESIGNATION NOMBRE DESIGNATION


---------- ------------------- ---------- --------------------
QD24 Lot de tapis 10 Carpettes
XX55 VELOCIPEDE 2 Roues
XX55 VELOCIPEDE 1 Cadre
XX55 VELOCIPEDE 1 Guidon

d. Les objets Sequence 

La création d’un objet SEQUENCE met à disposition de l’utilisateur un générateur de nombres. 
Les  séquences  sont  utilisées  pour  générer  des  numérotations  automatiques,  en  particulier  pour  la  création  de 
valeurs de clé primaire. 
L’utilisation  d’une  SEQUENCE  est  plus  souple  et  donne  de  meilleures  performances  que  la  gestion  manuelle  des 
compteurs par l’intermédiaire d’une table. 
Cependant l’utilisation d’une séquence ne garantit pas l’absence de "trous" dans la numérotation. La séquence est 
un  simple  générateur  de  numéros  et  tous  les  numéros  sont  différents  mais  si  des  numéros  sont  demandés  à  une 
séquence et ne sont pas utilisés par la suite, alors ces numéros sont perdus. La séquence est en effet un objet à 
part entière et peut être utilisée par plusieurs tables. 

Chaque valeur séquence s’exprime au maximum sur 28 chiffres significatifs. 
Syntaxe 

CREATE SEQUENCE nom [paramètres];

ALTER SEQUENCE nom paramètres ;

DROP SEQUENCE nom ;

Paramètres

START WITH n 

Valeur initiale. 

INCREMENT BY n 

Pas d’incrémentation. Il peut être positif ou négatif. 

MINVALUE n/NOMINVALUE 

Valeur limite minimum ou non. 

MAXVALUE n/NOMAXVALUE 

Valeur limite maximum ou non. 

CYCLE/NOCYCLE 

- 8- © ENI Editions - All rigths reserved


CYCLE  force  la  séquence  à  repasser  à  MINVALUE  lorsque  MAXVALUE  a  été  atteinte  (séquence  croissante)  ou  à 
MAXVALUE lorsque MINVALUE a été atteinte (séquence décroissante). 

CACHE n/NOCACHE 

Force l’anticipation de la génération des valeurs suivantes de la séquence en mémoire. A pour effet d’améliorer les 
temps de réponse de la séquence. 

ORDER/NOORDER 

Garantit un ordre d’affectation des nombres dans l’ordre des demandes. Cette option ne présente d’intérêt que dans 
le cas de l’utilisation de l’option PARALLEL OPTION en mode PARALLEL au niveau de l’instance Oracle. 

L’utilisation se fait par l’intermédiaire des pseudos­colonnes dans les instructions de manipulation de données. 

Pseudos­colonnes

nomseq.CURRVAL 

Donne la valeur actuelle de la séquence. Cette pseudo­colonne n’est pas valorisée par la création de la séquence ni 
lors de l’ouverture d’une nouvelle session. 

nomseq.NEXTVAL 

Incrémente la séquence et retourne la nouvelle valeur de la séquence. Cette pseudo­colonne doit être la première 
référencée après la création de la séquence ou une ouverture de session. 

Si la même séquence est référencée à partir de plusieurs sessions, la valeur de la pseudo­colonne  CURRVAL  dans 


une session n’est pas modifiée tant que l’utilisateur correspondant ne référence pas la pseudo­colonne NEXTVAL ; et 
ce, même si d’autres utilisateurs référencent NEXTVAL dans leur session. 
Exemple 

SQL> create sequence C_NOCLI start with 1000 maxvalue 9999 nocycle;

Séquence créée.

SQL> insert into CLIENTS (NOCLI, NOMCLI, VILLE)


2 values (C_NOCLI.nextval, ’DUPOND et DUPONT’, ’LILLE’);

1 ligne créée.

SQL> insert into CLIENTS (NOCLI, NOMCLI, VILLE)


2 values (C_NOCLI.nextval, ’DURAND et DURANT’, ’TOURCOING’);

1 ligne créée.

SQL> select NOCLI, NOMCLI, VILLE from CLIENTS order by NOCLI;


NOCLI NOMCLI VILLE
--------- ----------------------------- ----------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
36 BERNARD S.A. PARIS
138 DUBOIS Jean TOURS
152 LAROCHE LE MANS
1000 DUPOND et DUPONT LILLE
1001 DURAND et DURANT TOURCOING
8 ligne(s) sélectionnée(s).
SQL>

2. Les requêtes complexes 

a. Éléments de syntaxe 

© ENI Editions - All rigths reserved - 9-


Alias
Nom alternatif donné à une colonne ou à une table dans une requête. 

Les alias de colonne permettent de : 

● Changer le nom de la colonne à l’affichage ou pour la table résultante. 

● Donner un nom comportant des caractères spéciaux (espace par exemple). 

Les alias de table définis dans les clauses FROM des instructions SELECT correspondent à des synonymes internes à 
la requête. Ils permettent d’alléger l’écriture de l’instruction et de référencer dans des contextes différents la même 
table dans une instruction DML complexe (avec sous­requête). 

Syntaxe 

SELECT colonne [AS] alias_colonne,...


FROM table alias_table,...

Exemples 

Affichage d’un nom de colonne comportant des espaces : 

SQL> select NOCLI, NOMCLI as "Nom du client" from CLIENTS ;


NOCLI Nom du client
--------- ------------------------------
1000 DUPOND et DUPONT
1001 DURAND et DURANT
15 DUPONT S.A.
20 Etb LABICHE
35 DUBOIS Jean
36 BERNARD S.A.
138 DUBOIS Jean
152 LAROCHE
8 ligne(s) sélectionnée(s).

SQL>

Utilisation  de  la  table  d’origine  dans  une  sous­requête.  Alignement  de  la  quantité  en  stock  de  chaque  article  à  la  valeur 
maximum de la quantité en stock pour la famille (deux premiers caractères de la référence). 

SQL> update articles a


2 set qtestk=(select max (qtestk) from articles b
3 where substr(a.refart,1,2)=substr(b.refart,1,2));

9 ligne(s) mise(s) à jour.

SQL> select refart, designation, prix, qtestk 2 from articles;

REFA DESIGNATION PRIX QTESTK


---- ------------------------------ ---------- ----------
AB22 Taps Persan 1250,1 116
CD50 Chaine HIFI 735,4 20
CD21 Platine laser 500 20
ZZZZ Article bidon 25
AA00 Cadeau 8
AB03 Carpette 150 116
AB Tapis 116
ZZ01 Lot de tapis 500 25
AB10 Tapis de chine 1500 116

9 ligne(s) sélectionnée(s).

SQL>

Any
Compare, suivant l’opérateur donné (=,<>,<,<=,>,>=), les valeurs des colonnes spécifiées avec chacune des valeurs 
de la liste. L’expression est vraie si au moins une des comparaisons est vraie. La liste de valeurs peut être une liste 
de constantes littérales ou des valeurs retournées par une sous­requête. 

- 10 - © ENI Editions - All rigths reserved


Syntaxe 

SELECT ...... WHERE [(colonne, colonne,...)] opérateur ANY


({SELECT ...../expression,...});

La sous­requête ou la liste de valeurs doit retourner autant de valeurs que la liste d’expressions à comparer. 
Exemple 

Affichage des articles ayant le même prix que l’article ZZ01 : 

SQL> select refart, designation, prix, qtestk from articles


2 where prix=ANY(select prix from articles
3 where refart=’ZZ01’);

REFA DESIGNATION PRIX QTESTK


---- ------------------------------ ---------- ----------
CD21 Platine laser 500 20
ZZ01 Lot de tapis 500 25

SQL>

All
Compare, suivant l’opérateur donné (=,<>,<,<=,>,>=), les valeurs des colonnes spécifiées avec chacune des valeurs 
de la liste. L’expression est vraie si toutes les comparaisons sont vraies. La liste de valeurs peut être une liste de 
constantes littérales ou des valeurs retournées par une sous­requête. 
Syntaxe 

SELECT ...... WHERE [(colonne, colonne,..)] opérateur ALL


(SELECT...../expression,...);

Exists
La condition est vraie si la sous­requête retourne au moins une ligne. 
Syntaxe 

SELECT ...... WHERE [(]colonne [, colonne, ..)] EXISTS


(SELECT ...../expression,...);

Exemple 
La liste des clients n’est affichée que si au moins une commande existe dans la table COMMANDES. 

SQL> select NOCLI, NOMCLI from CLIENTS


2 where exists (select ’x’ from COMMANDES) ;

NOCLI NOMCLI
--------- ------------------------------
1000 DUPOND et DUPONT
1001 DURAND et DURANT
15 DUPONT S.A.
20 Etb LABICHE
35 DUBOIS Jean
36 BERNARD S.A.
138 DUBOIS Jean

152 LAROCHE
8 ligne(s) sélectionnée(s).

SQL> delete from COMMANDES;

4 ligne(s) supprimée(s).

SQL> select NOCLI, NOMCLI from CLIENTS


2 where exists (select ’x’ from COMMANDES) ;

aucune ligne sélectionnée

SQL>

© ENI Editions - All rigths reserved - 11 -


b. Les sous­requêtes 

Dans l’écriture d’une requête complexe, on distingue la requête externe de la requête interne, la sous­requête. 

Les  sous­requêtes  peuvent  être  divisées  en  deux  catégories  :  les  sous­requêtes  imbriquées  et  les  sous­requêtes 
corrélées. 

Sous­requêtes imbriquées

Dans  une  sous­requête  imbriquée  il  n’y  a  pas  de  lien  explicite  entre  la  requête  interne  et  la  requête  externe.  La 
requête  interne  est  exécutée  une  seule  fois  pour  construire  la  liste  de  valeurs,  avant  l’exécution  de  la  requête 
externe (quel que soit le nombre de lignes ramenées par celle­ci). 
Exemple 

Liste des clients qui habitent dans la même ville que le client "DUBOIS Jean". 

SQL> select NOCLI, NOMCLI, VILLE from CLIENTS


2 where VILLE in (select VILLE from CLIENTS
3 where NOMCLI like ’DUBOIS%’) ;

NOCLI NOMCLI VILLE


--------- ------------------------------ ----------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
138 DUBOIS Jean TOURS

SQL>

Sous­requêtes corrélées

Dans une sous­requête corrélée, la condition spécifiée dans la clause WHERE de la requête interne fait référence à 
une  ou  plusieurs  colonnes  de  la  requête  externe.  La  requête  interne  est  donc  réexécutée  pour  chaque  ligne 
retournée par la requête externe. 
Exemple 
Liste des clients pour lesquels il n’existe pas de commande. 

SQL> select nocli, nomcli


2 from clients cl
3 where not exists (select nocli
4 from commandes co
5 where cl.nocli=co.nocli);

NOCLI NOMCLI
---------- ------------------------------
15 DUPONT S.A.
20 Etb LABICHE
35 DUBOIS Jean
36 Bernard S.A.
37 Ets LAROCHE
138 DUBOIS Jean
152 LAROCHE

7 ligne(s) sélectionnée(s).

SQL>

Différence entre les deux types de sous­requêtes

Lors de l’écriture des sous­requêtes, il est possible de choisir l’écriture de sous­requête imbriquée, qui favorise alors 
l’utilisation de la clause IN, ou bien l’écriture de sous­requête corrélée, qui favorise l’utilisation de la clause EXISTS. 
Pour savoir qu’elle est la solution à retenir en fonction des données à extraire, il faut se pencher un peu plus sur le 
fonctionnement des clauses IN et EXISTS. 

Dans le cadre d’utilisation de la clause IN (sous­requête imbriquée), il est possible de concevoir que la sous­requête 
est  évaluée  comme  une  vue  en  ligne  et  qu’une  jointure  est  faite  sur  la  table  de  la  requête  principale  avec  les 

- 12 - © ENI Editions - All rigths reserved


informations issues de cette sous­requête. 
L’exemple présentant la sous­requête imbriquée est évalué de la façon suivante : 

Select nocli, nomcli, ville


from clients cli1, (select ville from clients where nomcli
like ’DUBOIS%’) cli2
where cli1.ville=cli2.ville

Dans le cas de l’utilisation de la clause EXISTS, la sous­requête corrélée est exécutée pour chaque ligne issue de la 
requête externe. Cette solution sera donc favorable si la table de la requête externe est relativement faible et qu’il 
existe de bons index posés sur la table de la sous­requête sur les colonnes qui participent à la jointure. 

L’exemple illustrant la sous­requête corrélée est intéressant par rapport à une sous­requête imbriquée si : 

● le nombre de clients est restreint par rapport aux commandes ; 

● l’extraction  des  différents  numéros  de  clients  à  partir  de  la  table  des  commandes  représente  une  lourde 
charge de travail. 

Un index est posé sur la colonne NOCLI de la table des commandes afin d’accélérer les temps de jointure. 

c. Les requêtes hiérarchiques 

Il est parfois nécessaire d’interroger les données suivant un ordre hiérarchique bien précis. Pour cela Oracle met à 
notre disposition des commandes pour extraire les données en utilisant un ordre. Ces commandes sont CONNECT BY 
PRIOR et START WITH. Lors de l’exécution d’une telle requête, Oracle procède de la façon suivante : 

● Oracle  sélectionne  la  racine  de  l’arbre,  ce  sont  les  lignes  qui  satisfont  la  condition  indiquée  dans  la  clause 
START WITH. 

● Oracle sélectionne les enfants de chaque père. Tous doivent satisfaire la condition indiquée dans la clause 
CONNECT BY. 

● Tous les enfants sont sélectionnés les uns après les autres. 

● Si la requête contient une clause WHERE, Oracle supprime de la hiérarchie toutes les lignes qui ne respectent 
pas la clause WHERE. 

Pour savoir à quel niveau de la hiérarchie on se situe, Oracle met à notre disposition la pseudo­colonne LEVEL. 
Exemple 
Création de table EMPLOYES. Chaque employé peut dépendre d’un chef dont il connaît le numéro. Le chef d’un employé est 
lui aussi un employé. On souhaite connaître l’organigramme de l’entreprise. 

SQL> create table employes(


2 noemp number(5)
3 constraint pk_employes primary key,
4 nom char(30),
5 poste char(15),
6 nochef number(5));

Table créée.

SQL>

La requête SQL permet de connaître l’organisation hiérarchique de l’entreprise : 

SQL> select substr(lpad(’ ’,2*(level-1))||nom,1,30) as nom,


2 noemp, nochef, poste
3 from employes
4 start with poste=’pdg’
5 connect by prior noemp=nochef;

NOM NOEMP NOCHEF POSTE


------------------------------ ---------- ---------- ---------------

© ENI Editions - All rigths reserved - 13 -


Ernest 5 pdg
Bernard 2 5 drh
Albert 1 2 comptable
Coutard 3 2 secrétaire
Hestor 8 2 employé
Fergère 6 5 expert
Dionaux 4 6 secrétaire
Grillet 7 6 employé

8 ligne(s) sélectionnée(s).

SQL>

La fonction SYS_CONNECT_BY_PATH, qui n’est utilisable que dans les requêtes hiérarchiques permet de connaître le 
chemin complet depuis le sommet de l’arbre. Cette fonction ne peut s’appliquer qu’aux colonnes de type caractère. 

L’exemple ci­dessous montre l’utilisation de cette fonction dans une requête hiérarchique. 

SQL> select lpad(’ ’,2*(level-1))||SYS_connect_by_path(rtrim(nom),’/’) as nom


2 from employes
3 start with poste=’pdg’
4 connect by prior noemp=nochef;

NOM
----------------------------------------------------------------------
/Ernest
/Ernest/Bernard
/Ernest/Bernard/Albert
/Ernest/Bernard/Coutard
/Ernest/Bernard/Hestor
/Ernest/Fergre
/Ernest/Fergre/Dionaux
/Ernest/Fergre/Grillet

8 ligne(s) sélectionnée(s).

SQL>

La  fonction  CONNECT_BY_ROOT  permet  de  connaître,  à  partir  d’un  élément  extrait  d’une  requête  hiérarchique,  les 
informations  concernant  le  sommet  de  la  hiérarchie.  Il  est  nécessaire  de  faire  précéder  le  nom  des  colonnes  pour 
lesquelles on souhaite cette information par CONNECT_BY_ROOT. 
Cette  fonctionnalité  est  surtout  intéressante  lorsque  l’on  souhaite  extraire  d’une  façon  hiérarchique  les  données 
avec une restriction sur certains critères. 
Par exemple, si la table contient des règles d’assemblage de pièces, il est possible à l’aide du CONNECT_BY_ROOT de 
connaître les éléments qui possèdent la pièce sur laquelle est faite la restriction. 
Exemple 
L’exemple ci­dessous permet facilement de connaître le "grand chef" de chaque employé. 

- 14 - © ENI Editions - All rigths reserved


 

L’extraction de données de façon hiérarchique est souvent faite par étape. Pour savoir si un élément est terminal ou 
non,  il  faut  effectuer  une  requête  hiérarchique  à  partir  de  cet  élément.  Avec  la  fonction  CONNECT_BY_ISLEAF  qui 
retourne 0 si l’élément n’est pas feuille et 1 sinon, il est tout de suite possible d’identifier les éléments qui possèdent 
un détail. 
Exemple 
Dans l’exemple ci­dessous on est capable de faire la distinction entre les employés qui gèrent une équipe et ceux qui ne le 
font pas. 

d. Pivoter les données 

Depuis  la  version  11,  il  est  possible,  très  facilement,  de  faire  pivoter  les  données  d’un  résultat  pour  obtenir  un 
affichage sous la forme d’un tableau croisé. 

À titre d’exemple, considérons une table qui stocke les ventes détaillées par code pays, code produit et année : 

SQL> desc VENTES


Nom NULL ? Type
----------------------------------------- -------- ---------------
CODEPAYS CHAR(2)
CODEPROD CHAR(4)
ANNEE NUMBER(4)
MONTANT NUMBER(8)

Nous pouvons interroger cette table pour produire un rapport donnant les ventes cumulées par pays et par année : 

© ENI Editions - All rigths reserved - 15 -


SQL> select ANNEE,CODEPAYS,sum(MONTANT)
2 from VENTES
3 group by ANNEE,CODEPAYS
4 order by ANNEE,CODEPAYS;

ANNEE CO SUM(MONTANT)
---------- -- ------------
2006 FR 1254781
2006 IT 1004852
2007 FR 1435278
2007 IT 986354
2007 US 835789
2008 FR 1451245
2008 IT 1034572
2008 US 1236745

8 ligne(s) sélectionnée(s).

Pour afficher le résultat sous la forme d’un tableau croisé, il faut modifier l’écriture de la requête et utiliser la clause 
PIVOT. 

Exemple 

SQL> select * from (


2 select ANNEE,CODEPAYS,MONTANT
3 from VENTES
4 )
5 pivot
6 (
7 sum(MONTANT)
8 for CODEPAYS in (’FR’,’US’,’IT’)
9 )
10 order by ANNEE;

ANNEE ’FR’ ’US’ ’IT’


---------- ---------- ---------- ----------
2006 1254781 1004852
2007 1435278 835789 986354
2008 1451245 1236745 1034572

Syntaxe simplifiée 

FROM table | sous-requête


PIVOT (
fonction_agrégat(expression)
FOR colonne IN (valeur [[AS] alias], ...)
)

La  clause  fonction_agrégat(expression)  permet  de  spécifier  la  formule  de  calcul  de  la  donnée  qui  va  être  affichée 
dans le tableau croisé ; cette formule de calcul doit utiliser une fonction d’agrégat (SUM, AVG, COUNT, etc). 
La clause FOR permet de spécifier la colonne du résultat d’origine dont les valeurs doivent être affichées en colonne, 
et de lister les valeurs qui seront affichées. Ces valeurs doivent être connues au départ ; il n’est pas possible de les 
définir dynamiquement. Dans la liste des valeurs, des alias peuvent être définis pour modifier le titre de la colonne. 

Exemple 

SQL> select * from (


2 select ANNEE,CODEPAYS,MONTANT
3 from VENTES
4 )
5 pivot
6 (
7 sum(MONTANT)
8 for CODEPAYS in (’FR’ AS FRANCE,’US’ AS USA,’IT’ AS ITALIE)
9 )
10 order by ANNEE;

ANNEE FRANCEUSAITALIE
---------- ---------- ---------- ----------

- 16 - © ENI Editions - All rigths reserved


2006 1254781 1004852
2007 1435278 835789 986354
2008 1451245 1236745 1034572

Il existe une variante de syntaxe qui permet de produire le résultat sous la forme d’un document XML. Avec 
cette variante, la liste des valeurs peut ne pas être connue au départ. 

Il existe aussi une clause UNPIVOT qui permet de faire l’opération inverse : transformer un tableau croisé en tableau. 

Supposons  que  nous  disposions  d’une  table  des  ventes  qui  stocke  les  données  sous  la  forme  d’un  tableau  croisé 
(assez étrange comme conception, j’en conviens) : 

SQL> desc VENTES


Nom NULL ? Type
----------------------------------------- -------- ------------
ANNEE NUMBER(4)
FRANCE NUMBER
USA NUMBER
ITALIE NUMBER

SQL> select * from VENTES;

ANNEE FRANCE USA ITALIE


---------- ---------- ---------- ----------
2006 1254781 1004852
2007 1435278 835789 986354
2008 1451245 1236745 1034572

Pour  afficher  le  résultat  sous  la  forme  d’un  tableau,  il  faut  modifier  l’écriture  de  la  requête  et  utiliser  la  clause 
UNPIVOT. 
Exemple 

SQL> select * from VENTES


2 unpivot
3 (
4 MONTANT
5 for CODEPAYS in (FRANCE,USA,ITALIE)
6 )
7 order by ANNEE,CODEPAYS;

ANNEE CODEPA MONTANT


---------- ------ ----------
2006 FRANCE 1254781
2006 ITALIE 1004852
2007 FRANCE 1435278
2007 ITALIE 986354
2007 USA 835789
2008 FRANCE 1451245
2008 ITALIE 1034572
2008 USA 1236745

8 ligne(s) sélectionnée(s).

Syntaxe simplifiée 

FROM table | sous-requête


UNPIVOT [{INCLUDE / EXCLUDE} NULLS] (
titre_colonne_cellule
FOR titre_colonne_pivot IN (colonne, ...)
)

titre_colonne_cellule définit le titre de la colonne qui va afficher la donnée initialement présente dans la cellule du 
tableau croisé. 

La  clause  FOR  permet  d’indiquer  quelles  colonnes  du  tableau  croisé  d’origine  doivent  devenir  des  valeurs  d’une 
colonne dont le titre est donné par titre_colonne_pivot. 
La clause INCLUDE NULLS permet d’inclure dans le résultat des lignes pour les valeurs NULL ; par défaut, ces lignes 
sont exclues. 

© ENI Editions - All rigths reserved - 17 -


Exemple d’utilisation de la clause INCLUDE NULLS 

SQL> select * from VENTES


2 unpivot include nulls
3 (
4 MONTANT
5 for CODEPAYS in (FRANCE,USA,ITALIE)
6 )
7 order by ANNEE,CODEPAYS;

ANNEE CODEPA MONTANT


---------- ------ ----------
2006 FRANCE 1254781
2006 ITALIE 1004852
2006 USA
2007 FRANCE 1435278
2007 ITALIE 986354
2007 USA 835789
2008 FRANCE 1451245
2008 ITALIE 1034572
2008 USA 1236745

9 ligne(s) sélectionnée(s).

3. Verrouillage des tables 

Lors des transactions concurrentes (accès aux mêmes données depuis des transactions différentes), il est nécessaire 
de préserver la cohérence des données. 
À un instant donné, une seule transaction est autorisée à modifier une donnée (une ligne). Les autres transactions 
souhaitant  modifier  la  même  donnée  peuvent  être  mises  en  attente  (sérialisation  des  demandes)  de  la  fin  de  la 
transaction. 
Pour  permettre  ce  fonctionnement,  Oracle  gère  simultanément  un  verrou  au  niveau  de  chaque  ligne  en  cours  de 
modification et un verrou au niveau de la table. Le verrou posé au niveau de la ligne (verrou TX : Row exclusive) est un 
verrou exclusif : si une transaction a pu poser ce verrou, aucune autre ne pourra le faire avant que le verrou ne soit 
relâché par la transaction (COMMIT ou ROLLBACK). 
Les  verrous  de  table  peuvent  être  posés  automatiquement  par  Oracle  au  cours  de  l’exécution  des  instructions  DML 
INSERT, UPDATE, DELETE et PL/SQL SELECT ... FOR UPDATE ou explicitement par les utilisateurs à l’aide de l’instruction 
LOCK TABLE. 

Types de verrou

EXCLUSIVE (X) 

La  pose  de  ce  type  de  verrou  sur  une  table  empêche  toute  autre  transaction  de  poser  explicitement  un  verrou  sur 
cette table et d’accéder à cette table en modification. 

SHARE (S) 

La pose de ce type de verrou sur une table empêche toute autre transaction de poser un verrou autre qu’un verrou 
SHARE sur la table et d’y accéder en modification. 

ROW SHARE (RS) 

La pose de ce type de verrou sur une table permet l’accès concurrent à la table (modification de lignes différente dans 
chacune  des  transactions)  et  empêche  toute  autre  transaction  de  poser  sur  cette  table  un  verrou  exclusif.  C’est un 
verrou d’intention. 

ROW EXCLUSIVE (RX) 

La pose de ce verrou sur une table indique que des lignes y ont été modifiées par une instruction DML. Il empêche la 
pose d’un verrou exclusif à partir d’une autre transaction. 

SHARE ROW EXCLUSIVE (SRX) 

- 18 - © ENI Editions - All rigths reserved


La pose de ce verrou sur une table empêche la pose d’un verrou par une transaction autre qu’un verrou d’intention 
RS. 

Les  instructions  DML  INSERT,  UPDATE,  DELETE  posent  automatiquement  un  verrou  RX  sur  la  table  en  cours  de 
modification. Une instruction SELECT ... FROM ... FOR UPDATE dans un bloc PL/SQL provoque la pose d’un verrou S sur 
la table. 

Lock
Syntaxe 

LOCK TABLE {table / view} IN{EXCLUSIVE / SHARE / ROW SHARE


/ ROW EXCLUSIVE / SHARE ROW EXCLUSIVE} MODE [NOWAIT / WAIT n] ;

Exemple 

Session 1 : la transaction verrouille la table COMMANDES de façon exclusive. 

SQL> lock table COMMANDES in EXCLUSIVE mode ;

Table(s) verrouillée(s).

SQL>

Session 2 : tentative de mise à jour d’une ligne de la table COMMANDES. L’instruction se met en attente du déverrouillage 
de la table. 

SQL> insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)


2 values (3001, 35, SYSDATE, ’EC’) ;

Session 1 : insertion d’une ligne et validation de la transaction. 

SQL> insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)


2 values (3001, 35, SYSDATE, ’EC’) ;

1 ligne créée.

SQL> commit ;

Validation effectuée.

SQL>

Session 2 : l’instruction d’insertion est exécutée mais échoue car la même donnée vient d’être insérée dans l’autre session. 

SQL> insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)


2 values (3001, 35, SYSDATE, ’EC’) ;
insert into COMMANDES (NOCDE, NOCLI, DATECDE, ETATCDE)
*
ERREUR à la ligne 1:
ORA-00001: violation de contrainte unique (GILLES.COMMANDES_PK)

SQL>

4. Les commentaires 

Afin de faciliter les opérations de mise à jour de la base, il est possible de poser des commentaires sur les tables et les 
vues  ainsi  que  sur  chacune  des  colonnes  qui  composent  ces  tables  et  ces  vues.  La  pose  de  commentaires  est  une 
étape indispensable car elle permet de connaître très exactement la signification et le rôle de chaque élément de la 
base  de  données.  Tous  ces  commentaires  sont  stockés  dans  un  dictionnaire  de  données  et  sont  accessibles  en 
interrogeant certaines vues du dictionnaire. 

Pour  poser  un  commentaire  sur  les  colonnes,  il  n’est  pas  indispensable  d’avoir  posé  au  préalable  un 
commentaire sur la table ou la vue. 

Syntaxe 

© ENI Editions - All rigths reserved - 19 -


COMMENT ON TABLE nom_table_vue IS ’texte’;
COMMENT ON COLUMN nom_table_vue.nom_colonne IS ’texte’;

Exemple 

Un commentaire est posé sur la table CLIENTS. 

Un commentaire est ensuite posé sur la colonne adrcli pour expliquer les données contenues dans cette colonne : 

Pour connaître les commentaires, il faut interroger le dictionnaire : 

Les  vues  ALL_COL_COMMENTS  et  USER_  COL_COMMENTS  contiennent  les  commentaires  posés  au  niveau 
colonne. 

5. Informations sur les objets du schéma 

Le  dictionnaire  de  données  possède  de  nombreuses  vues  qui  donnent  une  information  détaillée  des  différents 
éléments présents dans le schéma. 
Parmi les vues les plus couramment utilisées, on peut citer : 

ALL_OBJECTS, USER_OBJECTS 

ALL_CATALOG, USER_CATALOG 
ALL_TABLES, USER_TABLES 
ALL_TAB_COLUMNS, USER_TAB_COLUMNS 

ALL_TAB_COMMENTS, USER_TAB_COMMENTS 

ALL_COL_COMMENTS, USER_COL_COMMENTS 
ALL_VIEWS, USER_VIEWS 

ALL_INDEXES, USER_INDEXES 
ALL_IND_COLUMNS, USER_IND_COLUMNS 

ALL_SEQUENCES, USER_SEQUENCES 

ALL_SYNONYMS, USER_SYNONYMS 
ALL_DEPENDENCIES, USER_DEPENDENCIES 

- 20 - © ENI Editions - All rigths reserved


Toutes ces vues peuvent être retrouvées en effectuant une requête sur la vue DICT qui recense toutes les 
vues constitutives du dictionnaire avec pour chacune d’elle un petit commentaire indiquant leur rôle. 

Exemple 
La vue USER_TABLES est utilisée pour connaître toutes les tables de l’utilisateur courant. 

6. Fonctionnalités spécifiques 

NLS
Certaines fonctions doivent réagir différemment suivant le langage sélectionné au niveau du serveur Oracle. Au niveau 
Oracle,  tous  ces  critères  sont  fixés  par  les  paramètres  NLS  (National  Language  Support).  Ces  paramètres  ont  une 
incidence principalement sur l’affichage des données de type date et sur l’affichage des données de type numérique. 
Toutes  les  fonctions  SQL  qui  dépendent  de  NLS  acceptent  de  prendre  en  charge  un  paramètre  NLS  spécifique.  Ces 
fonctions sont : TO_CHAR, TO_DATE, TO_NUMBER, NLS_UPPER, NLS_LOWER, NLS_INITCAP, NLSSORT. 
Le principal intérêt de fixer le paramètre NLS au niveau de la fonction est de passer outre le choix réalisé au niveau de 
la session. 
Exemple 
Utilisation  de  paramètre  NLS  dans  une  fonction.  Pour  comparer  deux  dates,  l’exemple  suivant  transforme  la  date  de 
référence, qui est saisie sous forme de chaîne de caractères en donnée de type Date. Pour réaliser cette transformation, la 
fonction  TO_DATE  est  utilisée.  En  plus  de  la  chaîne  de  caractères  contenant  la  date,  cette  fonction  accepte  deux  autres 
paramètres : le format de la date et le paramètre de type NLS indiquant dans quelle langue la date a été saisie. 

La liste des différents paramètres NLS disponibles sur les fonctions SQL : 

Fonctions SQL  Paramètres NLS 

TO_DATE  NLS_DATE_LANGUAGE 
NLS_CALENDAR 

TO_NUMBER  NLS_NUMERIC_CHARACTERS 

© ENI Editions - All rigths reserved - 21 -


NLS_CURRENCY 
NLS_DUAL_CURRENCY 

NLS_ISO_CURRENCY 

TO_CHAR  NLS_DATE_LANGUAGE 

NLS_NUMERIC_CHARACTERS 
NLS_CURRENCY 

NLS_DUAL_CURRENCY 

NLS_ISO_CURRENCY 
NLS_CALENDAR 

NLS_UPPER  NLS_SORT 

NLS_LOWER  NLS_SORT 

NLS_INITCAP  NLS_SORT 

Différents exemples d’utilisation des paramètres NLS sont illustrés dans l’exemple suivant : 

TO_CHAR(datecde,’DD/MON/YYYY’,’NLS_DATE_LANGUAGE=FRENCH’)
TO_NUMBER(’15.999,80’,’9G999D99’,’NLS_NUMERIC_CHARACTERS=’’,.’’’)
TO_CHAR(prix,’9G999D99F’,’NLS_NUMERIC_CHARACTERS=’’,.’’
NLS_ISO_CURRENCY=Japan’)
NLS_UPPER(nomcli, ’NLS_SORT=SWISS’)
NLSSORT(nomcli,’NLS_SORT=GERMAN’)

Case
L’instruction  CASE  permet  de  mettre  en  place  une  condition  d’instruction  conditionnelle  directement  dans  la  requête 
SELECT, sans faire appel à un bloc d’instructions procédurales. 
L’intérêt  principal  de  cette  instruction  est  de  faciliter  la  présentation  et  la  mise  en  forme  des  résultats  directement 
dans les requêtes SELECT. L’instruction CASE permet également de limiter le nombre de fois où il est nécessaire de 
faire appel à un bloc PL/SQL pour résoudre le problème. 

L’instruction CASE est limitée à 128 choix. Pour pouvoir outrepasser cette limite, il est nécessaire d’imbriquer 
les instructions les unes dans les autres. 

Syntaxe 

CASE expression
WHEN expression_comparaison1 THEN expression_retournée1
WHEN expression_comparaison2 THEN expression_retournée2
....
[ELSE expression_retournée]
END

CASE
WHEN condition1 THEN expression_retournée1
WHEN condition2 THEN expression_retournée2
....
[ELSE expression_retournée]
END

L’instruction ELSE est optionnelle et, dans le cas où cette condition n’est pas présente, la valeur retournée est NULL si 
aucune instruction WHEN ... THEN n’est exécutée. 
Exemple 
L’exemple ci­dessous permet de connaître le libellé du département des clients à partir du code postal. 

SQL> select nocli, nomcli, case to_number(substr(code_postal,1,2))


2 when 44 then ’Loire Atlantique’
3 when 75 then ’Paris’

- 22 - © ENI Editions - All rigths reserved


4 else ’Autre’ END as departement
5 from clients;

NOCLI NOMCLI DEPARTEMENT


---------- ------------------------------ ----------------
15 DUPONT S.A. Loire Atlantique
20 Etb LABICHE Loire Atlantique
35 DUBOIS Jean Loire Atlantique
36 Bernard S.A. Paris
37 Ets LAROCHE Autre
138 DUBOIS Jean Autre
152 LAROCHE Autre

7 ligne(s) sélectionnée(s).

SQL>

Dans cet exemple, c’est la région qui est connue à partir du code postal du client. 

SQL> select nocli, nomcli, case


2 when to_number(substr(code_postal,1,2)) in (44,49,72,85,53)
3 then ’Pays de la Loire’
4 else ’Autre’ END as departement
5 from clients;

NOCLI NOMCLI DEPARTEMENT


---------- ------------------------------ ----------------
15 DUPONT S.A. Pays de la Loire
20 Etb LABICHE Pays de la Loire
35 DUBOIS Jean Pays de la Loire
36 Bernard S.A. Autre
37 Ets LAROCHE Autre
138 DUBOIS Jean Autre
152 LAROCHE Pays de la Loire

7 ligne(s) sélectionnée(s).

SQL>

7. Les expressions régulières 

Les  expressions  régulières  représentent  un  outil  puissant  pour  travailler  avec  les  chaînes  de  caractères.  Cette 
fonctionnalité est déjà présente sur de nombreux langages de programmation et sous Unix. 
Les  requêtes  d’extraction  de  données  avec  des  critères  très  précis  de  sélection  sur  les  données  de  type  caractère 
vont pouvoir être écrites plus facilement. 

Pour  pouvoir  travailler  avec  les  expressions  régulières,  Oracle  propose  un  opérateur  REGEXP_LIKE  et  quatre 
fonctions : REGEXP_INSTR, REGEXP_SUBSTR, REGEXP_REPLACE et REGEXP_COUNT. 
Les  expressions  régulières  vont  décrire  à  l’aide  de  méta­caractères  la  structure  que  doit  posséder  la  chaîne  de 
caractères avec laquelle on souhaite travailler. 
Bien  que  les  différents  méta­caractères  soient  présentés  par  la  suite,  il  est  préférable  de  travailler  avec  quelques 
exemples d’expressions régulières afin de bien comprendre comment elles fonctionnent. 
Les ancres 

^ : marque le début de la ligne 
$ : marque la fin de la ligne 

Les quantifieurs 

* : correspond à 0 ou plusieurs caractères. 
? : correspond à 0 ou 1 caractère. 

+ : correspond 1 ou plusieurs caractères. 
{m} : correspond à m caractères exactement. 

{m,} : correspond à au moins m caractères. 

© ENI Editions - All rigths reserved - 23 -


{m, n} : correspond à au moins m caractères mais moins que n caractères. 

Il faut faire attention à la manipulation de ces méta­caractères car ils ne possèdent pas forcément le même sens que 
ceux utilisés avec l’opérateur LIKE. 

Le caractère . permet de signaler l’existence de n’importe quel caractère dans la chaîne. 
Par exemple, l’expression régulière a.l peut correspondre aux chaînes de caractères apl, agl, ... mais également table, 
stable, allo. En effet dans l’expression régulière, seul est stipulé que les lettres a et l doivent être séparées par un 
caractère exactement. En aucun cas il n’est dit que la chaîne de caractères doit commencer par la lettre a et se finir 
par la lettre l. Si l’on souhaite un tel scénario, il faut utiliser les ancres afin de préciser le caractère qui marque le début 
de  la  chaîne.  L’expression  régulière  ^a.l  précise  que  la  chaîne  de  caractères  recherchée  doit  obligatoirement 
commencer par la lettre a, soit par exemple apl, agl, allo... 

Par  défaut,  les  caractères  présents  dans  l’expression  régulière  ne  doivent  être  présents  qu’une  seule  fois  dans  la 
chaîne  de  caractères.  Ainsi  l’expression  régulière  ^a.*e$  signifie  que  l’on  recherche  une  chaîne  commençant  par  la 
lettre  a  et  se  terminant  par  la  lettre  e.  Entre  le  premier  et  le  dernier  caractère  il  est  possible  d’avoir  entre  0  et  n 
caractères. Les chaînes ae, ane, anémone, ... répondent à cette expression. 
Afin  de  permettre  la  construction  d’expressions  encore  plus  complexes,  Oracle  supporte  les  classes  de  caractères 
POSIX  (Portable  Operating  system  Interface).  Grâce  à  cette  classe  de  caractères,  il  va  être  possible  d’écrire  des 
expressions régulières extrêmement précises afin de retrouver seulement l’information voulue. 

Les classes de caractères POSIX sont citées dans le tableau ci­dessous : 

[:alpha:] 

caractère alphabétique. 

[:lower:] 

caractère alphabétique en minuscule. 

[:upper:] 

caractère alphabétique en majuscule. 

[:digit:] 

numéro. 

[:alnum:] 

caractère alpha numérique. 

[:space:] 

espace. 

[:punct:] 

caractère de ponctuation. 

[:cntrl:] 

caractère de contrôle non imprimable. 

[:print:] 

caractère imprimable. 

Ces différentes classes de caractères permettent de couvrir l’ensemble des caractères présents dans la table ASCII. 

Pour  pouvoir  utiliser  les  classes  de  caractères  POSIX  dans  les  expressions  régulières,  il  est  nécessaire  de  les 
positionner entre des crochets []. 

Par exemple, l’expression [[:upper:]] permet de rechercher une chaîne de caractères écrite uniquement en majuscules 
alors que [[:lower:]]{5} correspond à des mots de 5 lettres en minuscules. 

Pour  affiner  les  recherches,  il  est  possible  de  citer  une  liste  de  caractères  que  l’on  souhaite  voir  apparaître  à  un 

- 24 - © ENI Editions - All rigths reserved


emplacement particulier. Par exemple l’expression ^pla[tc]e$ permet d’identifier aussi bien plate que place. 
Enfin,  et  c’est  souvent  là  que  réside  la  difficulté  d’écriture  des  expressions  régulières,  certains  méta­caractères  ne 
possèdent pas le même sens suivant leur emplacement. C’est le cas pour les 2 méta­caractères ^ et ­. 
Le caractère ^ lorsqu’il est placé en premier caractère d’une expression marque le début de l’expression  par  contre 
lorsqu’il apparaît comme premier caractère d’une liste de valeurs alors il marque la négation. 

Par  exemple  ^A[[:lower::]]  correspond  aux  chaînes  Ane,  Anneau, Arbre,  Appel,  ....  Par  contre  l’expression ^A[^nop]
[[:lower:]] permet simplement d’extraire Arbre, Ami, Avant, .... 

Le  caractère  ­  permet  de  simplifier  l’écriture  des  plages  de  valeur  en  citant  simplement  le  premier  et  le  dernier 
caractères  séparés  par  ­.  Par  exemple  dans  l’expression ^A[n­p][[:lower:]]  permet  d’identifier  les  chaînes  suivantes 
Ane, Anneau, Appel, .... 
Par contre s’il est placé en premier caractère d’une liste, il signale que les caractères situés à sa suite ne peuvent pas 
participer à la chaîne final. 

Donc l’expression ^A[­nop][[:lower:]] permet d’identifier Avant, Ami, Arbre.... 

REGEXP_LIKE

Cet opérateur permet l’utilisation des expressions régulières pour la recherche dans les clauses WHERE ou bien lors 
de la construction des contraintes d’intégrité. 

Syntaxe 

REGEXP_LIKE(colonne, expression_regulière)

Exemple 
Dans l’exemple suivant, on recherche les clients dont le nom commence par B suivi de caractères en minuscules. 

Mais l’opérateur REGEXP_LIKE peut également être utilisé pour définir des contraintes d’intégrité bien précise. 
Par  exemple,  si  l’on  souhaite  que  les  deux  premiers  caractères  d’une  référence  article  soit  toujours  des  caractères 
alphabétiques en majuscules, il est possible d’ajouter la contrainte d’intégrité suivante à la table des articles : 

REGEXP_REPLACE

La fonction REPLACE en SQL permet de substituer une chaîne de caractères par une autre. Mais l’utilisation de cette 
fonction  nécessite  de  connaître  exactement  la  chaîne  à  remplacer,  ce  qui  n’est  pas  toujours  le  cas.  La  fonction 
REGEXP_REPLACE quant à elle se sert simplement d’une description de la chaîne à remplacer. 

Syntaxe 

REGEXP_REPLACE(chaîne, expression_regulière,
chaîne_de_remplacement)

Exemple 

Par  exemple  lorsque  l’on  souhaite  éliminer  les  espaces  inutiles  dans  une  chaîne  de  caractères,  la  seule  certitude  que  l’on 
possède est que s’il y a plus d’un espace (deux, trois ou plus) alors il est possible d’éliminer les espaces inutiles. 

© ENI Editions - All rigths reserved - 25 -


 
 
Dans l’exemple ci­dessus, les espaces inutiles sont supprimés du nom du client.

REGEXP_INSTR

Cette fonction, dont l’objectif est le même que INSTR, permet de localiser l’emplacement de départ d’une sous­chaîne à 
l’intérieur d’une chaîne. L’avantage réside dans le fait qu’il n’est pas nécessaire de citer la sous­chaîne, mais il suffit de 
la décrire à l’aide d’une expression régulière pour la localiser. 
Syntaxe 

REGEXP_INSTR(chaîne, expression_regulière)

Exemple 
Dans l’exemple ci­dessous, on souhaite connaître la position de la sous­chaîne S.A. dans le nom des clients. 

REGEXP_SUBSTR

Comme pour la fonction SUBSTR, l’objectif de REGEXP_SUBSTR est d’extraire une sous­chaîne à partir d’une chaîne de 
caractères,  mais  en  décrivant  la  sous­chaîne  extraite  à  l’aide  d’une  expression  régulière.  Ceci  permet  d’extraire  la 
sous­chaîne sans connaître sa position exacte, ni même sa longueur. 

Syntaxe 

REGEXP_SUBSTR(chaine, expression_regulière)

Exemple : 
Dans l’exemple suivant, les noms des clients qui commence par LA est extrait. 

- 26 - © ENI Editions - All rigths reserved


 

REGEXP_COUNT

REGEXP_COUNT retourne le nombre de fois où l’expression régulière est trouvée dans la chaîne. La fonction retourne 
0 si l’expression régulière n’est pas trouvée. 
Syntaxe 

REGEXP_COUNT(chaîne, expression_régulière)

Exemple : 
Compter le nombre de mots d’une phrase. 

SQL> select
2 regexp_count(’il était une fois’,’[[:alnum:]]+’) nombre_mots
3 from dual;

NOMBRE_MOTS
-----------
4

© ENI Editions - All rigths reserved - 27 -


Utilisation de SQL*Plus 
L’accès et l’utilisation d’une base de données ORACLE peut se faire à l’aide de différents outils. 

L’outil principal pour l’utilisation du SQL et du PL/SQL est l’interface utilisateur SQL*Plus. 
Ce programme permet aux utilisateurs finaux, aux développeurs et aux administrateurs les fonctionnalités suivantes : 

● manipulation et exécution de commandes SQL et de blocs PL/SQL. 

● mise en forme des résultats de requêtes. 

● visualisation des structures des tables et copie de données inter­base. 

● commandes et opérations d’entrée/sortie (saisie, affichage, manipulation de variables). 

SQL*Plus possède également ses propres ordres de programmation. Il faut veiller à ne pas confondre l’utilitaire 
SQL*Plus et le langage SQL. 

Avant la version 11, l’outil SQL*Plus se déclinait sous trois formes différentes : 

● outil ligne de commande (sqlplus.exe) ; 

● application graphique Windows (sqlplusw.exe) ; 

● application Web (iSQL*Plus). 

Depuis la version 11, seule la version ligne de commande subsiste. 

1. Connexion et déconnexion 

Pour  pouvoir  utiliser  le  SQL,  il  faut  se  connecter  à  la  base  de  données,  c’est­à­dire  fournir  un  nom  d’utilisateur, 
éventuellement protégé par un mot de passe. 
SQL*Plus permet, soit de se connecter automatiquement en passant le nom et le mot de passe en paramètres de la 
ligne de commande du système d’exploitation, soit de demander le nom ou le mot de passe après le lancement. 
On peut, en outre, changer de nom d’utilisateur en cours de session SQL*Plus en se reconnectant. 

a. Lancement du programme 

À partir du prompt du système d’exploitation ; 

Syntaxe 

sqlplus[[-S] [nomuser[/motpasse][@chaîne_de_connexion]]

-S 

Mode silencieux. 

nomuser 

Nom de connexion à la base. 

motpasse 

Mot de passe de l’utilisateur. 

© ENI Editions - All rigths reserved - 1-


chaîne_de_connexion 

Nom du service défini dans le fichier TNSNAMES.ORA à utiliser pour se connecter au serveur Oracle. 
 

Les différents ordres permettant la configuration de SQL*Plus sont détaillés par la suite.

Si l’on souhaite retrouver toujours le même environnement de travail, il est possible de stocker ses préférences dans 
le ficher login.sql. Le fichier login.sql du répertoire courant est exécuté à la première connexion à SQL*Plus. 

Exemples 
Lancement du programme avec passage en paramètres du nom de l’utilisateur (TOTO) et du mot de passe (PIZZA) : 

$sqlplus toto/pizza
Connecté à :
...........
SQL>

Lancement du programme avec demande de connexion (le mot de passe est saisi en frappe aveugle) : 

$sqlplus
username : toto
password :
Connecté à :
............
SQL>

b. Connexion après lancement 

CONNECT
Syntaxe 

CONNECT [nomuser[/motpasse]][@chaîne_de_connexion]]

Exemple 
L’utilisateur courant veut se connecter sous le nom FLORIAN : 

SQL> Connect florian


password : < Saisie du mot de passe en frappe aveugle>
connecté.
SQL>

La chaîne de connexion n’est nécessaire que si l’on souhaite se connecter à un serveur Oracle qui n’est pas local. On 
peut donc se passer de chaîne de connexion lorsque l’on exécute SQL*PLUS directement sur le serveur Oracle. 
Connexion à une base distante depuis SQL*PLUS 

c. Changement du mot de passe 

Permet à l’utilisateur de changer son mot de passe dans l’environnement SQL*Plus. 

PASSWORD
Syntaxe 

PASSWORD [nomuser]

Exemple 
Changement du mot de passe de l’utilisateur courant. 

- 2- © ENI Editions - All rigths reserved


 

d. Déconnexion 

Après déconnexion, l’utilisateur ne peut plus utiliser de commande SQL ou PL/SQL. 

DISCONNECT
Syntaxe 

DISCONNECT

Exemple 
Déconnexion sans sortie de SQL*Plus : 

SQL>DISCONNECT
Disconnected from .......
.......
SQL>

e. Sortie de SQL*Plus 

La sortie du programme entraîne la déconnexion à la base. 
Syntaxe 

EXIT [SUCCESS / FAILURE / WARNING /n /variable


/:variable_liée][COMMIT / ROLLBACK]

SUCCESS/FAILURE/WARNING/n/ variable/:variable_liée 

Permet de communiquer au système d’exploitation un code de retour sur l’exécution de la session. 

COMMIT/ROLLBACK 

Valide ou annule la transaction en cours au moment de la fin de session (COMMIT par défaut). 

Exemple 
Sortie de SQL*Plus et retour au système d’exploitation ($ : prompt UNIX). 

SQL> EXIT
$.

2. Exécution des instructions 

Après  la  connexion,  l’utilisateur  peut  utiliser  SQL*Plus  pour  saisir  des  commandes  SQL,  des  blocs  PL/SQL  ou  des 
commandes SQL*Plus, à partir du prompt. 

Les  commandes  SQL  et  PL/SQL  peuvent  être  saisies  sur  plusieurs  lignes  (on  marque  une  fin  de  ligne  par  la  touche 
[Entrée]), le caractère de fin de commande étant le point­virgule (;). Pour améliorer la lisibilité on peut insérer dans la 
syntaxe  autant  d’espaces  ou  de  tabulations  qu’on  le  souhaite.  Il  n’y  a  pas  de  distinction  entre  majuscules  et 
minuscules (sauf utilisation de guillemets). 

Exemple 

Création de lignes dans la table CLIENTS : 

SQL> insert into CLIENTS (nocli, nom) values (10, ’TOTO’) ;

© ENI Editions - All rigths reserved - 3-


1 ligne creee
SQL> insert into
2> Clients (Nocli, Nom)
3> values (15, ’Titi’)
4> ;
1 ligne creee
SQL>

Les commandes SQL*Plus ne nécessitent pas de caractère de fin de commande, la marque de fin de ligne ([Entrée]) 
suffit. Si une commande doit être saisie sur plusieurs lignes, il faut utiliser le caractère de césure de ligne (tiret (­)). 

Exemple 
Déclaration de format de colonne : 

SQL> column REFART heading "Référence"


SQL> column DESIGN -
SQL> heading "Désignation"
SQL>

a. Gestion du buffer 

La dernière instruction SQL est stockée en mémoire (buffer). 
Ce buffer peut être réutilisé dans plusieurs cas : 

● réexécution de la dernière commande SQL ou du dernier bloc PL/SQL. 

● visualisation de la dernière commande. 

● modification de la dernière commande. 

● sauvegarde dans un fichier du buffer. 

La réexécution du buffer se fait par la commande RUN ou /. 
LIST
Visualisation du buffer. 
La  ligne  courante  est  indiquée  par  une  astérisque  (*).  Il  est  possible  de  changer  la  ligne  courante  en  ne  listant 
qu’une seule ligne (on précise son numéro). La ligne listée devient alors la nouvelle ligne courante. 
Syntaxe 

L[IST] [n|n m|n|n LAST|*|* n|* LAST|LAST]

n, m : numéro de ligne 

* : ligne courante 

LAST : dernière ligne 

Il est également possible de lister une seule ligne (qui devient alors la ligne courante) en tapant directement 
le numéro de la ligne. 

Exemple 

Saisie d’une commande SQL, visualisation du buffer, puis exécution : 

- 4- © ENI Editions - All rigths reserved


 

INPUT
Ajout de ligne au buffer après la ligne courante. 

Syntaxe 

I[NPUT] [texte]

Exemple 

Ajout d’une ligne à la dernière commande : 

SQL> select *
2 from clients
3 where nocli>15
4
SQL> i
4 order by nomcli
5
SQL> l
1 select *
2 from clients
3 where nocli>15
4* order by nomcli
SQL>

APPEND
Ajout à la fin de la ligne courante. 
Syntaxe 

A[PPEND] texte

Exemple 

Ajout de texte à la fin de la ligne 2 : 

SQL> l
1 select * from CLIENT
2 where NOCLI>15
3* order by NOM
SQL> 2
2* where NOCLI>15
SQL> A and NOCLI<20
2* where NOCLI>11 and NOCLI<20
SQL>

CHANGE

Modification de la ligne courante. 

© ENI Editions - All rigths reserved - 5-


Syntaxe 

C[HANGE]/ancien texte/[nouveau texte]

Si le nouveau texte est omis, il y a suppression de l’ancien texte. 

Exemple 
Modification de la première ligne : 

SQL> l
1 select * from clients
2* order by NOCLI
SQL>1
1* select * from clients
SQL>C/clients/COMMANDES
1* select * from COMMANDES
SQL>

DEL

Suppression d’une ou de plusieurs lignes du buffer. 

Syntaxe 

DEL [n|n m|n|n LAST|*|* n|* LAST|LAST]

n, m : numéro de ligne 

* : ligne courante 

LAST : dernière ligne 
 
Si la commande DEL est exécutée sans paramètres alors la ligne courante est supprimée.

Si la ligne courante est supprimée, alors c’est la ligne suivante (si elle existe) qui devient la nouvelle ligne 
courante. 

Exemple 
Suppression de la dernière ligne du buffer : 

SQL> l
1 select * from clients
2 where NOCLI>10
3* order by NOM
SQL> del
SQL> l
1 select * from clients
2* where NOCLI>10
SQL>

SAVE

Sauvegarde du buffer dans un fichier. 

Syntaxe 

S[AVE] nomfic [{CREATE/REPLACE/APPEND}]

Le fichier créé prend automatiquement l’extension .sql si aucune autre extension n’est précisée. 
CREATE 

(Option par défaut) crée un nouveau fichier. 

REPLACE 

Remplace le contenu d’un fichier existant. 

- 6- © ENI Editions - All rigths reserved


APPEND 

Ajoute le buffer à la fin d’un fichier existant. 

GET
Chargement du buffer à partir d’un fichier. 

Syntaxe 

G[ET] nomfic [{LIST/NOLIST}]

LIST 

(Option par défaut) liste le buffer. 

NOLIST 

Supprime l’affichage. 

b. Utilisation de scripts 

Il  est  possible  de  stocker  des  commandes  SQL  ou  SQL*Plus  dans  des  fichiers  de  texte  soit  par  SAVE,  soit  par 
l’éditeur  système,  puis  d’exécuter  ces  scripts  par  SQL*Plus.  Ces  fichiers  de  commandes  sont  reconnus  avec 
l’extension par défaut .sql, ils peuvent contenir des commentaires. 
EDIT

Appel de l’éditeur standard du système d’exploitation. 
Syntaxe 

[ED]IT [nomfic]

L’éditeur appelé est l’éditeur système sauf si la variable _EDITOR est valorisée (sous UNIX def _editor = vi, sous NT 
def _editor=notepad.exe). 
Edit  charge  par  défaut  le  fichier  avec  l’extension  .sql.  Si  aucun  nom  de  fichier  n’est  spécifié,  Edit  crée  un  fichier 
AFIEDT.BUF et recharge le buffer avec le contenu du fichier au retour dans SQL*Plus. 
REM
Commentaires. 
Syntaxe 

REM[ARK] texte

Le texte sera ignoré à l’exécution. 
Les commentaires peuvent aussi être indiqués par : 

-- 

Le reste de la ligne situé après ­­ est ignoré par SQL*Plus. 

/*... */ 

Le texte situé entre ces deux séparateurs est ignoré par SQL*Plus. Le commentaire peut comporter plusieurs lignes. 

START,@,@@

Exécution des commandes contenues dans le fichier. 

Syntaxe 

STA[RT] nomfic ou @nomfic ou @@nomfic

Par défaut, l’extension .sql est prise pour le fichier. 

© ENI Editions - All rigths reserved - 7-


Le nom du fichier doit contenir le chemin complet d’accès au fichier si ce dernier n’est pas dans le répertoire courant. 
Par défaut, si seul le nom du fichier est indiqué derrière la commande START ou @ alors le fichier script est recherché 
dans  le  répertoire  de  travail  de  SQLPLUS.  Le  fait  de  lancer  un  script  au  travers  de  la  commande  @@  permet  de 
garantir que le fichier sera recherché dans le même répertoire que celui du script qui demande l’exécution. 

COPY

Il est possible de copier des données d’une table à une autre table située sur une base de données locale ou non. 
Pour cela on utilise la commande SQL*Plus COPY et les clauses FROM et TO pour préciser la source et la destination 
des données. Les données à copier sont issues d’une requête SELECT. 
Syntaxe 

COPY {FROM base| TO base| FROM base TO base}


{APPEND|CREATE|INSERT|REPLACE} table_de_destination
[(colonne, ...)] USING requête

FROM base 

Permet  de  préciser  le  schéma  qui  contient  les  données  à  copier.  Si  la  clause  FROM  est  omise,  alors  l’origine  des 
données est le schéma auquel SQL*Plus est connecté. 

TO base 

Permet  de  préciser  le  schéma  de  destination  des  données.  Si  la  clause  TO  est  omise,  alors  la  destination  des 
données est le schéma auquel SQL*Plus est connecté. 

base 

Sous ce terme sont regroupés le nom de l’utilisateur, son mot de passe et la chaîne de connexion pour accéder à 
une base de données distante. 

APPEND 

Les données issues de la requête sont insérées dans la table de destination. Si cette dernière n’existe pas, alors la 
table est créée avant l’insertion des données. 

CREATE 

Les données issues de la requête sont insérées dans la table de destination après la création de cette dernière. Si 
la table de destination était déjà présente avant l’exécution de la commande COPY, alors une erreur est retournée. 

INSERT 

Les données issues de la requête sont insérées dans la table de destination. Si la table de destination n’existe pas, 
alors COPY retourne une erreur. 

REPLACE 

Les  données  issues  de  la  requête  remplacent  celles  de  la  table  de  destination.  Si  la  table  de  destination  n’existe 
pas, alors elle est créée par la commande COPY. 

Exemple 

La table DEPT de l’utilisateur SCOTT va être copiée sous le schéma de l’utilisateur LIVRE. Les deux schémas se situent sur 
une base de données distante. 

- 8- © ENI Editions - All rigths reserved


 

3. Gestion de l’environnement SQL*Plus 

SQL*Plus  permet  de  gérer  directement  (sans  passer  par  le  SQL)  certaines  fonctionnalités  de  la  base,  comme  la 
visualisation  des  structures  d’objet  ou  la  copie  de  données  d’une  base  à  une  autre.  Il  est  également  possible  de 
personnaliser l’utilisation de SQL*Plus en modifiant des paramètres agissant sur le fonctionnement des commandes, 
sur l’affichage, ou sur le résultat des commandes. 
DESCRIBE
Description de structure de table, vue, synonyme ou code stocké. 
Syntaxe 

DESC[RIBE] objet

SPOOL
Redirection des sorties. 
Syntaxe 

SPO[OL] {nomfic/OFF/OUT}

nomfic 

Nom du fichier recevant les sorties (extension .lst par defaut). 

OFF 

Fermeture du fichier. 

OUT 

Fermeture du fichier et sortie sur l’imprimante. 

SHOW
Visualisation de l’environnement. 

Syntaxe 

SHO[W] {ALL/paramètre}

SET

Paramètres d’environnement. 
Syntaxe 

SET parametre valeur

La valeur par défaut des paramètres est la première des valeurs possibles indiquées : 

© ENI Editions - All rigths reserved - 9-


AUTOCOMMIT {OFF/ON/IMMEDIATE/n} 

Validation automatique. 

CMDSEP {;/OFF/ON/c} 

Séparateur de commandes multilignes. 

FEEDBACK {6/n/OFF/ON} 

Affichage du nombre d’enregistrements selectionnés à partir de n. 

LONG {80/n} 

Format maximum des colonnes de type LONG. 

NULL {texte} 

Représentation des valeurs NULL. 

PAUSE {OFF/ON/texte} 

Activation de la pause en fin de page. 

SPACE {1/n} 

Nombre de caractères séparant les colonnes à l’affichage. 

SQLCASE {MIXED/LOWER/UPPER} 

Conversion en majuscules ou minuscules des commandes avant exécution. 

SQLCONTINUE {>/texte} 

Prompt de la énième ligne. 

SQLNUMBER {ON/OFF} 

Numérotation du prompt de énième ligne. 

SQLPROMPT {SQL/texte} 

Prompt de la première ligne. 

SQLTERMINATOR {;/c/OFF/ON} 

Caractère de fin de commande. 

ECHO {OFF/ON} 

Affichage des commandes d’un script à l’exécution. 

TERMOUT {ON/OFF} 

Affichage du résultat des commandes d’un script. 

HELP

Accès au système d’aide (s’il a été installé). 
Syntaxe 

HELP [commande]

- 10 - © ENI Editions - All rigths reserved


HOST
Accès au système d’exploitation. 

Syntaxe 

HOST [commande S.E.]

Avec  certains  systèmes  d’exploitation,  il  est  possible  d’utiliser  un  caractère  générique  pour  lancer  une 
commande  système  depuis  SQL*Plus.  Comme  ce  caractère  dépend  du  système,  il  faut  consulter  la 
documentation Oracle relative à la plate­forme d’installation pour connaître ce caractère. 

© ENI Editions - All rigths reserved - 11 -


Présentation des données 
SQL*Plus offre quelques fonctionnalités pour gérer des variables, saisir des valeurs et mettre en page des résultats de 
requêtes. 
Cela permet d’utiliser de manière plus conviviale le SQL ou le PL/SQL et de créer de véritables procédures de manière 
simple. 

1. Gestion des variables 

Il est possible de gérer deux sortes de variables : 

● les variables utilisateur, utilisées par SQL*Plus ou pour de la substitution de texte dans des commandes SQL 
et SQL*Plus avant leur exécution. 

● les variables de lien utilisées en interface avec le PL/SQL. 

DEFINE
Création d’une variable utilisateur. 
Syntaxe 

DEF[INE] [variable = texte]

Sans paramètre, DEFINE permet de visualiser les variables existantes. 
Les variables créées sont obligatoirement de type caractère. 
Certaines variables ont des noms et des utilisations réservées : 
_EDITOR 

Éditeur appelé par EDIT. 

_O_VERSION 

Version ORACLE. 

_O_RELEASE 

Numéro de "release" ORACLE. 

_CONNECT_IDENTIFIER 

Identifiant utilisé pour la connexion. 

_DATE 

Date courante. 

On peut définir 1024 variables au maximum. 
UNDEFINE

Suppression d’une variable utilisateur. 
Syntaxe 

UNDEF[INE] variable

Exemple 
Création des variables x et _editor, visualisation des variables, suppression de x. 

SQL> define x = abcdef

© ENI Editions - All rigths reserved - 1-


SQL> def _EDITOR = vi
SQL> DEF
DEFINE _EDITOR ="vi"(CHAR)
DEFINE X ="abcdef" (CHAR)
SQL> undef x

ACCEPT
Saisie d’une variable utilisateur. 

Si la variable n’a pas été définie, elle est créée. 
Syntaxe 

ACCEPT variable [NUM/CHAR] [PROMPT texte] [HIDE]

NUM/CHAR 

Caractères autorisés pour la valeur de la variable (chiffres uniquement ou alphanumérique). CHAR par défaut. 

PROMPT texte 

Affichage du texte avant la saisie. 

HIDE 

Frappe aveugle. 

Exemple 
Saisie des variables V_code et V_nom : 

SQL> accept V_NOM


(saisie par l’utilisateur de : Dupont)
SQL> accept V_CODE NUM prompt "Code ?"
Code ? (saisie de : 15)
SQL> def
DEFINE V_NOM = "Dupont" (CHAR)
DEFINE V_CODE = 15 (NUMBER)
SQL>

&nom
Utilisation d’une variable de substitution. 
Syntaxe 

&variable

Si la variable n’existe pas, une saisie est demandée. 
Exemple 

Saisie de variables et utilisation dans une commande SQL : 

SQL> accept NUMERO NUMBER prompt "Numero client ?"


Numero client ? 15
SQL> accept NOM prompt "Nom client ?"
Nom client ? TOTO
SQL> def tb = clients
SQL> select * from &tb where
2> Nocli > &NUMERO and
3> NOM = ’&NOM’;
ancien 1 : select * from &tb where
nouveau 1 : select * from client where
ancien 2 : nocli > &NUMERO
nouveau 2 : nocli >15
ancien 3 : NOM =’&NOM’ ;
nouveau 3 : NOM =’TOTO’ ;
aucune ligne sélectionnee
SQL>

- 2- © ENI Editions - All rigths reserved


&&nom

Permet en plus de créer la variable. 

Syntaxe 

&&variable

Exemple 

Lorsque la requête est réexécutée, la valeur de la variable n’est pas redemandée. 

SQL> select * from &&NomTab


2 /
Entrez une valeur pour nomtab: LIGCDES
ancien 1: select * from &&NomTab
nouveau 1: select * from LIGCDES

aucune ligne sélectionnée

SQL> run
1* select * from &&NomTab
ancien 1: select * from &&NomTab
nouveau 1: select * from LIGCDES

aucune ligne sélectionnée

SQL>

VARIABLE
Création d’une variable pour utilisation dans un bloc PL/SQL. 
Syntaxe 

VAR[IABLE] [nom [NUMBER/CHAR(n)]]

Sans paramètre, VARIABLE affiche les caractéristiques des variables existantes. 
Une variable PL/SQL ne peut être valorisée que dans un bloc PL/SQL par des instructions spécifiques au PL/SQL, elle 
est considérée par le PL/SQL comme une variable de l’hôte (préfixée de :). 
PRINT

Affichage du contenu de la variable PL/SQL. 
Syntaxe 

PRINT variable

Exemple 

SQL> var ncli number


SQL> variable
variable ncli
type de données NUMBER
SQL> begin
2 select count(*) into :ncli
3 from clients;
4 end;
5 /

Procédure PL/SQL terminée avec succès.

SQL> print ncli

NCLI
----------
7

SQL>

© ENI Editions - All rigths reserved - 3-


2. Présentation des résultats 

Le résultat des requêtes peut être mis en forme de manière simple en utilisant des commandes SQL*Plus. 
Ces  commandes  sont  généralement  des  déclarations  qui  doivent  être  faites  avant  les  instructions  SELECT  et  qui 
doivent être annulées ou désactivées après la requête. 

a. Contrôle du déroulement des scripts 

PAUSE
Définition d’une suspension d’exécution. 

Syntaxe 

PAUSE [texte]

PROMPT

Affichage de texte. 
Syntaxe 

PROMPT [texte]

b. En­tête et pied de page 

Déclaration ou annulation d’un en­tête : TTITLE. 
Déclaration ou annulation d’un pied de page : BTITLE 
BTITLE, TTITLE
Syntaxe 

{BTITLE/TTITLE} [option [texte/variable]]/ [OFF/ON]

Les différentes options sont : 
COL n 

Place le texte en colonne n. 

SKIP n 

Saute n lignes. 

TAB n 

Saute n colonnes. 

LEFT/CENTER/RIGHT 

Alignement. 

BOLD 

Caractère gras. 

FORMAT 

Format d’affichage composé de : 

9 remplace un chiffre (ex. : format ’9999’ pour 4 chiffres). 

- 4- © ENI Editions - All rigths reserved


0 affiche les zéros non significatifs (ex : ’00999’). 

$ est le préfixe du signe $. 

B remplace les zéros non significatifs par des espaces. 

MI/PR : MI affiche ­ après une valeur négative, PR affiche les valeurs négatives entre crochets. 

, insère une virgule. 

. positionne la marque décimale (ex. : ’999.99’ pour 3 entiers 2 décimales). 

V multiplie par 10 fois le nombre de décimales. 

EEEE est une notation scientifique. 

DATE est le format date. 

An permet un affichage sur n caractères. 

Les variables prédéfinies : 
SQL.PNO 

Page courante. 

SQL.LNO 

Ligne courante. 

SQL.RELEASE 

Numéro de release ORACLE. 

SQL.SQLCODE 

Dernier code erreur. 

SQL.USER 

Utilisateur courant. 

c. Rupture 

BREAK

Déclaration d’action à effectuer lors d’un changement de valeur de la colonne. 

Syntaxe 

BREAK [ON{colonne/expression/ROW/REPORT}
[{SKIP{n/PAGE}/DUPLICATES}]...]

d. Format de colonne 

COLUMN
Déclaration des attributs des colonnes sélectionnées. 

Syntaxe 

COLUMN [{colonne/expression} option]

Les différentes options sont : 

© ENI Editions - All rigths reserved - 5-


ALIAS nom 

Nom alternatif. 

LIKE alias 

Copie les attributs de l’alias. 

CLEAR 

Réinitialise les attributs. 

FOLD_AFTER 

Insère un retour chariot après la colonne. 

FOLD_BEFORE 

Insère un retour chariot avant la colonne. 

FORMAT format 

Format de la valeur affichée. 

HEADING texte 

En­tête de colonne. 

JUSTIFY{LEFT/CENTER/RIGHT} 

Justification. 

NEWLINE 

Idem à FOLD_BEFORE. 

NEW_VALUE variable 

Place la valeur de la colonne dans la variable pour l’afficher dans l’en­tête de page. 

OLD_VALUE variable 

Idem à NEW_VALUE pour le pied de page. 

NULL c 

Texte pour les valeurs nulles. 

NOPRINT/PRINT 

Affichage ou non de la colonne. 

WRAPPED/WORD_WRAPPED/TRUNCATED 

Césure des lignes trop longues. 

OFF 

Désactivation de la définition. 

ON 

- 6- © ENI Editions - All rigths reserved


Réactivation de la définition. 

e. Calcul statistique 

COMPUTE
Déclaration  d’un  calcul  à  effectuer  au  changement  de  valeur  de  l’expression  (qui  doit  avoir  été  déclarée  par  un 
BREAK). 
Syntaxe 

COMPUTE fonction OF {expression/colonne}


ON {expression/colonne/REPORT/ROW}

Les fonctions qu’il est possible d’utiliser sont : 

AVG 

Moyenne des valeurs non nulles. 

COUNT 

Dénombrement des valeurs non nulles. 

MAXIMUM 

Valeur maxi. 

MINIMUM 

Valeur mini. 

NUMBER 

Nombre de lignes. 

STD 

Écart­type. 

SUM 

Somme des valeurs. 

VARIANCE 

Variance. 

f. Annulation des déclarations 

CLEAR
Syntaxe 

CLEAR {BREAKS/COLUMNS/COMPUTES/TIMING/BUFFER/SQL/SCREEN}

3. Environnement et traitement des erreurs 

Un certain nombre de paramètres d’environnement permettent de gérer le fonctionnement des commandes de mise 
en page. Ces paramètres sont généralement valorisés en début de script et annulés en fin de script. 

a. Statistiques de temps 

© ENI Editions - All rigths reserved - 7-


TIMING

Syntaxe 

TIMING [{START texte/SHOW/STOP}]

b. Traitement des erreurs 

En cas d’erreurs soit du système d’exploitation, soit du SQL, SQL*Plus les ignore, ce qui peut être gênant dans des 
enchaînements de commandes ou pour l’intégrité des données. 

La déclaration WHENEVER permet de prévenir ces erreurs. 
WHENEVER

Syntaxe 

WHENEVER {OSERROR/SQLERROR} {EXIT[SUCCESS/


FAILURE/OSCODE/"][COMMIT/ROLLBACK]/CONTINUE
[COMMIT/ROLLBACK/NONE]}

EXIT 

Sort de SQL*Plus en envoyant le code erreur spécifié. 

CONTINUE 

Ne sort pas de SQL*Plus. 

COMMIT ou ROLLBACK 

Force une validation ou une annulation avant de sortir ou de continuer. 

NONE 

Ne fait rien avant de sortir ou de continuer. 

SET ERRORLOGGING
Syntaxe simplifiée 

SET ERRORL[OGGING] {ON | OFF} [TRUNCATE] [IDENTIFIER identifier]

Active ou désactive l’enregistrement dans une table des erreurs qui surviennent dans SQL*Plus. 
Par défaut, les erreurs sont enregistrées dans une table nommée SPERRORLOG ; si cette table n’existe pas, elle est 
créée automatiquement. 
TRUNCATE 

Vide la table lors de l’activation de l’enregistrement. 

IDENTIFIER 

Chaîne de caractères utilisée pour identifier les erreurs. 

c. Paramètres d’environnement 

SET

Paramètres liés à l’affichage. 
Syntaxe 

SET parametre valeur

- 8- © ENI Editions - All rigths reserved


DEFINE {’&’/c/ON/OFF} 

caractère utilisé pour les substitutions de variables. 

EMBEDDED {OFF/ON} 

chaque rapport débute sur une nouvelle page. 

HEADSEP {|/c/ON/OFF} 

caractère définissant un en­tête de colonne multiligne. 

LINESIZE {80/n} 

nombre de caractères par ligne. 

NEWPAGE {1/n/NONE} 

nombre de lignes entre le début de page et l’en­tête défini. 

NUMFORMAT {format} 

format par défaut des numériques. 

NUMWIDTH {10/n} 

taille par défaut des numériques. 

PAGESIZE {14/n} 

nombre de lignes entre l’en­tête et le bas de page. 

SCAN {ON/OFF} 

contrôle la présence des variables de substitution. 

SHOWMODE {ON/OFF} 

affichage des valeurs des variables en cas de changement. 

TAB {OFF/ON} 

utilisation des tabulations. 

TIME {OFF/ON} 

affichage de l’heure avant chaque commande. 

TIMING {OFF/ON} 

affichage des statistiques de temps. 

TRIMOUT {ON/OFF} 

suppression des espaces en fin de ligne. 

UNDERLINE {­/c/ON/OFF} 

caractère de soulignement. 

VERIFY {ON/OFF} 

liste la commande avant son exécution (en cas de substitution de variable). 

© ENI Editions - All rigths reserved - 9-


WRAP {ON/OFF} 

césure des lignes. 

La commande SET possède de nombreuses autres options mais seules les plus courantes sont documentées 
dans cet ouvrage. 

Exemple 
Script  de  mise  en  page,  extraction  et  sauvegarde  dans  un  fichier  (confcde.lis)  d’une  confirmation  de  commande  dont  le 
numéro est saisi par l’utilisateur. 

rem Edition de la confirmation d’une commande


rem Environnement
set echo off
set feed off
set pagesize 60
set newpage 0
set linesize 80

rem Saisie du numero de commande

accept VCDE number prompt ’No de commande à éditer ? ’

rem Mise en page

set term off

column REFART heading "Reference|article"


column DESIGNATION heading "Désignation"
column PRIXUNITHT heading "Prix H.T."
column QTECDE heading "Qté cde."
column NOCDE noprint new_value VNOCDE
column NOMCLIENT noprint new_value VNOM

break on NOCDE skip page

compute sum of Mt on NOCDE

ttitle center "Confirmation de commande" -


skip 2 left "Numero : " VNOCDE -
skip 1 left "Client : " VNOM skip 3

btitle tab 40 "Page " sql.pno

spool confcde.lis

rem Extraction

select COMMANDES.NOCDE,NOMCLIENT,LIGNESCDE.REFART,DESIGNATION,
PRIXUNITHT,QTECDE,PRIXUNITHT*QTECDE "Mt"
from COMMANDES,LIGNESCDE,CLIENTS,ARTICLES
where COMMANDES.NOCDE = &VCDE
and COMMANDES.NOCLIENT = CLIENTS.NOCLIENT
and COMMANDES.NOCDE = LIGNESCDE.NOCDE
and LIGNESCDE.REFART = ARTICLES.REFART
/
spool out

rem Annulation de la mise en page

ttitle off
btitle off
clear breaks
clear columns
clear compute
set pagesize 14
set newpage 1

- 10 - © ENI Editions - All rigths reserved


set feed on
set echo on
set term on

Résultat du script précédent si N° de commande saisi est 1210 : 

Confirmation de commande

Numero : 1210
Client : DUPONT S.A.

Reference
article Désignation Prix H.T. Qté cde. Mt
---------- ----------------- ----------- --------- -------
AB10 Tapis de Chine 1500 3 4500
CD50 Chaîne HIFI 735,4 4 2941,6
-------
7441,6
Page 1

4. Création d’un rapport au format HTML 

SQL*Plus offre la possibilité de créer un rapport au format HTML en utilisant les commandes SET MARKUP et SPOOL. 
Les  informations  du  rapport  sont  insérées  à  l’intérieur  de  la  balise  HTML  <PRE>,  et  donc  l’affichage  au  sein  de 
l’explorateur Internet est exactement le même que celui perçu dans SQL*Plus. 
Syntaxe 

SET MARK[UP] HTML [ON|OFF] [HEAD ’texte’] [BODY ’texte’][TABLE ’texte’]


[ENTMAP {ON|OFF}] [SPOOL {ON|OFF}] [PRE[FORMAT]{ON|OFF}]

Les choix par défaut des options sont soulignés. 
La commande SET MARKUP permet à SQL*Plus de générer un résultat au format HTML et non plus au simple format 
texte. L’intérêt de fournir directement les données au format HTML n’est plus à démontrer car ce format permet une 
présentation  simple  à  mettre  en  place  et  soignée  tout  en  restant  indépendante  de  l’outil  utilisé  pour  visualiser  le 
résultat. 
Les différents paramètres de cette commande sont : 
HTML 

(OFF  par  défaut)  Positionner  à  ON  la  valeur  de  cette  option  permet  d’activer  la  génération  des  résultats  au  format 
HTML. 

HEAD 

Permet de personnaliser l’en­tête de la page HTML comme par exemple le fait de définir un titre à l’aide des balises 
<TITLE>  et  </TITLE>.  C’est  également  à  cet  endroit  que  l’on  pourra  définir  les  styles  à  appliquer  aux  différentes 
balises. 

BODY 

L’option BODY permet de définir les attributs de la balise BODY. Par défaut aucun attribut n’est sélectionné mais il est 
toujours possible de le faire par cette option. 

TABLE 

Permet de spécifier les attributs du tableau. Par défaut, le tableau est défini comme possédant une largeur de 90% 
(WIDTH=’90%’) et la largeur de la bordure est fixée à 1 (border=’1’). 

ENTMAP 

(ON par défaut) Positionner à OFF la valeur de cette option permet d’interpréter les caractères HTML correctement, ce 
qui  peut  être  le  cas  pour  <,  >,"  et  &.  Avec  cette  précaution,  ces  caractères  ne  sont  pas  remplacés  par  leur  entité 

© ENI Editions - All rigths reserved - 11 -


respective &lt, &gt,&quot et &amp. 

SPOOL 

(OFF par défaut) Positionner à ON la valeur de cette option permet d’ajouter les balises <HTML> et <BODY> ainsi que 
les  balises  fermant  correspondant  en  début  et  fin  de  fichier.  Ce  paramètre  n’est  en  aucun  cas  équivalent  à  la 
commande SPOOL qui permet de rediriger les informations affichées à l’écran vers un fichier. 

PREFORMAT 

(OFF  par  défaut)  indique  à  SQL*Plus  que  les  résultats  sont  présentés  sous  forme  de  tableau.  Positionner  à  ON  la 
valeur de cette option permet de préciser les informations indiquées après une balise <PRE>. 

Afin  de  présenter  au  mieux  le  script  SQL*Plus  qui  contient  la  commande  SET  MARKUP,  il  est  fortement 
recommandé de saisir cette commande sur plusieurs lignes en prenant soin de ne pas oublier le caractère de 
continuation (­) des instructions SQL*Plus. 

Le script ci­dessous illustre comment il est possible de produire un résultat au format HTML depuis SQL*Plus. 

rem Exemple de génération de rapport en HTML


set echo on
set markup html on spool on entmap on -
head "<TITLE>Les commandes</TITLE> -
<STYLE type=’text/css’> -
<!-- BODY{background:#FFFFC6} --> -
</style>"-
BODY "TEXT=’#FF00FF’" -
TABLE "BORDER=’2’" -
preformat off
column nocde heading ’N°’
column nocli heading ’Client’
column datecde heading ’Date’
column etatcde heading ’Etat’ format A4
spool test.html
select nocde, nocli, datecde, etatcde from commandes;
spool off
set markup html off spool off

L’exécution de ce script donne le résultat suivant : 

SQL> select nocde, nocli, datecde, etatcde from commandes;

N° Client Date Etat


100 15 23/07/02 EC
1301 15 22/07/02 EC
1210 15 20/07/02 SO
1250 35 19/07/02 EC
1230 35 18/07/02 SO

SQL> spool off

- 12 - © ENI Editions - All rigths reserved


SQL Developer 

1. Lancer SQL Developer 

Oracle SQL Developer est une application graphique permettant d’exécuter des requêtes ou des scripts SQL, de gérer 
les objets d’une base de données (tables, vues, etc.) et de développer et mettre au point des programmes PL/SQL. 
Oracle SQL Developer est gratuit et peut être téléchargé directement sur le site OTN (Oracle Technology Network). La 
page  d’accueil  d’Oracle  SQL  Developer  se  trouve  à  l’adresse  suivante  : 
http://www.oracle.com/technology/products/database/sql_developer/index.html.  Vous  trouverez  notamment  à  cette 
adresse la documentation et des tutoriaux. 

Depuis la version 11, Oracle SQL Developer est installé par défaut avec le serveur Oracle et le client Oracle. 
Sur  plate­forme  Windows,  Oracle  SQL  Developer  peut  être  lancé  par  le  menu  Démarrer  ­  Programmes  ­  Oracle  ­ 
nom_oracle_home ­ Développement d’applications ­ SQL Developer. 
Sur  plate­forme  Unix  ou  Linux,  Oracle  SQL  Developer  peut  être  lancé  à  l’aide  du  shell  script 
$ORACLE_HOME/sqldeveloper/sqldeveloper.sh  ($ORACLE_HOME  désigne  le  répertoire  de  l’installation  d’Oracle). 
L’application nécessite un environnement graphique. 

Sur  plate­forme  Windows,  lors  du  premier  lancement,  il  est  possible  que  l’outil  demande  le  chemin  de  l’application 
java.exe.  Vous  pouvez  utiliser  celle  fournie  par  Oracle  : %ORACLE_HOME%\jdk\bin\java.exe  (%ORACLE_HOME%  désigne  le 
répertoire de l’installation d’Oracle). 
La fenêtre principale d’Oracle SQL Developer a l’allure suivante : 

Dans  la  partie  gauche  de  la  fenêtre,  une  structure  arborescente  permet  de  naviguer  dans  les  objets  d’une  ou  de 
plusieurs bases de données. Dans la partie droite de la fenêtre, la zone de travail permet d’éditer et d’exécuter des 
requêtes SQL et de visualiser le résultat. 

Dans  l’ensemble,  cet  outil  est  très  convivial  et  son  apprentissage  est  aisé.  Dans  ce  chapitre,  nous  ferons  une 
présentation  rapide  de  son  utilisation ;  pour  plus  d’informations,  vous  pouvez  consulter  la  documentation  "Oracle® 
Database SQL Developer User’s Guide". 

2. Créer une nouvelle connexion 

© ENI Editions - All rigths reserved - 1-


Pour  créer  une  nouvelle  connexion,  vous  pouvez  cliquer  sur  le  bouton  ou  faire  un  clic  droit  sur  le  dossier 
Connections et sélectionner le menu New Connection. 

Dans la boîte de dialogue qui s’affiche, vous devez saisir les informations suivantes : 
Connection Name 

Nom de la connexion. 

Username 

Compte à utiliser pour la connexion. 

Password 

Mot de passe du compte à utiliser pour la connexion. 

Save Password 

Si la case est cochée, le mot de passe est enregistré et ne sera pas demandé lors de l’ouverture de la connexion. 

Hostname 

Nom du serveur. 

SID 

Nom de l’instance. 

Le bouton Test permet de tester la connexion. Le bouton Connect permet d’enregistrer la nouvelle connexion et de se 
connecter. 

Une fois que la connexion existe, pour se connecter, il suffit de cliquer sur le petit + situé à gauche de l’icône  de  la 


connexion, ou de faire un clic droit sur le nom de la connexion et sélectionner le menu Connect. 

3. Saisir des requêtes SQL 

- 2- © ENI Editions - All rigths reserved


Une fois la connexion établie, une zone de travail SQL s’ouvre dans la partie droite de la fenêtre : 

Pour ouvrir des zones de travail SQL supplémentaires, vous pouvez cliquer sur le bouton  dans la barre d’outils 
(ou  choisir  le  nom  d’une  connexion  dans  la  liste  déroulante  associée  à  ce  bouton),  ou  faire  un  clic  droit  sur  le  nom 
d’une connexion dans le panneau des connexions et sélectionner le menu Open SQL Worksheet. 

Vous  pouvez  maintenant  saisir  la  requête  souhaitée  dans  la  zone  de  saisie  puis  cliquer  sur  le  bouton  ou 
appuyer sur la touche [F9] ; le résultat s’affiche dans l’onglet Results, comme dans une feuille Excel : 

© ENI Editions - All rigths reserved - 3-


 

Une ou plusieurs requêtes peuvent aussi être exécutées sous la forme d’un script en cliquant sur le bouton  ou 
en appuyant sur la touche [F5] ; le résultat s’affiche dans l’onglet Script Output, comme dans SQL*Plus : 

- 4- © ENI Editions - All rigths reserved


La liste déroulante située en haut à gauche permet de changer de connexion : 

Un  script  SQL  existant  peut  aussi  être  ouvert  dans  SQL  Developer  en  cliquant  sur  le  bouton  puis  en 
sélectionnant le fichier dans la boîte de dialogue qui vous est proposée. Le script est ouvert dans une nouvelle zone 
de travail : 

Vous pouvez sélectionner une connexion pour cette nouvelle zone de travail à l’aide de la liste déroulante présentée 
précédemment. 

Une fois ouvert, le script peut être modifié puis exécuté (bouton  ou touche [F5]) ; lors de la première exécution, 
si aucune connexion n’a été sélectionnée au préalable, une boîte de dialogue s’affiche pour en choisir une. 
 
Vous pouvez sauvegarder le script modifié en cliquant sur le bouton  .
 
Oracle SQL Developer supporte un grand nombre de commandes SQL*Plus.

4. Mettre à jour les données 

La zone de travail SQL présentée précédemment peut être utilisée pour saisir et exécuter des requêtes de mise à jour 
(INSERT,  UPDATE,  DELETE).  Dans  ce  cas,  vous  devez  utiliser  le  bouton  pour  enregistrer  définitivement  les 
modifications  dans  la  base  (COMMIT).  En  cas  de  besoin,  pour  annuler  les  modifications  en  cours  (ROLLBACK),  vous 
pouvez cliquer sur le bouton  . 

Pour mettre à jour les données, vous pouvez aussi utiliser l’éditeur de données de la table. 

© ENI Editions - All rigths reserved - 5-


Pour  cela,  il  suffit  de  sélectionner  la  table  souhaitée  dans  le  panneau  des  connexions,  puis  de  cliquer  sur  l’onglet 
Data : 

Les  données  peuvent  être  modifiées  directement  dans  la  grille.  Vous  disposez  aussi  de  plusieurs  boutons  pour  agir 
sur les données : 
 

Insérer une nouvelle ligne. 
 

Supprimer la ligne courante. 
 

Enregistrer définitivement les modifications dans la base. 
 

Annuler les modifications. 

Dans la première colonne, le numéro des lignes modifiées est précédé d’un symbole : + pour une ligne insérée, ­ pour 
une ligne supprimée et * pour une ligne modifiée. Exemple : 

- 6- © ENI Editions - All rigths reserved


 

5. Travailler avec les objets d’un schéma 

Dans le panneau des connexions, vous pouvez naviguer très facilement dans les différents types d’objets d’un schéma 
et visualiser leur définition. 
Pour  créer  un  nouvel  objet,  il  faut  sélectionner  le  dossier  correspondant  au  type  d’objet  souhaité  (table,  vue,  etc.), 
faire un clic droit, puis sélectionner le menu New….  Une boîte de dialogue spécifique au type d’objet sélectionné est 
alors affichée. 
Exemple pour une table 

Pour modifier la définition d’un objet, il suffit de le sélectionner dans le panneau des connexions, de faire un clic droit 
et de sélectionner le menu Edit…. Une boîte de dialogue spécifique au type d’objet sélectionné est alors affichée. 

Exemple pour une table 

© ENI Editions - All rigths reserved - 7-


 

Cette boîte de dialogue permet de modifier les différentes caractéristiques de l’objet sélectionné. 
D’une  manière  générale,  en  faisant  un  clic  droit  sur  un  objet,  un  menu  contextuel  s’affiche  et  offre  différentes 
possibilités d’action sur l’objet. 
Exemple pour une table 

6. Exporter des données 

Les données affichées dans les différentes grilles d’Oracle SQL Developer peuvent être très facilement exportées sous 
différents formats (CSV, XML, HTML, etc.). 
Pour cela, il suffit de faire un clic droit dans la grille et de sélectionner un des sous­menus du menu Export Data : 

- 8- © ENI Editions - All rigths reserved


 

Une boîte de dialogue est ensuite affichée afin de préciser notamment le nom du fichier : 

7. Exporter des définitions 

Oracle  SQL  Developer  offre  la  possibilité  d’exporter  la  définition  (et  les  données)  de  tout  ou  partie  des  objets  d’un 
schéma. 

Pour cela, il faut sélectionner le menu Tools ­ Export DDL (and Data). Une boîte de dialogue Export s’affiche : 

© ENI Editions - All rigths reserved - 9-


 

Cette  boîte  de  dialogue  permet  de  définir  le  fichier  de  destination  et  la  connexion  à  utiliser,  et  de  sélectionner  les 
différents types d’objets à exporter et les options de l’export. 
L’onglet Filter Objects permet de définir des filtres sur les objets à exporter (basés sur le nom et le type de l’objet). 
L’onglet Filter Data permet de définir des filtres sur les données à exporter. 
Pour lancer l’export, il suffit de cliquer sur le bouton Appliquer. 

- 10 - © ENI Editions - All rigths reserved


Introduction 

1. Qu’est­ce que le PL/SQL ? 

Le PL/SQL est le langage procédural d’ORACLE. Il constitue une extension au SQL qui est un langage ensembliste. 
L’intérêt  du  PL/SQL  est  de  pouvoir  mélanger  la  puissance  des  instructions  SQL  avec  la  souplesse  d’un  langage 
procédural dans un même traitement. 

Ces  traitements  peuvent  être  exécutés,  soit  directement  par  les  outils  ORACLE  (blocs  anonymes),  soit  à  partir 
d’objets de la base (procédures stockées et PACKAGES). 

Les avantages du PL/SQL sont multiples : 

● Intégration du SQL : les instructions du DML, du transaction control et les fonctions SQL peuvent être utilisées 
avec pratiquement la même syntaxe. 

● Traitements procéduraux : la gestion des variables et les structures de contrôle (test, boucles) accroissent les 
possibilités de gestion des données. 

● Fonctionnalités  supplémentaires  :  la  gestion  des  curseurs  et  le  traitement  des  erreurs  offrent  de  nouvelles 
possibilités de traitements. 

● Amélioration des performances : plusieurs instructions sont regroupées dans une unité (bloc) qui ne génèrera 
qu’un "accès" à la base (à la place d’un accès par instruction). 

● Incorporation  aux  produits  ORACLE  :  les  blocs  ou  procédures  PL/SQL  sont  compilés  et  exécutés  par  le 
"moteur"  PL/SQL.  Ce  moteur  est  directement  intégré  au  moteur  de  la  base  de  données  ainsi  qu’à  certains 
outils Oracle : Oracle*Forms, Oracle*Report. 

2. Instructions SQL intégrées dans PL/SQL 

Ces instructions sont utilisables avec pratiquement la même syntaxe qu’en SQL. 

● La partie interrogation : SELECT. 

● La partie manipulation : INSERT, UPDATE, DELETE. 

● La partie gestion des transactions : COMMIT, ROLLBACK, SAVEPOINT... 

● Les fonctions TO_CHAR, TO_DATE, UPPER, SUBSTR, ROUND... 

3. Instructions spécifiques au PL/SQL 

Les caractéristiques procédurales de PL/SQL apportent les possibilités suivantes : 

● la gestion des variables (déclaration, valorisation, utilisation), 

● les structures de contrôle (séquence, test, boucles). 

Des fonctionnalités supplémentaires sont disponibles : 

● la gestion des curseurs (traitement du résultat d’une requête ligne par ligne), 

● les traitements d’erreurs (déclaration, action à effectuer). 

© ENI Editions - All rigths reserved - 1-


4. Le bloc PL/SQL 

PL/SQL n’interprète pas une commande, mais un ensemble de commandes contenues dans un "bloc" PL/SQL. Ce bloc 
est compilé et exécuté par le moteur PL/SQL du produit ou de la base. 

Structure d’un bloc PL/SQL

Un bloc est composé de trois sections. 

DECLARE
(déclaration des variables, des constantes, des exceptions
et des curseurs)

BEGIN
(instruction SQL, PL/SQL, structures de contrôle)

EXCEPTION
(traitement des erreurs)

END ;

Il est possible d’ajouter des commentaires à un bloc : 

­­ 

permet de mettre en commentaire ce qui suit sur la ligne. 

/*... ... */ 

permet de mettre en commentaire plusieurs lignes. 

Des étiquettes (label) permettent de marquer des parties de bloc, sous la forme <<nometiquette>>. 

La section DECLARE qui permet de déclarer les variables qui vont être utilisées dans le bloc PL/SQL n’est nécessaire 
que si le bloc a besoin de définir des variables. De même, la section EXCEPTION ne sera présente que dans les blocs 
qui vont gérer les erreurs. 

- 2- © ENI Editions - All rigths reserved


Gestion des variables 
Les variables sont des zones mémoires nommées permettant de stocker une valeur. 

En PL/SQL, elles permettent de stocker des valeurs issues de la base ou de calculs, afin de pouvoir effectuer des tests, 
des calculs ou des valorisations d’autres variables ou de données de la base. 

Les variables sont caractérisées par : 

● leur nom, composé de lettres, chiffres, $, _ ou # . Un maximum de 30 caractères est possible. Ce ne doit pas 
être un nom réservé. 

● leur type, qui détermine le format de stockage et d’utilisation de la variable. 

Les variables doivent être obligatoirement déclarées avant leur utilisation. 

Comme SQL, PL/SQL n’est pas sensible à la casse. Les noms des variables peuvent donc être saisis indifféremment en 
minuscules ou en majuscules. 

1. Variables locales 

Déclaration

PL/SQL dispose de l’ensemble des types utilisables dans la définition des colonnes des tables dans le but de faciliter 
les échanges de données entre les tables et les blocs de code. Cependant, les étendues des valeurs possibles pour 
chacun de ces types peuvent être différentes de celles du SQL. 
Il dispose également d’un certain nombre de types propres, principalement pour gérer les données numériques. 
Enfin,  PL/SQL  permet  de  définir  des  types  complexes  basés  soit  sur  des  structures  issues  des  tables,  soit  sur  des 
descriptions propres à l’utilisateur. 
Syntaxe 

nom-de-variable [CONSTANT]
type [[NOT NULL]:=expression] ;

CONSTANT 

La valeur de la variable n’est pas modifiable dans le code de la section BEGIN. 

NOT NULL 

Empêche l’affectation d’une valeur NULL à la variable, expression doit être fournie. 

expression 

Valeur initiale affectée à la variable lors de l’exécution du bloc. 

© ENI Editions - All rigths reserved - 1-


 

2. Types prédéfinis 

a. Types caractères 

CHAR[(n)] 

Chaîne de caractères de longueur fixe avec n compris entre 1 et 32767. Si aucune taille maximale n’est précisée alors 
la valeur utilisée par défaut est 1. Il faut également garder présent à l’esprit que la longueur maximale d’une colonne 
de  type  CHAR  est  2000,  et  il  est  donc  impossible  d’insérer  une  valeur  de  plus  de  2000  caractères  dans  une  telle 
colonne. 

VARCHAR2[(n)] 

Chaîne  de  caractères  de  longueur  variable  avec  n  compris  entre  1  et  32767  et  représentant  le  nombre  maximum 
d’octets  alloués  à  la  variable.  Il  faut  également  considérer  que  la  longueur  maximale  d’une  colonne  de  type 
VARCHAR2 est 4000 octets, et il est donc impossible d’insérer une valeur de plus de 4000 caractères dans une telle 
colonne. 

LONG 

Chaîne de caractères de longueur variable comprenant au maximum 32760 octets. 

RAW[(n)] 

Chaîne de caractères ou données binaires de longueur variable avec n compris entre 1 et 32767. Le contenu d’une 
variable de ce type n’est pas interprété par PL/SQL (pas de gestion des caractères nationaux). 

LONG RAW 

Identique au type LONG, mais PL/SQL n’en interprète pas le contenu. 

En  règle  générale,  un  octet  suffit  à  coder  tous  les  caractères  présents  dans  une  langue.  Mais  certaines  langues 
comme le japonais, le chinois... possèdent trop de caractères pour pouvoir tous les coder sur un octet. Oracle offre 
donc une solution pour coder ces caractères sur plusieurs octets. Le nombre d’octets dépend de la langue fixée au 
moyen de NLS (National Language Support). 

NCHAR[(n)] 

- 2- © ENI Editions - All rigths reserved


Chaîne de caractères de longueur fixe. N compris entre 1 et 32767. 

NVARCHAR2[(n)] 

Chaîne de caractères de longueur variable. N compris entre 1 et 32767. 

Le  nombre  de  caractères  effectivement  stockés  dépend  du  nombre  d’octets  utilisés  pour  coder  chaque  caractère 
dans le jeux de caractères choisi. 
UROWID, ROWID 

Permet de définir des variables dont la valeur représente l’adresse absolue de stockage d’une ligne d’une table sous 
forme d’une chaîne de caractères. 

Les valeurs de type ROWID sont composées de la façon suivante : OOOOOOFFFBBBBBBRRR et se décomposent en 
quatre parties : 
OOOOOO 

Permet de connaître le numéro de l’objet qui possède cette ligne. En effet, il est nécessaire de connaître l’objet qui 
possède la ligne d’information car, dans le cas de cluster, plusieurs objets peuvent partager le même segment. 

FFF 

Le numéro du fichier qui contient la ligne d’information. Le numéro de fichier est unique dans la base de données. 

BBBBBB 

Le  numéro  du  bloc  qui  contient  la  ligne  d’information.  Le  numéro  du  bloc  est  relatif  au  fichier  et  non  pas  au 
tablespace. 

RRR 

Permet de connaître le numéro de la ligne dans le bloc. 

Le type de données UROWID est utilisé par Oracle dans les tables qui n’ont pas de ROWID physique (par 
exemple, les tables organisées en index). 

b. Types numériques 

NUMBER[(p,s)] 

Nombres réels avec p chiffres significatifs stockés et un arrondi à droite de la marque décimale à s chiffres. 

BINARY_INTEGER 

Nombre entier compris entre ­2 147 483 647 et +2 147 483 647. 

PLS_INTEGER 

Nombre entier compris entre ­2 147 483 647 et +2 147 483 647. 

Les  variables  de  type  PLS_INTEGER  et  BINARY_INTEGER  nécessitent  moins  d’espace  mémoire  que  celles  de  type 
NUMBER. Les variables de type PLS_INTEGER et BINARY_INTEGER permettent des calculs plus rapides que celles de 
type NUMBER. 

c. Types pour les grands objets 

Les  variables  déclarées  avec  les  types  suivants  permettent  de  stocker  des  données  non  structurées  (dont  la 
structure n’est pas gérée par PL/SQL) de grande taille. 
BFILE 

© ENI Editions - All rigths reserved - 3-


Permet de stocker la référence vers un fichier du système d’exploitation qui contient physiquement les données. 

BLOB 
 
32
Permet de stocker un objet binaire jusqu’à 2 ­1 blocs Oracle.

CLOB 
 
32
Permet de stocker un ensemble de caractères, codés sur un octet, jusqu’à 2 ­1 blocs Oracle.

NCLOB 
 
32
Permet de stocker un ensemble de caractères, codés sur un octet ou plusieurs octets, jusqu’à 2 ­1 blocs Oracle.

d. Autres types 

BOOLEAN 

Stocke des valeurs logiques TRUE, FALSE ou la valeur NULL. 

DATE 

Stocke une date dans un format de longueur fixe. La plage de date valide va du 1er janvier 4712 avant JC au 31 
décembre 9999 après JC. 

TIMESTAMP 

Permet  d’étendre  le  type  DATE  en  conservant  des  fractions  de  secondes  en  plus  des  informations  de  type  année, 
mois, jour, heure, minute et seconde. Par défaut, la précision des fractions de secondes est exprimée sur 6 chiffres 
mais elle peut s’étendre de 0 à 9 chiffres. 

e. Sous­types 

PL/SQL  propose  des  sous­types  synonymes  des  types  donnés  ci­dessus.  Ces  sous­types  permettent  d’assurer  la 
compatibilité avec les types standards ANSI/ISO et IBM. 

Type ORACLE  Sous­types 

NUMBER  DEC, DECIMAL, NUMERIC, DOUBLE PRECISION, FLOAT, REAL INTEGER, INT, SMALLINT 

BINARY_INTEGER  NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE 

VARCHAR2  STRING, VARCHAR 

CHAR  CHARACTER 

3. Types définis par l’utilisateur 

PL/SQL autorise la définition de nouveaux types propres à une application. Ces types structurés permettent de définir 
des variables qui regroupent sous un nom plusieurs valeurs de même type ou de type différent. 
Pour  chaque  type  de  données  il  existe  une  plage  des  valeurs  possibles  et  un  ensemble  d’opérations  qui  travaillent 
avec  ce  type  de  données.  Les  sous­types  permettent  d’utiliser  les  mêmes  opérations  mais  la  plage  des  valeurs 
possibles est réduite. On peut donc dire que les sous­types n’introduisent pas de nouveaux types de données mais ils 
permettent au contraire de poser des contraintes sur des types de données existants. 

Le but des sous­types est de simplifier l’écriture et la compréhension du programme en utilisant des noms de types de 
données déjà connus par le programmeur ou utilisés dans l’entreprise. Par exemple, le type de données CHARACTER 
est un sous­type de CHAR pour que le langage PL/SQL respecte la norme ANSI. 
Après la définition des sous­types dans la section DECLARE du bloc PL/SQL, il est possible d’y définir des variables de 

- 4- © ENI Editions - All rigths reserved


la même façon que sur des types de base. 
Syntaxe 

SUBTYPE nom_sous_type IS type;

Exemple 
Définition et utilisation d’un sous­type : déclaration du sous­type date­naissance et utilisation dans un bloc PL/SQL. 

4. Collections et enregistrements 

Les  collections  et  les  enregistrements  ont  pour  but  de  faciliter  la  programmation  en  PL/SQL.  Ces  types  de  données 
n’existent qu’en  PL/SQL  et  ne  trouvent  pas  leur  équivalent  dans  la  base  Oracle.  Il  n’est pas possible de stocker un 
enregistrement  directement  dans  la  base  mais  par  contre,  il  est  tout  à  fait  possible  de  stocker  chaque  élément  qui 
compose l’enregistrement dans la base. 

a. Les collections 

Une collection est un ensemble ordonné d’éléments de même type. Une collection peut être comparée aux tableaux 
qu’il est possible de définir dans certains langages de programmation mais à cette différence que les collections ne 
peuvent  avoir  qu’une  seule  dimension  et  que  les  éléments  de  la  collection  sont  indexés  par  une  valeur  de  type 
numérique ou chaîne de caractères. 
Parmi  les  collections  il  faut  distinguer  deux  types  différents  :  les  tables  (TABLE)  qui  sont  de  type index  by  table ou 
nested table (qui étend les fonctionnalités offertes par les tables de type index) et les tableaux de type VARRAY. 

Après la déclaration, les collections nested table et VARRAY doivent être initialisées. Pour cela, il existe une fonction 
particulière, nommée constructeur, qui porte le même nom que la collection et qui accepte en paramètres les valeurs 
que contient initialement la collection. Attention, ce constructeur n’est pas appelé implicitement par Oracle. 

Les collections de type nested table et Index by table

Ces collections sont de taille dynamique et il n’existe pas forcément de valeurs pour toutes les positions. 

Les collections 

Comme  le  montre  le  schéma  ci­dessus,  les  collections  sont  beaucoup  plus  souples  que  les  tableaux,  car  il  est 
possible de supprimer des éléments particuliers de la collection. 
Les  collections  de  type  nested  table  présentent  la  particularité  que  les  données  qu’elles  contiennent  peuvent  être 
stockées directement dans une colonne de table, d’où leur nom. De plus, les collections non initialisées sont NULL. 
Les  collections  de  type  index­by  table  représentent  quant  à  elle  la  méthode  la  plus  rapide  pour  transférer  des 
données entre un bloc PL/SQL et la base de données. 

Syntaxes 
Déclaration d’une collection de type nested table. 

© ENI Editions - All rigths reserved - 5-


TYPE nom_type IS TABLE OF type_element [NOT NULL]

Déclaration d’une collection de type index­by table 

TYPE nom_type IS TABLE OF type_element [NOT NULL] INDEX


BY BINARY_INTEGER | VARCHAR2(n) | CHAR[(n)]

Exemple 
Déclaration  et  utilisation  de  collections  :  dans  l’exemple  ci­après,  deux  collections  sont  définies  puis  sont  utilisées  pour 
valider leur définition (l’utilisation des collections sera détaillée ultérieurement dans ce chapitre). 

Les collections de type VARRAY

Une collection de type VARRAY possède une dimension maximale qui doit être précisée lors de la déclaration de la 
collection. Ces collections possèdent une longueur fixe et donc la suppression d’éléments ne permet pas de gagner 
de la place en mémoire. Les éléments sont numérotés à partir de la valeur 1. 
Syntaxe 

TYPE nom_type IS VARRAY (taille_maxi) OF type_element


[NOT NULL]

nom_type 

Représente le nom de la collection. 

taille_maxi 

Représente le nombre maximum d’éléments présents dans la collection. 

type_element 

Représente le type de données des éléments qui constituent la collection. 

Exemple 
Déclaration et utilisation de collections : dans l’exemple suivant, une collection nommée Calendrier est définie. 

- 6- © ENI Editions - All rigths reserved


 

b. Les enregistrements 

Un enregistrement est un ensemble de valeurs liées entre elles et regroupées sous un même nom. Chaque valeur 
est  stockée  dans  un  champ.  Par  exemple,  l’enregistrement  qui  permet  de  manipuler  un  client  sera  composé  des 
champs  numéro,  nom,  adresse...  Les  enregistrements  représentent  donc  un  moyen  simple  de  manipuler  les 
informations qui sont liées entre elles. 
Pour  pouvoir  créer  un  enregistrement,  il  est  nécessaire  au  préalable,  de  définir  le  type  d’enregistrement  dans  la 
section DECLARE du bloc PL/SQL. 
Record
Un RECORD est un regroupement d’éléments de types différents logiquement liés entre eux et désignés par un nom 
unique. 
Syntaxe 

TYPE nom_type IS RECORD ([nom_champs type_champs[[NOT


NULL] := expression ]
[, ...]) ;
nom_variable nom_type ;

type_champs correspond à un type PL/SQL défini plus haut. 

Les  champs  d’une  variable  de  type  RECORD  peuvent  être  référencés  à  l’aide  de  l’opérateur  "."  : 
Nom_variable.nom_champs 

Exemple 

Définition d’un RECORD client reprenant les informations relatives à un client : 

SQL> declare
2 type T_CLIREC is record (
3 NOCLI number(4),
4 NOM char(20),
5 ADR char(20),
6 CODPOST number(5));
7 UNCLIENT T_CLIREC ;
8 begin
9 -- Instructions
10 UNCLIENT.NOCLI := 1024;
11 -- Instructions
12 end;
13 /

Procédure PL/SQL terminée avec succès.

SQL>

Comme pour la déclaration des variables, il est possible d’initialiser les champs lors de leur déclaration et de 
les rendre obligatoires ou non. 

5. Types dérivés 

© ENI Editions - All rigths reserved - 7-


À  la  déclaration  d’une  variable,  on  peut  faire  référence  à  une  entité  existante  :  colonne,  table,  curseur  ou  variable. 
Ceci est intéressant pour des raisons de simplification d’écriture et d’évolutivité des structures de données. 

%TYPE

L’attribut %TYPE permet de référencer soit une colonne d’une table, soit une variable précédemment définie. 
Syntaxe 

nom-de-variable nomdetable.nomdecolonne%TYPE;

ou 

nom-de-variable2 nomdevariable1%TYPE;

Exemple 

-- Déclaration d’une variable de même type que le nom client.


DECLARE
V_nom FLORIAN.CLIENTS.NOMCLI%TYPE ;
-- Déclaration de deux variables de même type.
x NUMBER(10,3) ;
y x%TYPE ;

%ROWTYPE
On peut référencer des structures entières de table ou de curseur afin de créer des variables qui seront composées 
de la même structure. 

Syntaxe 

nom-de-variable {nom de table | nom de curseur} %ROWTYPE ;

Exemple 

-- Déclaration d’une variable pouvant recevoir une ligne


entière de la table ARTICLES.
DECLARE
LIGART ARTICLES%ROWTYPE ;
-- A l’utilisation on pourra prendre le nom simple
SELECT * INTO LIGART ;
-- ou prendre le nom en combinaison avec la colonne
x := LIGART.prixht * 1.1 ;

6. Variables définies dans un environnement extérieur à PL/SQL 

Ces variables sont déclarées en dehors du bloc et utilisables dans le bloc. 

Ce  sont  des  champs  d’écran  créés  dans  Oracle*Forms,  ou  des  variables  définies  en  langage  hôte  par  les 
précompilateurs ou par SQL*Plus (ces variables sont toujours préfixées de ":" dans un bloc PL/SQL). 
Exemple 

Utilisation d’une variable de lien SQL*Plus (x) : 

SQL> variable x NUMBER


SQL> define t = CLIENTS
SQL> Begin
2> select COUNT(*) INTO :x from &t ;
3> end ;
4> /
Procédure PL/SQL terminée avec succès
SQL> print x
x
15
SQL>

- 8- © ENI Editions - All rigths reserved


7. Utilisation des variables 

Les  variables  sont  utilisées  soit  pour  leur  affecter  une  valeur,  soit  en  tant  qu’expression  dans  les  tests  ou  les 
modifications de données. 

a. Affectation de valeur 

Plusieurs possibilités de valorisation de variables sont possibles. 
:=

L’affectation directe de valeur. 

Syntaxe 

nom-de-variable := expression ;

L’expression  peut  être  soit  une  constante,  soit  une  variable,  soit  un  calcul  portant  sur  des  constantes  et  des 
variables. 
Les opérateurs de calcul sont les suivants : 
opérateurs arithmétiques + ; ­ ; * ; / ; **(exponentiation) 
opérateur de concaténation || 

On peut utiliser les parenthèses pour grouper les calculs. 
L’écriture des constantes suit les mêmes règles qu’en SQL. 
Exemple 
Valorisation de variables (dans la section BEGIN) : 

x := 0 ;
Vnom := ’Monsieur’|| Vnom ;
y := (x + 5) * y ;

INTO

La clause INTO des instructions SELECT et FETCH du PL/SQL permet la valorisation des variables à partir d’une ligne 
issue d’une requête (et une seule). 
Syntaxe 

SELECT {* | liste d’expression} INTO liste de variable FROM ... ;


FETCH nom curseur INTO liste de variables ;

Exemple 
Valorisation de variables à partir de tables de la base : 

DECLARE
Vref CHAR(10) ;
Vprix ARTICLES.PRIXHT%TYPE ;
Cli CLIENTS%ROWTYPE ;

BEGIN
select REFART, PRIXHT into Vref, Vprix from Articles
where DESIGNATION = ’Cadeau’ ;
select * into Cli from CLIENTS where NOCLI = 10 ;

b. Utilisation 

Les valeurs stockées dans les variables peuvent être utilisées en tant qu’expression dans les commandes SQL ou 
PL/SQL. 
Exemple 

Modification de la table CLIENTS à partir des valeurs de variables : 

© ENI Editions - All rigths reserved - 9-


DECLARE
Vnocli CLIENTS.NOCLI%TYPE := 10 ;
Vnom CLIENTS.NOM%TYPE ;

BEGIN
Vnom := ’Dupont’ ;
UPDATE CLIENTS SET NOM = Vnom where NOCLI = Vnocli ;
Vnocli := Vnocli + 1 ;
INSERT INTO CLIENTS (NOCLI, NOM) VALUES (Vnocli, Vnom) ;
COMMIT ;
END ;

c. Visibilité 

Une variable est visible dans le bloc où elle a été déclarée, et dans les blocs imbriqués si elle n’a pas été redéfinie. 

Exemple 
Test de la visibilité des variables dans des blocs PL/SQL imbriqués : 

8. Variables structurées et instruction du DML 

Il est possible d’utiliser une variable de type structuré dans une opération INSERT pour ajouter des données dans une 
table de la base depuis un bloc PL/SQL. 

Exemple 
L’exemple  ci­dessous  montre  la  mise  en  place  de  cette  possibilité  depuis  le  bloc  PL/SQL.  La  variable  structurée  vcli  est 
composée  de  champs.  Chacun  de  ces  champs  est  destiné  à  recevoir  une  valeur  d’une  colonne  de  la  table  CLIENTS.  Les 
différents champs sont renseignés puis cette variable est utilisée directement dans la commande INSERT. 

declare
vcli clients%rowtype;
begin
-- renseigner les différents champs de la variable structurée
vcli.nocli :=100;
vcli.nomcli :=’MOORE’;
vcli.adrcli :=’13 rue de la croissance’;
vcli.code_postal:=’69004’;
vcli.ville:=’LYON’;

- 10 - © ENI Editions - All rigths reserved


-- insérer ces données ds la table des clients
insert into clients values vcli;
end;
/

Le  travail  avec  les  variables  structurées  est  également  possible  pour  les  opérations  de  mise  à  jour  avec  les 
instructions UPDATE. Pour cela, la variable structurée doit contenir un champ pour chaque colonne de la table et c’est 
donc  la  totalité  de  la  ligne  qui  est  mise  à  jour  d’un  coup.  La  commande  UPDATE  utilise  alors  l’instruction  SET  ROW=  
variable composée. 

Exemple 

-- script pour la mise à jour à partir d’une variable structuré


declare
vcli clients%rowtype;
begin
-- initialiser la variable vcli
select * into vcli
from clients
where nocli=100;
-- mettre à jour les données
vcli.nomcli:=’Newton’;
-- mise à jour des informations dans la base
update clients
set row=vcli
where nocli=100;
end;
/
 
L’instruction SET ROW n’accepte pas le résultat d’une sous­requête.

Il  est  parfois  nécessaire  d’aller  lire  les  données  nouvellement  insérées,  supprimées  ou  mises  à  jour.  L’opération 
habituelle consiste à utiliser un ordre SELECT pour connaître la valeur des colonnes après mise à jour. Il est possible 
de demander aux instructions INSERT, UPDATE ou DELETE de retourner la valeur des colonnes nouvellement mises à 
jour  par  l’intermédiaire  de  la  clause  RETURNING.  Bien  sûr,  il  est  possible  d’utiliser  cette  clause  uniquement  si  la 
commande SQL DML a porté sur exactement une ligne de données. 
Exemple 
L’exemple suivant permet de connaître la valeur du prix d’un article après son augmentation de 10%. 

declare
type rec_art_info is record(
refart char(4),
prix number(8,2)
);
art_info rec_art_info;

begin
update articles set prix=prix*1.1
where refart=’AB01’
returning refart, prix into art_info;
-- art_info contient les valeurs après mise à jour
end;
/

© ENI Editions - All rigths reserved - 11 -


Structures de contrôle 
Les structures de contrôle permettent de choisir la façon dont les différentes instructions vont être exécutées. 

Les trois structures de contrôles sont : 

● la séquence : exécution d’instructions les unes après les autres. 

● l’alternative : exécution d’instructions en fonction d’une condition. 

● la répétitive : exécution d’instructions plusieurs fois en fonction d’une condition. 

1. Traitements conditionnels 

If

Il permet l’exécution d’instructions en fonction du résultat d’une condition. 
Syntaxe 

© ENI Editions - All rigths reserved - 1-


IF condition1 THEN traitement1;
[ELSIF condition2 THEN traitement2;]
[ELSE
traitement3;]
[END IF;]

Les opérateurs utilisés dans les conditions sont les mêmes que dans SQL : 
=; <, >, !, >=, <=, IS NULL, IS NOT NULL, BETWEEN, LIKE, AND, OR, etc. 

Exemple 
Si le client 10 est en cours de traitement, on le met à jour sinon on annule la transaction : 

if Vnocli = 10 THEN
UPDATE CLIENTS SET NOM = ’Dupont’ where NOCLI = Vnocli ;
COMMIT ;
else
ROLLBACK ;
end if ;

CASE
L’instruction CASE permet une exécution conditionnelle comme l’instruction IF. Cependant, cette instruction CASE est 
particulièrement bien adaptée aux conditions comportant de nombreux choix différents. Elle permet une présentation 
plus  lisible  du  code,  donc  moins  de  risque  d’erreur.  De  plus,  l’utilisation  du  CASE  est  susceptible  d’améliorer  les 
performances au cours de l’exécution. 
Syntaxe 

[<<étiquette>>]
CASE element_de_selection
WHEN valeur1 THEN instructions1;
WHEN valeur2 THEN instructions2;
...
[ELSE instructions;]
END CASE [étiquette];

[<<étiquette>>]
CASE
WHEN condition1 THEN instructions1;
WHEN condition2 THEN instructions2;
...
[ELSE instructions;]
END CASE [étiquette];

La condition ELSE est optionnelle et elle n’est exécutée que si aucune des conditions WHEN précédentes n’est 
exécutée.  En  l’absence  de  définition  de  la  condition  ELSE,  PL/SQL  ajoute  implicitement  la  condition  ELSE 
suivante : ELSE RAISE CASE_NOT_FOUND (ce qui génère une exception). 

L’instruction  CASE  peut  se  présenter  sous  deux  formes  :  dans  un  premier  cas,  soit  la  valeur  à  tester  suit 
immédiatement le CASE et c’est alors un test d’égalité qui est fait avec chaque valeur suivant les instructions WHEN 
pour  déterminer  s’il  faut  ou  non  exécuter  les  instructions  PL/SQL  associées.  Dans  sa  deuxième  forme,  chaque 
instruction WHEN est suivie d’une condition, et c’est l’évaluation de cette condition à vraie qui permet d’exécuter les 
instructions associées PL/SQL. 
Dans tous les cas, les instructions WHEN sont évaluées de façon séquentielle et seule la première évaluée à vraie est 
exécutée. 
Exemples 

L’exemple suivant permet de comparer la valeur contenue dans la variable département avec chacune des valeurs qui suit le 
WHEN. 

declare
departement number:=44;
libelle varchar2(40);
begin
case departement
when 44 then libelle:=’Loire Atlantique’;
when 49 then libelle:=’Maine et Loire’;
when 53 then libelle:=’Mayenne’;

- 2- © ENI Editions - All rigths reserved


when 72 then libelle:=’Sarthe’;
when 85 then libelle:=’Vendée’;
else libelle:=’Hors Region’;
end case;
end;
/

Dans l’exemple ci­dessous la condition de chaque instruction WHEN est évaluée pour savoir s’il est nécessaire d’exécuter ou 
non les instructions placées dernière le mot clé THEN. 

declare
departement number:=44;
region varchar2(40);
begin
case
when departement in (18,28,36,37,41,45)
then region:=’Centre’;
when departement in (75,77,78,91,92,93,94,95)
then region:=’Ile de France’;
when departement in (44,49,53,72,85)
then region:=’Pays de la loire’;
end case;
end;
/

Ce dernier exemple permet de mettre en évidence la possibilité d’imbriquer les instructions CASE les unes dans les autres. 
Avec ce type d’imbrication, il faut prendre en compte les problèmes de clarté du code. 

set serveroutput on
declare
departement number:=44;
region varchar2(80);
libelle varchar2(80);
begin
case
when departement in (18,28,36,37,41,45) then
region:=’Centre’;
when departement in (75,77,78,91,92,93,94,95) then
region:=’Ile de France’;
when departement in (44,49,53,72,85) then
region:=’Pays de la loire’;
case departement
when 44 then libelle:=’Loire Atlantique’;
when 49 then libelle:=’Maine et Loire’;
when 53 then libelle:=’Mayenne’;
when 72 then libelle:=’Sarthe’;
when 85 then libelle:=’Vendée’;
else libelle:=’Hors Region’;
end case;
end case;
dbms_output.put_line(’region:’||region);
end;
/

2. Traitements répétitifs 

Ce sont des ensembles d’instructions écrites une seule fois et exécutées à plusieurs reprises. 
LOOP

PL/SQL permet d’effectuer des traitements répétitifs grâce à la clause LOOP. 
Utilisé seul, LOOP initialise des boucles sans fin et systématiques. 

Syntaxe 

[<<LABEL>>]
LOOP
instructions;

© ENI Editions - All rigths reserved - 3-


.......
END LOOP [LABEL] ;

Sortie de la boucle par la commande : 

EXIT [LABEL] [WHEN condition]

où LABEL est le nom de la boucle et condition la condition qui doit être vraie pour la sortie. 

Exemple 
Insertion de 10 lignes dans CLIENTS : 

x := 0 ;
<<INCREMENTATION>>
LOOP
x := x + 1 ;
exit INCREMENTATION when x > 10 ;
insert into CLIENTS (NOCLI) VALUES (x) ;
END LOOP INCREMENTATION ;
COMMIT ;

L’instruction  CONTINUE  permet  d’interrompre  l’itération  en  cours  et  de  passer  immédiatement  à  la  suivante  ;  cette 
instruction est apparue en version 11. 
La syntaxe est semblable à celle de l’instruction EXIT : 

CONTINUE [LABEL] [WHEN condition]

où LABEL est le nom de la boucle et condition la condition qui doit être vraie pour que l’exécution passe à l’itération 
suivante. 
Exemple :  
Insérer uniquement des clients avec des numéros impairs. 

x := 0;
<<INCREMENTATION>>
LOOP
x := x + 1;
exit INCREMENTATION when x > 10 ;
continue INCREMENTATION when mod(x,2) = 0 ;
insert into CLIENTS (NOCLI) VALUES (x) ;
END LOOP INCREMENTATION ;
COMMIT;

FOR
La boucle FOR permet d’exécuter les instructions de la boucle en faisant varier un indice. 

Les instructions sont exécutées autant de fois que l’indice change de valeur. 
L’indice peut être utilisé dans les instructions comme une variable (en lecture). 
Syntaxe 

[<<LABEL>>]
FOR indice IN [REVERSE] exp1..exp2 LOOP
instructions;
....
END LOOP [LABEL];

L’indice est déclaré implicitement. 

exp1, exp2 sont des constantes, expressions ou variables. 

Sans l’option REVERSE, indice varie de exp1 à exp2 avec un incrément de 1. 

Avec l’option REVERSE, indice varie de exp2 à exp1 avec un incrément de ­1. 

Exemple 
Création de 10 clients avec numéros successifs : 

- 4- © ENI Editions - All rigths reserved


FOR n IN 100..110 LOOP
insert into CLIENTS (NOCLI) values (n) ;
END LOOP ;
COMMIT ;

WHILE

L’entrée dans la boucle se fait si la condition est vraie. 
Les instructions sont ensuite exécutées tant que cette condition reste vraie. 

Syntaxe 

[<<LABEL>>]
WHILE condition LOOP
instructions;
......
END LOOP [LABEL];

La condition est une combinaison d’expressions au moyen d’opérateurs : 

<, >, =, !=, AND, OR, LIKE,.. 
Exemple 

Création de 11 clients consécutifs : 

x := 200 ;
while x <= 210 LOOP
insert into CLIENTS (NOCLI) values (x) ;
x := x + 1 ;
end loop ;
COMMIT ;

© ENI Editions - All rigths reserved - 5-


Utilisation des curseurs 

1. Définition 

Le curseur est une zone de mémoire de taille fixe, utilisé par le moteur de la base Oracle pour analyser et interpréter 
tout ordre SQL. 
Les statuts d’exécution de l’ordre se trouvent dans le curseur. 

Il existe deux types de curseurs : 
Le curseur implicite 

Curseur SQL généré et géré par ORACLE pour chaque ordre SQL. 

Le curseur explicite 

Curseur SQL généré et géré par l’utilisateur pour traiter un ordre SELECT qui ramène plusieurs lignes. 

2. Étape d’utilisation d’un curseur explicite 

a. Déclaration 

Tout curseur explicite utilisé dans un bloc PL/SQL doit être déclaré dans la section DECLARE du bloc en donnant : 

● son nom, 

● l’ordre SELECT associé. 

Syntaxe 

CURSOR nom_curseur IS ordre_select;

b. Ouverture 

Après avoir déclaré le curseur, on "ouvre" celui­ci pour faire exécuter l’ordre SELECT. 
L’ouverture déclenche : 

● l’allocation mémoire du curseur, 

● l’analyse syntaxique et sémantique de l’ordre SELECT, 

● le positionnement de verrous éventuels (si SELECT ... FOR UPDATE). 

L’ouverture du curseur se fait dans la section BEGIN du bloc. 
Syntaxe 

OPEN nom_curseur;

c. Traitement des lignes 

Après l’exécution du SELECT, les lignes ramenées sont traitées une par une, la valeur de chaque colonne du SELECT 
doit être stockée dans une variable réceptrice. 
Syntaxe 

FETCH nom_curseur INTO liste_variables;

© ENI Editions - All rigths reserved - 1-


Le FETCH ramène une seule ligne à la fois ; pour traiter n lignes, il faut une boucle. 

d. Fermeture 

Après le traitement des lignes pour libérer la place mémoire, on ferme le curseur. 

Syntaxe 

CLOSE nom_curseur;

e. Curseur for 

Dans  la  mesure  où  l’utilisation  principale  d’un  curseur  est  le  parcours  d’un  ensemble  de  lignes  ramenées  par 
l’exécution du SELECT associé, il peut être intéressant d’utiliser une syntaxe plus simple pour l’ouverture du curseur 
et le parcours de la boucle. 
Oracle  propose  une  variante  de  la  boucle  FOR  qui  déclare  implicitement  la  variable  de  parcours,  ouvre  le  curseur, 
réalise les FETCH successifs et ferme le curseur. 
Syntaxe 

FOR variable IN cursor LOOP


--instructions
END LOOP;

Exemple 

Définition et parcours d’un CURSOR sur la table CLIENTS. Affichage du dernier client lu dans la table. 

SQL> variable NO_CLIENT number


SQL> variable NOM_CLIENT char(20)

SQL> declare
2 cursor c_cli is select NOCLI, NOMCLI from CLIENTS;
3 begin
4 for V_CLI in C_CLI LOOP
5 :NO_CLIENT := V_CLI.NOCLI;
6 :NOM_CLIENT := V_CLI.NOMCLI;
7 end loop ;
8 end;
9 /

Procédure PL/SQL terminée avec succès.

SQL> rem Dernier client lu dans la boucle


SQL> print NO_CLIENT

NO_CLIENT
---------
152

SQL> print NOM_CLIENT

NOM_CLIENT
------------
LAROCHE

SQL>

Il est également possible de ne pas déclarer le curseur dans la section DECLARE mais de spécifier celui­ci directement dans 
l’instruction FOR. 

SQL> variable NO_CLIENT number


SQL> variable NOM_CLIENT char(20)

SQL> begin
2 for V_CLI in (select NOCLI, NOMCLI from CLIENTS) LOOP

- 2- © ENI Editions - All rigths reserved


3 :NO_CLIENT := V_CLI.NOCLI;
4 :NOM_CLIENT := V_CLI.NOMCLI;
5 end loop ;
6 end;
7 /

Procédure PL/SQL terminée avec succès.

SQL> rem Dernier client lu


SQL> print NO_CLIENT
NO_CLIENT
---------
152

SQL> print NOM_CLIENT

NOM_CLIENT
---------------------
LAROCHE

SQL>

3. Les attributs d’un curseur 

Les attributs d’un curseur (implicite ou explicite) sont des indicateurs sur l’état d’un curseur. 
%FOUND
C’est un attribut de type booléen. 
Nom de l’attribut pour un curseur implicite : SQL%FOUND 

Il est à TRUE (vrai) si : 

● la dernière instruction INSERT, UPDATE ou DELETE a traité au moins une ligne, 

● ou si le dernier SELECT ... INTO a ramené une et une seule ligne. 

Nom de l’attribut pour un curseur explicite : nom_curseur%FOUND 

Il est à TRUE si le dernier FETCH a ramené une ligne. 
%NOTFOUND
C’est un attribut de type booléen. 

Nom de l’attribut pour un curseur implicite : SQL%NOTFOUND 

Il est à TRUE ( vrai ) si : 

● la dernière instruction INSERT, UPDATE, ou DELETE n’a traité aucune ligne, 

● ou si le dernier SELECT ... INTO n’a pas ramené de ligne (dans ce cas une exception est d’abord générée, cf. 
Gestion des erreurs dans ce chapitre). 

Nom de l’attribut pour un curseur explicite : nom_curseur%NOTFOUND 

Il est à TRUE si le dernier FETCH n’a pas ramené de ligne. 

%ISOPEN
C’est un attribut de type booléen. 

Nom de l’attribut pour un curseur implicite : SQL%ISOPEN 

Toujours à FALSE car ORACLE referme les curseurs après utilisation. 

Nom de l’attribut pour un curseur explicite : nom_curseur%ISOPEN 

Il est à TRUE si le curseur est ouvert. 

© ENI Editions - All rigths reserved - 3-


%ROWCOUNT
Il est de type numérique. 

Nom de l’attribut pour un curseur implicite : SQL%ROWCOUNT 

Il contient le nombre de lignes traitées par le dernier INSERT, UPDATE ou DELETE. 

Il est à 0 si le dernier SELECT...INTO n’a ramené aucune ligne, à 1 si le dernier SELECT... INTO a ramené exactement 1 
ligne,  ou  à  2  si  SELECT...INTO  a  ramené  plus  d’une  ligne  (mais  une  exception  est  d’abord  générée  si  le  nombre  de 
ligne retournée est différent de 1, cf. Gestion des erreurs dans ce chapitre). 

Nom de l’attribut pour un curseur explicite : nom_curseur%ROWCOUNT 

Indique le numéro de la ligne ramenée par le dernier FETCH. 

Bien entendu, tous les attributs ne sont pas testables n’importe comment. Le tableau ci­dessous indique la valeur à 
laquelle on peut s’attendre lorsque l’on teste l’un de ces attributs. 

% ISOPEN   % FOUND  %NOT FOUND  %ROWCOUNT 

OPEN  FAUX  erreur  erreur  erreur 

avant  VRAI  NULL  NULL  0 


après 

premier FETCH  VRAI  NULL  NULL  0 

avant  VRAI  VRAI  FAUX  1 


après 

FETCH  VRAI  VRAI  FAUX  1 


avant  VRAI  VRAI  FAUX  suivant les 
données 
après 

dernier FETCH  VRAI  VRAI  FAUX  suivant les 


données 
avant  VRAI  FAUX  VRAI 
suivant les 
après  données 

CLOSE  VRAI  FAUX  VRAI  suivant les 


données 
avant  FAUX  erreur  erreur 
Erreur 
après 

4. ROWNUM 

La variable ROWNUM retourne un numéro indiquant l’ordre dans lequel la ligne a été sélectionnée depuis une table. La 
première ligne sélectionnée porte le numéro 1, la deuxième le numéro 2... Si la commande SELECT, d’extraction des 
lignes, contient une clause ORDER BY, alors ROWNUM contient le numéro de la ligne avant le tri des données. 

Exemple 
Utilisation de ROWNUM : dans l’exemple suivant, la variable ROWNUM est utilisée pour extraire les trois premiers clients. 

- 4- © ENI Editions - All rigths reserved


5. Modification des valeurs d’un curseur 

La  clause  CURRENT  OF  permet  d’accéder  directement  en  modification  ou  en  suppression  à  la  ligne  que  vient  de 
ramener l’ordre FETCH. 
Il faut au préalable réserver les lignes lors de la déclaration du curseur par un verrou d’intention (... FOR UPDATE OF 
nom_col...). 

Cette fonctionnalité est très importante car la clause FOR UPDATE permet de poser un verrou d’intention, c’est­à­dire 
que les données ne peuvent pas être modifiées, par un autre utilisateur, entre le moment où les données sont lues et 
le  moment  où  les  données  sont  modifiées.  Sans  ce  verrou  d’intention,  des  modifications  peuvent  avoir  lieu  entre  la 
lecture et la mise à jour, ce qui peut avoir des conséquences non négligeables. 

De plus, la clause CURRENT OF permet de ne pas manipuler la clé primaire. 
Exemple 

Utilisation d’un curseur pour la mise à jour de chaque ligne traitée : 

Declare
CURSOR C1 is
Select REFART, PRIXHT from ARTICLES
FOR UPDATE OF PRIXHT ;
ART C1%ROWTYPE ;

BEGIN
Open C1 ;
fetch C1 into ART ;
while C1%FOUND loop
update ARTICLES set PRIXHT = ART.PRIXHT * 2
where current of C1 ;
fetch C1 into ART ;
end loop ;
commit ;
close C1 ;
END ;

6. Passage de paramètres 

Il  est  possible  de  définir  les  curseurs  avec  des  paramètres  afin  de  rendre  leur  utilisation  la  plus  souple  possible.  Le 
passage de paramètres s’effectue à l’ouverture du curseur par la commande OPEN. 
Syntaxe 
Déclaration du curseur avec paramètres : 

CURSOR nom_curseur( nom_paramètre type_donnée, ...)


IS requête_SELECT;

Ouverture du curseur paramétré et passage de la valeur des paramètres : 

OPEN nom_curseur(valeur_parametre1, ...);

Exemple 
Utilisation d’un curseur paramétré : dans l’exemple suivant, le curseur accepte en paramètre le numéro du client et permet 
de connaître les numéros des commandes passées par ce client. 

© ENI Editions - All rigths reserved - 5-


 

- 6- © ENI Editions - All rigths reserved


Gestion des erreurs 
De nombreuses erreurs peuvent survenir au cours de l’exécution. Ces erreurs peuvent être d’origine matérielle, dues à 
une faute de programmation ou de n’importe quelle autre origine. Avec certains langages de programmation, il n’est pas 
possible de gérer toute sorte d’erreur, comme la division par zéro. 

Le  langage  PL/SQL  fournit  un  mécanisme  d’interception  des  erreurs  afin  de  donner  une  réponse  logicielle  à  tout  type 
d’erreur.  Bien  sûr,  toutes  les  erreurs  ne  pourront  être  traitées  mais  il  est  possible  de  prévoir  une  sortie  propre  du 
programme quoi qu’il arrive. 
Le traitement des erreurs a lieu dans la partie EXCEPTION du bloc PL/SQL. Cette partie est optionnelle et ne doit être 
définie que si le bloc intercepte des erreurs. 

Structure d’un bloc PL/SQL : 

La  section  EXCEPTION  permet  d’affecter  un  traitement  approprié  aux  erreurs  survenues  lors  de  l’exécution  du  bloc 
PL/SQL. 
On distingue deux types d’erreurs : 

● les erreurs internes Oracle, 

● les anomalies dues au programme. 

Après  l’exécution  du  code  correspondant  au  traitement  de  l’exception,  le  bloc  en  cours  d’exécution  est  terminé,  et 
l’instruction suivante à être exécutée est celle qui suit l’appel à ce bloc PL/SQL dans le bloc maître. 
Les avantages de ce mode de gestion des erreurs sont nombreux. Le plus important est représenté par le fait que pour 
gérer  un  type  d’erreur,  le  code  ne  doit  être  écrit  qu’une  seule  fois.  Dans  les  langages  de  programmation  qui  ne 
possèdent pas ce mécanisme d’interception des erreurs, l’appel à la fonction traitant l’erreur doit être précisé à chaque 
fois que l’erreur peut se produire. 
Schéma résumant le principal avantage d’un mécanisme d’interception des erreurs : 

© ENI Editions - All rigths reserved - 1-


 

Règles à respecter

● Définir et donner un nom à chaque erreur (différent pour les erreurs utilisateur et les erreurs Oracle). 

● Associer une entrée dans la section EXCEPTION pour chaque nom d’erreur défini dans la partie DECLARE. 

● Définir le traitement à effectuer dans la partie EXCEPTION. 

La levée des exceptions ne permet pas de continuer normalement le traitement des opérations. 
Toutefois,  en  s’appuyant  sur  la  définition  de  sous­blocs  au  sein  desquels  les  exceptions  sont  gérées,  il  est  possible 
d’exécuter une suite d’instructions même si une exception est levée au cours de l’exécution d’un sous­bloc. 

1. Erreurs prédéfinies 

Toutes les erreurs Oracle possèdent un numéro d’identification unique. Mais elles ne peuvent être interceptées dans 
un bloc PL/SQL que si un nom est associé au numéro de l’erreur Oracle. Dans le langage PL/SQL, les erreurs Oracle les 
plus courantes sont associées à un nom afin de faciliter leur interception dans les blocs PL/SQL. 

La  liste  de  ces  exceptions  prédéfinies  est  donnée  ci­dessous.  Pour  traiter  les  autres  erreurs  Oracle,  il  est  toujours 
possible  d’utiliser  le  mot  clé  OTHERS  et  de  connaître  l’exception  à  l’origine  de  ce  traitement  en  faisant  appel  aux 
fonctions SQLCODE et SQLERRM. 

Exception  Erreur  Valeur de 


Oracle  SQLCODE 

ACCESS_INTO_NULL   ORA­06530  ­6530 

CASE_NOT_FOUND   ORA­06592  ­6592 

COLLECTION_IS_NULL   ORA­06531  ­6531 

CURSOR_ALREADY_OPEN   ORA­06511  ­6511 

DUP_VAL_ON_INDEX   ORA­00001  ­1 

- 2- © ENI Editions - All rigths reserved


INVALID_CURSOR   ORA­01001  ­1001 

INVALID_NUMBER   ORA­01722  ­1722 

LOGIN_DENIED   ORA­01017  ­1017 

NO_DATA_FOUND   ORA­01403  +100 

NOT_LOGGED_ON   ORA­01012  ­1012 

PROGRAM_ERROR   ORA­06501  ­6501 

ROWTYPE_MISMATCH   ORA­06504  ­6504 

SELF_IS_NULL   ORA­030625  ­30625 

STORAGE_ERROR   ORA­06500  ­6500 

SUBSCRIPT_BEYOND_COUNT   ORA­06533  06533 

SUBSCRIPT_OUTSIDE_LIMIT   ORA­06532  ­6532 

SYS_INVALID_ROWID   ORA­01410  ­1410 

TIMEOUT_ON_RESOURCE   ORA­00051  ­51 

TOO_MANY_ROWS   ORA­01422  ­1422 

VALUE_ERROR   ORA­06502  ­6502 

ZERO_DIVIDE   ORA­01476  ­1476 

Les exceptions prédéfinies appartiennent au package STANDARD,  aussi ces exceptions sont utilisables telles quelles 
dans les programmes PL/SQL 
Les exceptions sont traitées dans la partie EXCEPTION du bloc PL/SQL. À l’intérieur de cette partie, les clauses WHEN 
permettent de connaître le code à exécuter en réponse à une exception levée. 
Exemple 
Gestion  de  l’exception  Oracle  prédéfinie  TOO_MANY_ROWS  :  dans  l’exemple  ci­après,  la  partie  exception  du  bloc  PL/SQL 
permet  de  traiter  les  exceptions  qui  correspondent  à  une  tentative  de  stocker  un  ensemble  de  valeurs  dans  une  seule 
variable (TOO_MANY_ROWS). 

2. Anomalies programme utilisateur 

Si  le  programmeur  pense  qu’une  anomalie  peut  se  produire  pendant  le  traitement  (erreur  logique  ou  erreur  de 
données), il peut le prévoir comme une exception qui permettra un traitement supplémentaire si elle se produit. 

© ENI Editions - All rigths reserved - 3-


À  la  différence  des  exceptions  prédéfinies,  les  exceptions  définies  par  l’utilisateur  devront  être  déclarées  et  levées 
explicitement par l’intermédiaire de l’ordre RAISE. 

Les exceptions peuvent être définies uniquement dans la section DECLARE du bloc PL/SQL. Une exception est définie 
en précisant son nom, suivi du mot clé EXCEPTION. 

DECLARE
Depassement EXCEPTION
...

Dans l’exemple ci­dessus l’exception Depassement est définie. 
 
La déclaration des exceptions est similaire à celle des variables.

Syntaxe 

DECLARE
...
nom_erreur EXCEPTION;
...
BEGIN
...
IF(anomalie)
THEN RAISE nom_erreur;
...
EXCEPTION
WHEN nom_erreur THEN
(traitement);
END;
=> Sortie du bloc après exécution du traitement.

Exemple 
Par rapport à l’exemple précédent (curseurs), on prévoit d’arrêter et d’annuler les modifications si un prix dépasse le plafond 
fixé. 

DECLARE
CURSOR C1 ...
ART ...
Depassement EXCEPTION ;
NVPRIX NUMBER ;
BEGIN
....
while C1%FOUND LOOP
NVPRIX := ART.PRIXHT *2 ;
if NVPRIX > 10000 then raise depassement ;
update ARTICLES set PRIXHT = NVPRIX ...
fetch ...
end loop ;
...
EXCEPTION
When depassement then
rollback ;
END ;

Le  mot  clé  RAISE  permet  bien  sûr  de  lever  des  erreurs  utilisateurs  dans  la  partie  traitement  du  bloc,  mais  il  est 
également  possible  de  l’utiliser  pour  propager  des  exceptions  dans  le  bloc  appelant  après  traitement  partiel  ou 
complet d’une exception. 
En effet, une exception se propage de bloc en bloc, jusqu’à trouver un traitement qui lui est approprié dans la section 
exception.  Après  traitement  de  l’exception,  le  bloc  courant  est  quitté  pour  revenir  au  bloc  de  niveau  supérieur  sans 
erreur. Il peut parfois être nécessaire de faire remonter une exception après le traitement d’exception. Pour cela, on 
utilise le mot clé RAISE suivi du nom de l’exception à propager au bloc de niveau supérieur. 

Exemple 
Utilisation de l’instruction RAISE pour propager une erreur : dans l’exemple suivant, le bloc PL/SQL et son sous­bloc essaient 
de supprimer une commande. 

- 4- © ENI Editions - All rigths reserved


 

3. Erreurs Oracle 

Pour capturer une erreur Oracle non prédéfinie il est nécessaire, soit de travailler avec la clause WHEN OTHERS du bloc 
de traitement des exceptions, soit d’associer un nom au numéro de l’erreur Oracle que l’on souhaite capturer. Cette 
association,  nom  d’exception  et  numéro  d’erreur  Oracle,  est  possible  grâce  à  la  directive  de  compilation  PRAGMA 
EXCEPTION_INIT. 
Le nom associé à l’erreur Oracle doit être défini au préalable comme étant un nom d’exception. 
Syntaxe 

PRAGMA EXCEPTION_INIT (nom_exception,


numero_erreur_oracle)

Exemple 

Interception d’une erreur Oracle non prédéfinie : dans l’exemple  ci­après, le bloc PL/SQL traite l’erreur qui correspond à un 
verrou mortel. Un verrou mortel survient lorsque les verrous posés sur les différentes lignes modifiées par les utilisateurs 
bloquent tous les utilisateurs. Les verrous mortels sont détectés automatiquement par Oracle qui décide alors de libérer une 
transaction pour l’autoriser à saisir l’ordre ROLLBACK afin de libérer les ressources et les utilisateurs. 

Le traitement de cette exception sera donc simplement l’ordre ROLLBACK. 

© ENI Editions - All rigths reserved - 5-


 

PL/SQL  déclare  des  exceptions  prédéfinies  dans  le  package  standard.  Il  ne  faut  surtout  pas  redéfinir  ces 
exceptions, car la définition locale de l’exception masque la déclaration globale. Par exemple, si l’on définit une 
exception invalid_number associée à un code d’erreur Oracle, pour traiter l’exception prédéfinie qui porte ce nom, il 
faudra préfixer le nom de l’exception par le nom de package, soit standard.invalid_number. 

Toutes les erreurs dues au SQL ou au PL/SQL ont un code. Il est possible d’associer ce code à un nom d’exception afin 
de prendre en compte le traitement de l’erreur au niveau du bloc. 
Syntaxe 

DECLARE
...
nom_erreur EXCEPTION;
PRAGMA EXCEPTION_INIT(nom_erreur, code_erreur);
...
BEGIN
...
=>Dès qu’une erreur Oracle est rencontrée, passage
automatique à la section EXCEPTION pour réaliser le trai-
tement approprié à l’erreur
...
EXCEPTION
WHEN nom_erreur THEN
(traitement);
[WHEN OTHERS THEN (traitement);]
END;
=> Sortie du bloc après exécution du traitement

Exemple 
L’erreur 1401 signifie une valeur trop grande pour une colonne. Si elle se produit on veut tout arrêter proprement : 

Declare
...
Trop_grand EXCEPTION ;
PRAGMA EXCEPTION_INIT (Trop_Grand, -1401) ;
Begin
...
...
Exception
When Trop_grand then rollback ;
end ;

4. Portée des exceptions 

La visibilité des exceptions est similaire à celle des variables. En effet, une exception est visible dans le bloc où elle est 
définie  et  dans  tous  les  sous­blocs  de  ce  bloc.  Toutefois,  il  est  possible  de  masquer  cette  exception  dans  les  sous­
blocs en redéfinissant une exception qui porte le même nom. 

- 6- © ENI Editions - All rigths reserved


Visibilité des exceptions : 

Le  sous­bloc  ne  peut  pas  lever  l’exception  définie  dans  le  bloc  de  niveau  supérieur  car  elle  est  masquée  par  la 
définition locale. Si le bloc de niveau supérieur porte une étiquette, il est possible de lever l’exception définie au niveau 
supérieur en utilisant la syntaxe suivante : nom_du_bloc.nom_exception 

Dans l’exemple ci­avant les deux exceptions depassement sont totalement différentes et il n’existe aucun lien 
entre elles. 

5. Utilisation de raise_application_error 

Le  package  DBMS_STANDARD,  qui  est  installé  avec  Oracle,  fournit  un  ensemble  de  fonctions  et  de  procédures  qui 
facilitent  le  développement  sous  Oracle.  Par  exemple,  la  procédure  raise_application_error  permet  de  définir  des 
erreurs utilisateur depuis des sous­programmes. 

Syntaxe 

raise_application_error (numero_erreur, message[,{TRUE|FALSE}]);

numero_erreur 

représente le numéro de l’erreur utilisateur. Ce numéro doit être compris entre ­20000 et ­20999. 

message 

chaîne de caractères d’une longueur maximale de 2048 octets qui contient le message associé à l’erreur. 

Le troisième paramètre, qui est optionnel, permet de savoir si l’erreur doit être placée sur la pile des erreurs (TRUE) ou 
bien si l’erreur doit remplacer toutes les autres erreurs. C’est cette dernière solution qui est adoptée par défaut. 
Lorsque  le  bloc  PL/SQL  appelle  la  procédure  raise_application_error,  le  déroulement  de  ce  bloc  est  interrompu  et 
l’erreur est remontée au bloc appelant. Ce dernier doit traiter l’exception comme une erreur Oracle. 

Exemples 
Utilisation de raise_application_error : dans l’exemple suivant une erreur est levée si le client habite Nantes. 

© ENI Editions - All rigths reserved - 7-


 

Bloc de suppression d’un client : dans ce second exemple, on utilise le principe de gestion des exceptions pour supprimer un 
client. 

- 8- © ENI Editions - All rigths reserved


Exemple récapitulatif 
L’exemple  suivant  montre  les  syntaxes  utilisées  pour  la  gestion  des  variables,  des  curseurs  et  les  structures  de 
contrôle dans un programme complet. 

Ce programme est exécuté via SQL*Plus. 

1. Énoncé du traitement 

On veut pouvoir mettre à jour la quantité en stock de la table ARTICLES (REFART, DESIGNATION, PRIXHT, QTESTK) à 
partir  des  commandes  en  cours  (ETATCDE  =   ’EC’)  stockées  dans  les  tables  COMMANDES  (NOCDE,  NOCLI,  DATCDE, 
ETATCDE) et LIGNESCDE (NOCDE, NOLIG, REFART, QTECDE). 

Le traitement doit mettre à jour la colonne QTESTK de ARTICLES en otant les QTECDE de LIGNESCDE pour l’article. Il 
doit également y avoir mise à jour de ETATCDE à ’LI’ si toutes les quantités peuvent être livrées pour la commande 
(QTESTK > 0 après décrémentation). 

Dans le cas où la quantité en stock de l’article devient négative, les mises à jour pour cette commande sont annulées. 
Une  table  témoin  est  mise  à  jour  pour  chaque  article  à  problème  (non  livrable)  et  pour  chaque  commande  livrée 
entièrement. 

2. Exemple 

Script majliv.sql. 

rem Livraison des commandes et mise à jour des stocks


rem Création de la table TEMOIN
create table TEMOIN(nocde number(6), texte char(60));

rem Bloc PL/SQL de mise à jour


DECLARE
cursor ccde is select c.nocde, refart, qtecde
from ligcdes l,commandes c
where c.nocde=l.nocde
and c.etatcde=’EC’
order by c.nocde;
vcde ccde%rowtype;
vqtestk articles.qtestk%type;
vnvqte vqtestk%type;
vtexte temoin.texte%type;
verr boolean;
vcderef commandes.nocde%type;
BEGIN
open ccde;--Execution du curseur
fetch ccde into vcde;--Lecture de la 1re ligne
<<Bcde>>
while ccde%found loop
vcderef:=vcde.nocde;--Debut de commande
verr:=false;
vtexte:=’Problème sur article(s): ’;
commit;
<<Blig>>
while ccde%found and vcde.nocde=vcderef loop
select qtestk into vqtestk
from articles
where refart=vcde.refart;
vnvqte:=vqtestk-vcde.qtecde;
if (vnvqte>=0) then --stock OK
update articles set qtestk=vnvqte
where refart=vcde.refart;
else -- stock pas OK
verr:=true;
vtexte:=rtrim(vtexte)||rtrim(vcde.refart);
end if;

© ENI Editions - All rigths reserved - 1-


fetch ccde into vcde; --lecture ligne suivante
end loop Blig;
if verr then
rollback;
else
update commandes set etatcde=’LI’
where nocde=vcderef;
vtexte:=’Commande livre’;
end if;
insert into temoin values (vcde.nocde, vtexte);
commit;
end loop Bcde;
close ccde;

END;

/
rem Consultation de la table témoin
select * from temoin;
drop table temoin;

3. Exécution par SQL*Plus 

SQL> select * from articles;

REFA DESIGNATION PRIX CODETVA CATEGORIE QTESTK


---- ------------------------- -------- --------- ---------- ----------
AB22 Tapîs Persan 1250,1 2 IMPORT 40
CD50 2 IMPORT 1
CD21 Platine laser 500 2 IMPORT 100
ZZZZ Article bidon DIVERS 25
AA00 Cadeau 0 DIVERS 8
AB03 Carpette 150 2 SOLDES 30
AB Tapis 2 DIVERS 2
ZZ01 Lot de tapis 500 2 DIVERS 150
AB10 Tapis de chine 1500 2 IMPORT 2

9 ligne(s) sélectionnée(s).

SQL> select * from cde;

NOCDE ET REFA QTECDE


---------- -- ---- ----------
1210 EC AB10 3
1210 EC CD50 4
1250 EC AB03 8
1301 EC AB03 5
1230 EC AB10 20

SQL> @majliv
SQL> select * from temoin;

NOCDE TEXTE
---------- ----------------------------------------------------
1210 Problème sur article(s):AB10CD50
1230 Problème sur article(s):AB10
1250 Commande livrée
1301 Commande livrée

SQL> drop table temoin;

Table supprimée.

SQL> select * from articles;

REFA DESIGNATION PRIX CODETVA CATEGORIE QTESTK

- 2- © ENI Editions - All rigths reserved


---- ------------------------ -------- --------- --------- ----------
AB22 Tapîs Persan 1250,1 2 IMPORT 40
CD50 2 IMPORT 1
CD21 Platine laser 500 2 IMPORT 100
ZZZZ Article bidon DIVERS 25
AA00 Cadeau 0 DIVERS 8
AB03 Carpette 150 2 SOLDES 17
AB Tapis 2 DIVERS 2
ZZ01 Lot de tapis 500 2 DIVERS 150
AB10 Tapis de chine 1500 2 IMPORT 2

9 ligne(s) sélectionnée(s).

SQL> select * from cde;

NOCDE ET REFA QTECDE


---------- -- ---- ----------
1210 EC AB10 3
1210 EC CD50 4
1250 LI AB03 8
1301 LI AB03 5
1230 EC AB10 20

SQL> spool off

© ENI Editions - All rigths reserved - 3-


Introduction 
En  plus  des  blocs  PL/SQL  anonymes  utilisés  par  SQL*PLus  ou  par  les  outils  de  développement  (Oracle*FORMS, 
Oracle*Reports...),  on  peut  utiliser  le  PL/SQL  dans  des  objets  de  la  base,  comme  les  procédures  stockées 
(PROCEDURE, FUNCTION, PACKAGE) et les databases TRIGGER. 

© ENI Editions - All rigths reserved - 1-


Les DATABASES TRIGGERS 
Un  déclencheur  ou  trigger  est  un  bloc  PL/SQL  associé  à  une  table.  Ce  bloc  s’exécutera lorsqu’une  instruction  du  DML 
(INSERT, UPDATE, DELETE) sera demandée sur la table. 
Le  bloc  PL/SQL  qui  constitue  le  trigger  peut  être  exécuté  avant  ou  après  la  mise  à  jour  et  donc  avant  ou  après 
vérification des contraintes d’intégrité. 
Les  triggers  offrent  une  solution  procédurale  pour  définir  des  contraintes  complexes  ou  qui  prennent  en  compte  des 
données issues de plusieurs lignes ou de plusieurs tables. Par exemple, pour garantir le fait qu’un client ne peut pas 
avoir plus de deux commandes non payées. Toutefois, les triggers ne doivent pas êtres utilisés lorsqu’il est possible de 
mettre  en  place  une  contrainte  d’intégrité. En effet, les contraintes d’intégrité  étant  définies  au  niveau  de  la  table  et 
faisant partie de la structure de la table, la vérification du respect de ces contraintes est beaucoup plus rapide. De plus, 
les  contraintes  d’intégrité  garantissent  que  toutes  les  lignes  contenues  dans  la  tables  respectent  ces  contraintes, 
tandis que les triggers ne prennent pas en compte les données déjà présentes dans la table lorsqu’ils sont définis. 
Le bloc PL/SQL associé au trigger peut être exécuté pour chaque ligne affectée par l’ordre DML (option FOR EACH ROW), 
ou bien une seule fois pour chaque commande DML exécutée (option par défaut). 

Exécution avant ou après vérification des contraintes d’intégrité pour chaque ligne ou chaque ordre. 

Dans les triggers BEFORE et FOR EACH ROW, il est possible de modifier les données qui vont être insérées dans la table 
pour qu’elles respectent les contraintes d’intégrité. Il est également possible de faire des requêtes de type SELECT sur 
la  table  sur  laquelle  porte  l’ordre  DML  uniquement  dans  le  cadre  d’un  trigger  BEFORE  INSERT.  Toutes  ces  opérations 
sont  impossibles  dans  les  triggers  AFTER  car  après  vérification  des  contraintes  d’intégrité,  il  n’est  pas  possible  de 
modifier  les  données  et  comme  la  modification  (ou  ajout,  ou  suppression)  de  la  ligne  n’est  pas  terminée,  il  n’est  pas 
possible d’effectuer des SELECT sur la table. 
Il est également possible de poser des triggers sur les vues (VIEW) afin d’intercepter les ordres DML que l’on  peut  y 
exécuter. Ces triggers permettent de maîtriser toutes les opérations qui sont effectuées sur les vues et pour l’utilisateur 
final, la vue est en tout point similaire à une table puisqu’il peut y faire les opérations INSERT, UPDATE et DELETE. Ces 
triggers sont de type INSTEAD OF, c’est­à­dire que leur exécution va remplacer celle de la commande DML à laquelle ils 
sont associés. Ce type de trigger n’est définissable que sur les vues, et seul ce type de trigger peut être mis en place 
sur les vues. 

Principe de fonctionnement des triggers instead of 

Syntaxe 

CREATE [OR REPLACE] TRIGGER nom_trigger


{BEFORE/AFFTER/INSTEAD OF}
{INSERT/UPDATE[OF col,...]/DELETE}
ON nom_table [FOR EACH ROW]
[FOLLOWS nom_autre_trigger[,...]]
[ENABLE/DISABLE]
[WHEN (condition)]
Bloc PL/SQLv

© ENI Editions - All rigths reserved - 1-


OR REPLACE 

Remplace la description du TRIGGER s’il existe déjà. 

BEFORE 

Le bloc PL/SQL est exécuté AVANT la vérification des contraintes de tables et la mise à jour des données dans la table. 

AFTER 

Le bloc PL/SQL est exécuté APRES la mise à jour des données dans la table. 

INSTEAD OF 

Le bloc PL/SQL qui suit remplace le traitement standard associé à l’instruction qui a déclenché le TRIGGER (pour une vue 
uniquement). 

INSERT/UPDATE [OF col, ...]/DELETE 

Instruction associée au déclenchement du TRIGGER. Plusieurs instructions peuvent déclencher le même TRIGGER. Elles 
sont combinées par l’opérateur OR. 

FOR EACH ROW 

Le TRIGGER s’exécute pour chaque ligne traitée par l’instruction associée. 

FOLLOWS nom_autre_trigger[,...] 

Oracle  permet  de  définir  plusieurs  triggers  pour  la  même  table  et  le  même  événement.  Dans  ce  cas,  l’ordre  relatif  de 
déclenchement  de  ces  triggers  est  indéterminé.  Si  l’ordre  de  déclenchement  de  ces  triggers  est  important  pour  votre 
application,  vous  pouvez  utiliser  la  clause  FOLLOWS  apparue  en  version  11.  Cette  clause  permet  d’indiquer  que  le 
trigger doit être déclenché après les triggers mentionnés. 

ENABLE/DISABLE 

Cette clause permet d’indiquer si le trigger est actif ou non dès sa création ; par défaut, un trigger nouvellement créé 
est actif. Créer un trigger désactivé permet de vérifier qu’il se compile correctement avant de le mettre réellement en 
service. Un trigger créé désactivé peut ensuite être activé par un ordre ALTER TRIGGER … ENABLE. 

WHEN (condition) 

La condition donnée doit être vérifiée pour que le code s’exécute. 

Les  données  de  la  table  à  laquelle  est  associé  le  TRIGGER  sont  inacessibles  depuis  les  instructions  du  bloc.  Seule  la 
ligne  en  cours  de  modification  est  accessible  à  l’aide  de  deux  variables  RECORD,  OLD  et  NEW,  qui  reprennent  la 
structure de la TABLE ou de la VIEW associée. Ces variables peuvent être utilisées dans la clause WHEN du TRIGGER ou 
dans  le  bloc  d’instructions.  Dans  ce  dernier  cas,  elles  sont  référencées  comme  des  variables  hôtes  avec  le  préfixe 
":" (:OLD.nom_champs, :NEW.nom_champs). 
Le  terme  OLD  permet  de  connaître  la  ligne  en  cours  de  suppression  dans  un  trigger  DELETE  ou  la  ligne  avant 
modification  dans  un  trigger  UPDATE.  Le  terme  NEW  permet  de  connaître  la  nouvelle  ligne  insérée  dans  un  trigger 
INSERT ou la ligne après modification dans un trigger UPDATE. 
Les  termes  OLD  et  NEW  sont  fixés  par  défaut  et  il  est  possible  d’utiliser  d’autres  termes  en  précisant  la  clause 
REFERENCING OLD AS nouveau_nom NEW AS nouveau_nom. Cette clause prend place juste avant la clause FOR EACH ROW 
(si elle existe) dans la définition du trigger. 

Exemple 

Exécution d’un bloc PL/SQL avant une suppression dans la table CLIENTS du user FLORIAN : 

CREATE TRIGGER avant_sup_cli


BEFORE DELETE
ON FLORIAN.CLIENTS
DECLARE
...
BEGIN

- 2- © ENI Editions - All rigths reserved


...
END ;

Exécution d’un bloc PL/SQL après mise à jour de chaque ligne de la table ARTICLES si l’ancien prix est supérieur au nouveau : 

create or replace trigger post_majprix


after update of prix
on articles
for each row
when (old.prix > new.prix)
declare
...
begin
...
end;

Pour chaque commande on souhaite connaître le nom de l’utilisateur Oracle qui a réalisé la saisie. La première étape consiste 
à ajouter une nouvelle colonne à la table des commandes. Cette colonne doit accepter la valeur NULL car pour les lignes de 
commande existantes, le nom de l’utilisateur Oracle est inconnu. 
Modification de la table des commandes : 

SQL> alter table commandes


2 add (utilisateur varchar2(30));

Table modifiée.

SQL>

Dans le trigger, le nom de la nouvelle ligne est changé, il s’exécute avant vérification des contraintes d’intégrité pour chaque 
ligne insérée dans la table commandes. 
Définition du trigger : 

SQL> create or replace trigger bf_ins_commandes


2 before insert
3 on commandes
4 referencing new as nouvelle
5 for each row
6 begin
7 select user into :nouvelle.utilisateur from dual;
8 end;
9 /

Déclencheur créé.

SQL>

On souhaite connaître le nombre de commandes saisies par utilisateur Oracle. Pour éviter d’écrire une requête qui parcourt la 
totalité de la table des commandes, ce qui peut être très lourd, une table de statistiques va être alimentée par le trigger. 
Création de la table de statistiques : 

SQL> create table stat_util(


2 utilisateur varchar2(30),
3 nombre integer);

Table créée.

SQL>

Le trigger doit s’assurer que l’utilisateur existe dans la table des statistiques, et s’il n’est pas déjà présent alors il faut le créer. 
Le  trigger  s’exécute  après  chaque  insertion  de  ligne,  pour  des  raisons  d’optimisation  en  cas  de  violation  des  contraintes 
d’intégrité. 
Le code du trigger : 

SQL> create or replace trigger af_ins_commandes


2 after insert
3 on commandes for each row
4 declare

© ENI Editions - All rigths reserved - 3-


5 vnbre stat_util.nombre%type;
6 begin
7 -- connaitre le nombre actuel pour l’utilisateur courant
8 select nombre into vnbre
9 from stat_util
10 where utilisateur=:new.utilisateur;
11 -- mettre à jour la valeur
12 update stat_util
13 set nombre=vnbre+1
14 where utilisateur=:new.utilisateur;
15 exception
16 when no_data_found then
17 insert into stat_util (utilisateur, nombre)
18 values (:new.utilisateur,1);
19 end;
20 /

Déclencheur créé.

SQL>

L’écriture  d’un  déclencheur  peut  se  compliquer  lorsque  certains  traitements  sont  communs,  par  exemple,  aux 
instructions  INSERT  et  UPDATE  alors  que  certaines  autres  sont  spécifiques  à  l’insertion  ou  bien  à  la  mise  à  jour  des 
informations.  Une  première  solution  consiste  à  écrire  2  déclencheurs,  l’un  pour  l’instruction  INSERT  et  l’autre  pour 
l’instruction  UPDATE.  Il  en  résulte  alors  une  certaine  redondance  de  codage  ce  qui  n’est  jamais  souhaitable 
(maintenance plus lourde du code). Oracle propose les prédicats INSERTING, UPDATING et DELETING qui permettent au 
sein du déclencheur de savoir si le code PL/SQL est exécuté suite à une instruction INSERT, UPDATE ou bien DELETE. 
Ces prédicats retournent une valeur booléenne et ils sont utilisés dans la condition de test d’une instruction IF. Il est 
ainsi  possible  d’écrire  un  déclencheur  commun  aux  instructions  INSERT  et  UPDATE,  par  exemple,  tout  en  conservant 
l’exécution conditionnelle de certaines instructions. 
Exemples 
Dans l’exemple suivant, le déclencheur va être commun aux instructions INSERT et DELETE afin de maintenir à jour l’attribut 
CALCULE qui représente le nombre de commandes d’un client. 

- 4- © ENI Editions - All rigths reserved


 

L’exemple  suivant  permet  de  montrer  l’intérêt  des  déclencheurs  instead  of.  Dans  un  premier  temps  la  vue  CLINANTES  est 
créée.  Cette  vue  permet  de  connaître  les  clients  qui  habitent  Nantes.  Un  client  est  ensuite  inséré  au  travers  de  cette  vue, 
mais il ne peut pas y être retrouvé. 
Création de la vue et mise en avant de la faille : 

Un trigger de type INSTEAD OF va donc être défini pour pallier cette faille et pour garantir que les éléments insérés dans une 
vue seront visibles au travers de cette vue. 
Création du trigger et test : 

© ENI Editions - All rigths reserved - 5-


 

Trigger INSTEAD OF associé à une VIEW sur les tables COMMANDES et LIGCDES. 

SQL> create or replace view vcdelig (nocde, datecde, nolig, refart, qtecde) as
2 select l.nocde, datecde, nolig, refart, qtecde
3 from commandes c, ligcdes l
4 where c.nocde=l.nocde;

Vue créée.

SQL> create or replace trigger inst_del_vcdelig


2 instead of delete
3 on vcdelig
4 for each row
5 declare
6 vbidon number(5);
7 begin
8 delete from ligcdes
9 where nocde=:old.nocde
10 and nolig=:old.nolig;
11 -- si dernière ligne alors suprimer la commande
12 select count(*) into vbidon
13 from ligcdes
14 where nocde=:old.nocde;
15 exception
16 when no_data_found then
17 delete from commandes where nocde=:old.nocde;
18 end;
19 /

Déclencheur créé.

SQL>

En version 11, Oracle a introduit la notion de trigger composé. 
À la différence d’un trigger simple dont l’instant de déclenchement est unique (avant ou après l’instruction ou la mise à 
jour  de  ligne),  un  trigger  composé  peut  comporter  jusqu’à  quatre  sections  correspondant  chacune  à  un  instant  de 
déclenchement : avant instruction, avant chaque ligne, après chaque ligne, après instruction. 

Le  trigger  composé  présente  un  avantage  par  rapport  à  l’utilisation  de  plusieurs  triggers  séparés  :  les  différentes 
sections peuvent partager des déclarations communes (variables, types, curseurs, sous­programmes, etc.). 

Syntaxe 

CREATE [OR REPLACE] TRIGGER nom_trigger

- 6- © ENI Editions - All rigths reserved


FOR {INSERT/UPDATE[OF col,...]/DELETE}
ON nom_table
[FOLLOWS nom_autre_trigger[, ...]]
[ENABLE/DISABLE]
[WHEN (condition)]
COMPOUND TRIGGER
[déclarations_communes]
[BEFORE STATEMENT IS
[déclarations_locales]
BEGIN
instructions
END BEFORE STATEMENT]
[BEFORE EACH ROW IS
[déclarations_locales]
BEGIN
instructions
END BEFORE EACH ROW]
[AFTER EACH ROW IS
[déclarations_locales]
BEGIN
instructions
END AFTER EACH ROW]
[AFTER STATEMENT IS
[déclarations_locales]
BEGIN
instructions
END AFTER STATEMENT]
END [nom_trigger]

La clause FOR remplace la clause BEFORE/AFTER d’un trigger simple et permet de définir l’événement de déclenchement 
du trigger. 
La clause ON permet de spécifier la table concernée ; à ce niveau, la clause FOR EACH ROW du trigger simple est interdite. 

Les clauses FOLLOWS, ENABLE/DISABLE et WHEN sont les mêmes que pour un trigger simple. 

La  clause  optionnelle déclarations_communes permet de définir les déclarations communes (variables, types, curseurs, 


sous­programmes, etc.) aux différentes sections de code du trigger. 
Le  code  du  trigger  comporte  ensuite  jusqu’à  quatre  sections  de  code  correspondant  chacune  à  un  instant  de 
déclenchement ; chaque section a la structure suivante : 

instant_déclenchement IS
[déclarations_locales]
BEGIN
instructions
END instant_déclenchement

avec instant_déclenchement égal à une des clauses suivantes : BEFORE STATEMENT, BEFORE EACH ROW, AFTER STATEMENT 


et AFTER EACH ROW. 

La clause optionnelle déclarations_locale permet de définir des déclarations locales à la section de code. 

À titre d’exemple, nous allons créer un trigger qui audite les modifications de salaire des employés : 

SQL> create or replace trigger trace_modification_salaire


2 for update of salaire on employe
3 compound trigger
4 cumul number := 0;
5 procedure affiche(texte varchar2)
6 is
7 begin
8 dbms_output.put_line(texte);
9 end affiche;
10 after each row is
11 delta number;
12 begin
13 delta := :new.salaire - :old.salaire;
14 affiche(:new.noemp || ’ : ’ || delta);
15 cumul := cumul + delta;
16 end after each row;
17 after statement is

© ENI Editions - All rigths reserved - 7-


18 begin
19 affiche(’Total : ’ || cumul);
20 end after statement;
21 end trace_modification_salaire;
22 /

Déclencheur créé.

Ce  trigger  composé  définit  deux  déclarations  communes  :  une  variable  cumul  pour  stocker  le  montant  cumulé  des 
modifications de salaire et une procédure affiche pour afficher une information à l’écran. 

Dans la section after each row, le trigger calcule la variation de salaire pour la ligne en cours, stocke cette valeur dans 


une variable locale à la section (delta), puis l’affiche avant de l’ajouter à la variable globale cumul. 

Dans la section after statement, le trigger se contente d’afficher la valeur de la variable globale cumul. 

Nous pouvons maintenant tester ce trigger : 

SQL> set serveroutput on


SQL> select NOEMP,SALAIRE from EMPLOYE;

NOEMP SALAIRE
---------- ----------
1 1200
2 1800

SQL> update EMPLOYE set SALAIRE = SALAIRE * 1.01;


1 : 12
2 : 18
Total : 30

2 ligne(s) mise(s) à jour.

- 8- © ENI Editions - All rigths reserved


Les triggers sur des événements système ou utilisateur 
Il est possible d’utiliser les triggers pour suivre les changements d’état du système, tels que l’arrêt et le démarrage. Ces 
triggers vont permettre d’améliorer la gestion de la base et de l’application. En effet, certains événements systèmes ou 
utilisateurs ont un impact direct sur les performances de l’application et/ou la cohérence des données. 

Les  événements  système  sont  l’arrêt  et  le  démarrage  de  l’instance  Oracle  (startup  et  shutdown)  et  la  gestion  des 
erreurs. Les triggers d’arrêt et de démarrage ont comme portée l’ensemble de l’instance Oracle, tandis que le trigger de 
gestion des erreurs peut être défini soit au niveau du schéma soit au niveau de la base de données. 
Au niveau de l’utilisateur, des triggers peuvent exister pour ses opérations de connexion et de déconnexion (logon et 
logoff), pour surveiller et contrôler l’exécution des ordres du DDL (CREATE, ALTER et DROP) et du DML (INSERT, UPDATE 
et DELETE). 

Les  triggers  DML  sont  associés  à  une  table  et  à  un  ordre  du  DML,  leur  définition  et  utilisation  a  été  détaillée 
précédemment dans ce chapitre. 

Lors  de  l’écriture  de  ces  triggers,  il  est  possible  d’utiliser  des  attributs  pour  identifier  précisément  l’origine  de 
l’événement et adapter les traitements en conséquence. 

1. Les attributs 

ora_client_ip_address 

Permet de connaître l’adresse IP du poste client à l’origine de la connexion. 

ora_database_name 

Nom de la base de données. 

ora_des_encrypted_password 

Permet de connaître les descripitions codées du mot de passe de l’utilisateur qui vient d’être créé ou modifié. 

ora_dict_obj_name 

Nom de l’objet sur lequel l’opération du DDL vient d’être exécutée. 

ora_dict_obj_name_list 

Permet de connaître la liste de tous les noms d’objet qui ont été modifiés. 

ora_dict_obj_owner 

Propriétaire de l’objet sur lequel l’opération du DDL a porté. 

ora_dict_obj_owner_list 

Permet de connaître la liste de tous les propriétaires des objets qui ont été modifiés. 

ora_dict_obj_type 

Type de l’objet atteint par la dernière opération DDL. 

ora_grantee 

Permet de connaître les utilisateurs qui possèdent ce privilège. 

ora_instance_num 

Numéro de l’instance. 

© ENI Editions - All rigths reserved - 1-


ora_is_alter_column 

Retourne Vrai si la colonne passée en paramètre a été modifiée. 

ora_is_creating_nested_table 

Permet de savoir si une table de fusion a été créée. 

ora_is_drop_column 

Permet de savoir si la colonne passée en paramètre a été modifiée. 

ora_is_servererror 

Retourne Vrai si le numéro de l’erreur passée en paramètre se trouve dans la pile des erreurs. 

ora_login_user 

Permet de connaître le nom de connexion. 

ora_privileges 

Permet de connaître la liste des privilèges accordés ou retirés par un utilisateur particulier. 

ora_revokee 

Permet de connaître les utilisateurs à qui le privilège a été enlevé. 

ora_server_error 

Retourne le numéro de l’erreur Oracle dans la pile dont la position lui est passée en paramètre (le sommet de la pile 
occupe la position 1). 

ora_sysevent 

Nom de l’événement système qui a déclenché le trigger. 

ora_with_grant_option 

Retourne Vrai si le privilège a été accordé avec une option d’administration. 

2. Les événements système 

STARTUP 

L’événement est déclenché lors de l’ouverture de l’instance. 

SHUTDOWN 

L’événement est déclenché juste avant que le serveur ne commence le processus d’arrêt de l’instance. Lors d’un arrêt 
brutal du serveur de base de données, cet événement ne sera pas exécuté. 

SERVERERROR 

L’événement  est  déclenché  lorsqu’une  erreur  Oracle  se  produit.  Cependant,  ce  trigger  n’est  pas  déclenché  pour  les 
erreurs  ORA­1034,  ORA­1403,  ORA­1422,  ORA­1423  et  ORA­4030  qui  sont  trop  importantes  pour  que  le  processus 
puisse continuer à s’exécuter. 

Syntaxe 

Create trigger nom_trigger {AFTER|BEFORE} evenement_systeme


ON{DATABASE|SCHEMA}
Bloc PL/SQL

- 2- © ENI Editions - All rigths reserved


Seuls  les  triggers  AFTER  existent  pour  les  événements  STARTUP  et  SERVERERROR  et  seul  le  trigger  BEFORE 
existe pour l’événement SHUTDOWN. 

Exemple 

Mise  en  place  d’un  trigger  de  gestion  des  erreurs  :  dans  l’exemple  ci­après,  les  informations  concernant  chaque  erreur 
provoquée sur le schéma de l’utilisateur  qui  crée  le  trigger  sont  enregistrées  dans  la  table  les_erreurs  qui  a  été  créée  au 
préalable. 

3. Les événements utilisateur 

AFTER LOGON 

Après avoir établi une connexion avec le serveur. 

BEFORE LOGOFF 

Avant de rompre la connexion avec le serveur. 

BEFORE CREATE, AFTER CREATE 

Lorsqu’un objet est créé. 

BEFORE ALTER, AFTER ALTER 

Lorsqu’un objet est modifié. 

BEFORE DROP, AFTER DROP 

Lorsqu’un objet est supprimé. 

BEFORE ANALYZE, AFTER ANALYZE 

Quand un ordre d’analyse est exécuté. 

BEFORE ASSOCIATE STATISTICS AFTER ASSOCIATE STATISTICS 

Quand une association de statistiques est exécutée. 

BEFORE AUDIT, AFTER AUDIT 

Lorsqu’un audit est mis en place. 

BEFORE NOAUDIT, AFTER NOAUDIT 

Lorsqu’une opération d’audit est annulée. 

BEFORE COMMENT, AFTER COMMENT 

© ENI Editions - All rigths reserved - 3-


Lors de la pose d’un commentaire. 

BEFORE DDL, AFTER DDL 

Lors  de  l’exécution  de  la  plupart  des  ordres  du  DDL  à  l’exception  des  commandes  ALTER  DATABASE,  CREATE 
CONTROLFILE, CREATE DATABASE ainsi que toutes les commandes du DDL issues d’un bloc PL/SQL. 

BEFORE DISSOCIATE STATISTICS AFTER DISSOCIATE STATISTICS 

Lors de la dissociation des statistiques d’un objet. 

BEFORE GRANT, AFTER GRANT 

Lors de l’exécution de la commande GRANT. 

BEFORE RENAME, AFTER RENAME 

Lors de l’exécution de la commande RENAME. 

BEFORE REVOKE, AFTER REVOKE 

Lors de l’exécution de la commande REVOKE. 

BEFORE TRUNCATE, AFTER TRUNCATE 

Lors de la troncature d’une table. 

Syntaxe 

Create trigger nom_trigger {AFTER|BEFORE}


evenement_utilisateur ON{DATABASE|SCHEMA}
Bloc PL/SQL
 

Il faut consulter la liste ci­dessus pour savoir si l’événement peut être traité en BEFORE et ou en AFTER.

Exemple 
Mise  en  place  d’un  trigger  de  surveillance  des  tables  :  dans  l’exemple  suivant,  le  trigger  mis  en  place  permet  de  scruter 
toutes les créations de table. Tous les renseignements sont stockés dans la table INFOS_TABLE qui a été créée auparavant. 

- 4- © ENI Editions - All rigths reserved


Les modifications de triggers 
Il n’est pas possible de modifier un trigger de base de données. Par contre, il est possible de le supprimer puis de le 
récréer ou bien de le créer avec l’option OR REPLACE. 
La commande ALTER TRIGGER va permettre en réalité de désactiver puis de réactiver les triggers. La désactivation peut 
être envisagée lors d’un import massif de données ou bien d’une modification de grande envergure. 
La désactivation et la réactivation de trigger peuvent être réalisées trigger par trigger ou bien table par table. En effet, 
la commande ALTER TABLE permet l’activation et la désactivation de tous les triggers posés sur la table. 
Syntaxe 

ALTER TRIGGER nom_trigger {ENABLE|DISABLE};


ALTER TABLE nom_trigger { ENABLE|DISABLE } ALL TRIGGERS;

Exemple 

Désactivation puis réactivation de triggers : 

Pour obtenir des informations sur les triggers il faut interroger le dictionnaire de données. Les trois vues du dictionnaire 
à utiliser sont : USER_TRIGGERS, ALL_TRIGGERS et DBA_TRIGGERS. 
La colonne BASE_OBJECT_TYPE permet de savoir si le trigger est basé sur une table, une vue, un schéma ou la totalité 
de la base de données. 
La  colonne  TRIGGER_TYPE  permet  de  savoir  s’il  s’agit  d’un  trigger  BEFORE,  AFTER  ou  INSTEAD  OF,  si  son  mode 
d’exécution est FOR EACH ROW ou non, s’il s’agit d’un trigger événementiel ou non. 
La colonne TRIGGERING_EVENT permet de connaître quel événement est concerné par le trigger. 
Exemple 

Interrogation du dictionnaire : dans l’exemple suivant, la vue USER_TRIGGERS est interrogée pour connaître les déclencheurs 
posés sur le schéma de l’utilisateur courant. 

© ENI Editions - All rigths reserved - 1-


- 2- © ENI Editions - All rigths reserved
Les procédures stockées 
Une procédure stockée est un bloc de code PL/SQL nommé stocké dans la base de données et qui peut être exécuté à 
partir des applications ou d’autres procédures stockées. Dans un bloc PL/SQL, il suffit de référencer la procédure par 
son nom pour l’exécuter. À partir de l’outil SQL*Plus, on peut utiliser l’instruction EXECUTE. 
Syntaxe 

CREATE [OR REPLACE] PROCEDURE nom procédure


[(paramètre {IN/OUT/IN OUT} type, ...)]
{IS/AS} bloc PL/SQL ;

OR REPLACE 

Remplace la description si la procédure existe. 

paramètre 

Variable passée en paramètre, utilisable dans le bloc. 

IN 

Le paramètre est passé en entrée de procédure. 

OUT 

Le paramètre est valorisé dans la procédure et renvoyé à l’environnement appelant. 

type 

Type de variable (SQL ou PL/SQL). 

Exemple 
Procédure de suppression d’un article : 

SQL> create or replace procedure supp_art (numero in char) is


2 begin
3 delete from ligcdes where refart=numero;
4 delete from articles where refart=numero;
5 end;
6 /

Procédure créée.

SQL>

Utilisation par SQL*Plus : 

SQL> EXECUTE supp_art (’AB01’) ;


utilisation dans un bloc PL/SQL

Utilisation dans un bloc PL/SQL. 

DECLARE
x char ;
BEGIN
...
supp_art (x) ;
...
END ;

© ENI Editions - All rigths reserved - 1-


Les fonctions stockées 
Comme  les  procédures,  une  fonction  est  un  ensemble  de  code  PL/SQL,  mais  la  fonction  renvoie  une  valeur.  Ces 
fonctions stockées seront utilisées comme les fonctions ORACLE. 

Syntaxe 

CREATE [OR REPLACE] FUNCTION nom de fonction


[(paramètre [IN] type, ...)]
RETURN type {IS/AS} Bloc PL/SQL ;

OR REPLACE 

La description est remplacée si la fonction existe. 

Paramètre 

Paramètre passé en entrée utilisé comme une variable dans le bloc. 

type 

Type du paramètre (SQL ou PL/SQL). 

RETURN type 

Type de la valeur retournée par la fonction. 

Exemple 

Fonction factorielle : 

CREATE FUNCTION factorielle (n IN NUMBER)


RETURN NUMBER
IS BEGIN
if n = 0 then
return (1) ;
else
return ((n * factorielle (n-1))) ;
end if ;
END ;

Utilisation par SQL*Plus : 

SQL> Select factorielle (5) from DUAL ;


FACTORIELLE (5)
---------------
120
SQL>

Depuis la version 11, il est possible d’indiquer à Oracle de conserver en mémoire le résultat de l’appel d’une fonction. 
Lorsque  cette  fonctionnalité  est  activée  pour  une  fonction,  à  chaque  fois  que  celle­ci  est  appelée  avec  des  valeurs 
différentes  des  paramètres,  Oracle  stocke  en  cache  la  valeur  des  paramètres  et  le  résultat  de  la  fonction.  Lorsque 
cette fonction est de nouveau appelée ultérieurement avec les mêmes valeurs de paramètres, le résultat est retourné 
à partir du cache au lieu d’être recalculé. 
Pour  activer  cette  fonctionnalité  pour  une  fonction,  il  suffit  d’inclure  la  clause  RESULT_CACHE  dans  la  définition  de  la 
fonction. 
Syntaxe 

RESULT_CACHE [RELIES_ON (nom_table_ou_vue[,...])]

La clause optionnelle RELIES_ON permet de spécifier une ou plusieurs tables ou vues dont la fonction dépend. Lorsque 
les données sont modifiées dans les tables concernées, le cache est invalidé puis reconstitué lors des appels ultérieurs 
de la fonction. 

Exemple 

© ENI Editions - All rigths reserved - 1-


SQL> create or replace function valeur_parametre(n in number)
2 return varchar2
3 result_cache relies_on (parametres)
4 is
5 resultat varchar2(40);
6 fin timestamp;
7 begin
8 -- code qui simule un temps d’exécution long
9 fin := systimestamp + 2/24/60/60;
10 while systimestamp < fin
11 loop
12 null;
13 end loop;
14 -- sélectionner et retourner la valeur demandée
15 select valeur into resultat from parametres where code = n;
16 return resultat;
17 end;
18 /

Fonction créée.

SQL> set timing on


SQL> select valeur_parametre(1) from dual;

VALEUR_PARAMETRE(1)
-------------------------------------------
ENI

Ecoulé : 00 :00 :01.62


SQL> select valeur_parametre(1) from dual;

VALEUR_PARAMETRE(1)
-------------------------------------------
ENI

Ecoulé : 00 :00 :00.15


SQL> insert into parametres(code,valeur)
2 values(123,’UN DEUX TROIS’);

1 ligne créée.

Ecoulé : 00 :00 :00.12


SQL> commit;

Validation effectuée.

Ecoulé : 00 :00 :00.10


SQL> select valeur_parametre(1) from dual;

VALEUR_PARAMETRE(1)
-------------------------------------------
ENI

Ecoulé : 00 :00 :01.60


SQL> select valeur_parametre(1) from dual;

VALEUR_PARAMETRE(1)
-------------------------------------------
ENI

Ecoulé : 00 :00 :00.17

Lors  du  premier  appel  avec  1  comme  valeur  du  paramètre,  la  fonction  retourne  le  résultat  en  un  peu  plus  de  1,5 
secondes. Lors du deuxième appel avec la même valeur du paramètre, la fonction ne met plus que 15 centièmes de 
seconde  pour  s’exécuter.  Après  modification  des  données  de  la  table,  un  nouvel  appel  avec  1  comme  valeur  du 
paramètre s’exécute de nouveau en un peu plus de 1,5 secondes : le cache de résultat a été invalidé car la fonction 
dépend de la table modifiée (clause RELIES_ON). 

- 2- © ENI Editions - All rigths reserved


L’administrateur  de  la  base  de  données  dispose  de  plusieurs  paramètres  pour  régler  le  fonctionnement  du 
cache de résultat. 

© ENI Editions - All rigths reserved - 3-


Les packages 
Un  package  est  un  objet  du  schéma  qui  regroupe  logiquement  des  éléments  PL/SQL  liés,  tels  que  les  types  de 
données, les fonctions, les procédures et les curseurs. 

Les packages se divisent en deux parties : un en­tête ou spécification et un corps (body). La partie spécification permet 
de décrire le contenu du package, de connaître le nom et les paramètres d’appel des fonctions et des procédures. Mais 
le  code  n’est pas présent dans la spécification. On trouve le code dans la partie body du package. Cette séparation 
des spécifications et du code permet de déployer un package sans que l’utilisateur puisse visualiser le code et permet 
de plus de faire évoluer simplement le code pour répondre à de nouvelles règles. 

Les packages offrent de nombreux avantages : 
Modularité 

Le fait de regrouper logiquement les éléments PL/SQL liés rend plus facile la compréhension des différents éléments du 
package et leur utilisation en est simplifiée. 

Simplification du développement 

Lors  de  la  mise  en  place  d’une  application,  il  est  possible  dans  un  premier  temps  de  définir  uniquement  la  partie 
spécification  des  packages  et  réaliser  ainsi  les  compilations.  Le  corps  du  package  ne  sera  nécessaire  que  pour 
l’exécution de l’application. 

Informations cachées 

Avec  un  package,  il  est  possible  de  rendre  certains  éléments  invisibles  à  l’utilisateur  du  package.  Cela  permet  de 
construire  des  éléments  qui  ne  peuvent  être  utilisés  qu’à  l’intérieur  du  package  et  donc  l’écriture  du  package  s’en 
trouve simplifiée. 

Ajout de fonctionnalités 

Les  variables  et  curseurs  publics  du  package  existent  durant  la  totalité  de  la  session,  donc,  il  est  possible  par  cet 
intermédiaire de partager des informations entre les différents sous­programmes d’une même session. 

Amélioration des performances 

Le package est présent en mémoire dès le premier appel à un élément qui le compose. L’accès aux différents éléments 
du package est donc beaucoup plus rapide que l’appel à des fonctions et à des procédures indépendantes. 

1. En­tête 

La portée de tous les éléments définis dans la spécification du package est globale pour le package et locale pour le 
schéma de l’utilisateur. 

La spécification permet de préciser quelles seront les ressources du package utilisable par les applications. Toutes les 
informations  pour  savoir  comment  utiliser  les  ressources  du  package  (paramètres  d’appel,  type  de  la  valeur 
renvoyée) doivent être présentes dans cette spécification. 
Syntaxe 

CREATE PACKAGE nom_package AS


--Définition de type
--Déclarations de variables publiques
--Prototypes des curseurs publiques
--Prototypes des PROCEDUREs et FUNCTIONs publiques
END [nom_package];

Exemple 
En­tête d’un package de gestion des clients : 

SQL> create or replace package GESTION_CLIENTS as


2 type T_CLIREC is record (
3 NOCLI number(4),
4 NOM char(20),
5 ADR char(20),

© ENI Editions - All rigths reserved - 1-


6 CODPOST number(5),
7 VILLE char(30));
8 cursor C_CLIENTS return T_CLIREC;
9 function CRE_CLI (NOM char, ADR char, CODPOST number,
10 VILLE char)
11 return number;
12 procedure SUPP_CLI (NOCLIENT number);
13 end GESTION_CLIENTS;
14 /

Package créé.

SQL>

2. Corps du package 

Le  corps  du  PACKAGE  contient  l’implémentation  des  procédures  et  fonctions  exposées  dans  la  partie  en­tête.  Il 
contient également des définitions de types et des déclarations de variables dont les portées sont limitées au corps 
du PACKAGE. 

La spécification du corps du PACKAGE n’est pas nécessaire si l’en­tête du PACKAGE ne comporte que des 
définitions de types et des déclarations de variables. 

Pour  s’assurer  que  dans  le  corps  du  package  tous  les  éléments  précisés  dans  la  spécification  sont  bien  définis, 
PL/SQL  effectue  une  comparaison  point  par  point.  Aussi,  à  l’exception  des  espaces,  la  déclaration  faite  dans  la 
spécification doit trouver son équivalent exact dans le corps. Si ce n’est pas le cas, une exception est levée lors de la 
compilation. 
Le  corps  du  package  peut  en  plus  contenir  des  définitions  locales  de  curseurs,  variables,  types,  fonctions  et 
procédures  pour  une  utilisation  à  l’intérieur  du  package.  Ces  élément  ne  seront  pas  accessibles  en  dehors  du 
package. 

Syntaxe 

CREATE PACKAGE BODY nom_package AS


--Définitions de type locaux au package
--Déclarations de variables locales au package
--Implémentation des curseurs publics
--Corps des PROCEDUREs et FUNCTIONs locales au package
--Corps des PROCEDUREs et FUNCTIONs publiques
END [nom_package];

Exemple 

Corps du package de gestion des clients : 

SQL> create or replace package body GESTION_CLIENTS as


2 NOMBRE_CLI integer; -- Définition d’une variable locale
3
4 -- Implémentation du curseur
5 cursor C_CLIENTS return T_CLIREC is
6 select NOCLI, NOMCLI, ADRCLI, CODE_POSTAL, VILLE
7 from CLIENTS
8 order by NOCLI;
9
10 -- Fonction de création d’un nouveau client
11 function CRE_CLI (NOM char, ADR char, CODPOST number
12 , VILLE char)
13 return number
14 is
15 NOUV_NOCLI number;
16 begin
17 select S_NOCLI.nextval into NOUV_NOCLI from DUAL;
18 insert into CLIENTS
19 values(NOUV_NOCLI, NOM, ADR, CODPOST, VILLE);
20 NOMBRE_CLI := NOMBRE_CLI + 1;
21 return NOUV_NOCLI;

- 2- © ENI Editions - All rigths reserved


22 end;
23
24 -- Procédure de suppression d’un client
25 procedure SUPP_CLI (NOCLIENT number)
26 is
27 begin
28 delete from CLIENTS where NOCLI = NOCLIENT;
29 end;
30 end GESTION_CLIENTS;
31 /

Corps de package créé.

SQL>

3. Utilisation 

Les  éléments  d’un  package  (variables,  procédures,  fonctions)  sont  référencés  par  rapport  au  nom  du  PACKAGE  à 
l’aide de l’opérateur ".". 
Exemple 

Utilisation du package de gestion des clients : 

SQL> var V_NOCLI number

SQL> begin
2 :V_NOCLI := GESTION_CLIENTS.CRE_CLI
3 (’CESAR’, ’Vieux Port’, 13000, ’MARSEILLE’);
4 end;
5 /

Procédure PL/SQL terminée avec succès.


SQL> print V_NOCLI

V_NOCLI
---------
2003

SQL> select NOCLI, ltrim(NOMCLI) NOMCLI, VILLE


2 from CLIENTS order by NOCLI
3 /

NOCLI NOMCLI VILLE


--------- ------------------------------ --------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
36 BERNARD S.A. PARIS
138 DUBOIS Jean TOURS
152 LAROCHE LE MANS
1000 DUPOND et DUPONT LILLE
1001 DURAND et DURANT TOURCOING
2003 CESAR MARSEILLE

9 ligne(s) sélectionnée(s).

SQL> begin
2 GESTION_CLIENTS.SUPP_CLI(152);
3 end;
4 /

Procédure PL/SQL terminée avec succès.

SQL> select NOCLI, ltrim(NOMCLI) NOMCLI, VILLE


2 from CLIENTS order by NOCLI
3 /

© ENI Editions - All rigths reserved - 3-


NOCLI NOMCLI VILLE
--------- ------------------------------ -------------------
15 DUPONT S.A. NANTES
20 Etb LABICHE NANTES
35 DUBOIS Jean NANTES
36 BERNARD S.A. PARIS
138 DUBOIS Jean TOURS
1000 DUPOND et DUPONT LILLE
1001 DURAND et DURANT TOURCOING
2003 CESAR MARSEILLE

8 ligne(s) sélectionnée(s).

SQL>

4. Les curseurs 

Il  est  possible  de  séparer  la  déclaration  d’un  curseur  (sa  spécification)  de  sa  définition  (son  corps).  Avec  cette 
technique, il devient alors possible de changer la définition du curseur sans que sa déclaration ne soit modifiée. La 
déclaration du curseur dans la partie spécification du package doit respecter la syntaxe suivante : 

CURSOR nom_curseur [(paramètre, ...)] RETURN


type_valeur_renvoyée
 

La valeur retournée est, soit une valeur simple soit un enregistrement.

Dans le corps du package, il est maintenant obligatoire de définir la clause SELECT associée au curseur. Bien sûr, les 
colonnes  précisées  derrière  la  clause  SELECT  et  le  type  de  données  indiqué  comme  étant  retourné  dans  la  partie 
spécification doivent correspondre exactement. 

La définition des curseurs à l’intérieur du package offre plus de souplesse car il est possible de changer leur définition 
sans pour autant être obligé de modifier la partie spécification du package. 

Pour utiliser un curseur défini dans un package, il faut, dans un bloc PL/SQL, faire préfixer le nom du curseur par celui 
du package. La notation est la même que celle mise en place pour appeler des fonctions ou des procédures définies 
dans un package. 

La  portée  d’un  curseur  de  package  n’est  pas  limitée  au  seul  bloc  dans  lequel  il  est  ouvert.  Il  est  ainsi  possible  de 
conserver le curseur ouvert pendant toute une session et de le fermer simplement lors de la déconnexion. 

- 4- © ENI Editions - All rigths reserved


Les transactions autonomes 
Une  transaction  est  un  ensemble  d’ordres  SQL  qui  constitue  une  unité  logique  de  traitement.  Soit  la  totalité  des 
instructions de l’unité est exécutée avec succès soit aucune instruction n’est exécutée. Dans certaines applications, une 
transaction doit s’exécuter à l’intérieur d’une autre transaction. 

Un transaction autonome est une transaction indépendante qui est lancée depuis une autre transaction : la transaction 
principale. Durant l’exécution de la transaction autonome, la transaction principale est suspendue. 

Les  transactions  autonomes  sont  totalement  indépendantes,  et  cette  indépendance  permet  de  construire  des 
applications  plus  modulaires.  Bien  sûr,  les  transactions  autonomes  présentent  les  mêmes  caractéristiques  que  les 
transactions régulières. 
Pour définir une transaction autonome, il faut utiliser la directive de compilation (pragma) AUTONOMOUS_TRANSACTION. 
Cette directive doit apparaître dans la section de déclaration des variables, des blocs PL/SQL anonymes, des fonctions, 
des procédures et des triggers. En règle générale, les directives de compilation sont placées en début de la section de 
déclaration des variables, ce qui facilite la relecture du programme. 

Il  n’est  pas  possible  de  placer  la  directive  de  compilation  pragma  AUTONOMOUS_TRANSACTION  au  niveau  du 
package.  Par  contre,  chaque  fonction  et  procédure  du  package  peut  être  déclarée  en  tant  que  transaction 
autonome. 

Exemple 
Procédure définissant une transaction autonome : dans l’exemple suivant, la fonction de mise à jour des clients constitue une 
transaction autonome. 

Les modifications réalisées par la transaction autonome sont visibles des autres transactions immédiatement après sa 
validation  (COMMIT),  même  si  la  transaction  principale  qui  a  appelé  la  transaction  autonome  n’est  pas  terminée.  Les 
modifications  seront  également  visibles  par  la  transaction  principale.  Pour  que  la  transaction  principale  ne  puisse  pas 
connaître les modifications, il faut préciser le niveau d’isolation de la transaction à l’aide de la commande suivante : SET 
TRANSACTION ISOLATION LEVEL SERIALIZABLE. 
Les  transactions  autonomes  sont  contrôlées  par  les  ordres  COMMIT,  ROLLBACK  et  SAVEPOINT.  À  l’intérieur  d’un  bloc 
PL/SQL  défini  comme  transaction  autonome,  il  est  possible  de  réaliser  plusieurs  transactions  les  unes  à  la  suite  des 
autres. Pour la transaction principale appelante, c’est l’ensemble des transactions du bloc appelé qui est autonome. 

Exemple 
Procédure définissant une transaction autonome : dans l’exemple ci­après, la procédure de mise à jour des clients est appelée 
depuis un bloc PL/SQL anonyme, dont la transaction est annulée. On constate que le travail de la procédure reste validé. 

© ENI Editions - All rigths reserved - 1-


 

Il  est  également  possible  de  définir  les  triggers  comme  réalisant  des  transactions  autonomes.  Cette  option  est 
intéressante  lorsque  l’on  utilise  les  triggers  pour  journaliser  les  opérations  qui  interviennent  sur  une  table,  même  si 
l’opération n’est pas validée. Le fait que le trigger soit autonome permet d’assurer que le travail réalisé sera enregistré 
dans la base de données, même si l’opération à l’origine de l’exécution du trigger est annulée (ROLLBACK). 
De  plus,  contrairement  aux  triggers  traditionnels,  les  triggers  autonomes  peuvent  exécuter  des  ordres  SQL  DDL  en 
utilisant des ordres SQL Dynamique. 

La clause RETURNING

Dans le cas où l’instruction INSERT est utilisée pour insérer une seule ligne d’informations dans la table, il est possible 
d’utiliser la clause RETURNING pour connaître par exemple la valeur d’une colonne ou bien le résultat d’un calcul. Cette 
fonctionnalité s’avère particulièrement pratique lorsqu’une séquence est associée à la colonne et que la valorisation de 
la colonne à partir de la séquence est réalisée depuis un déclencheur de base de données. 

La clause RETURNING permet de connaître la valeur qui a été générée et insérée dans la table. Sans cette clause, les 
accès à la base sont multipliés pour connaître la valeur affectée à la colonne. 
Syntaxe 

INSERT INTO table[(colonne, ...)] VALUES (expression, ...)


RETURNING colonne INTO variable

Exemple 
Dans l’exemple suivant, une fonction de création des clients est mise en place. Cette fonction utilise une séquence oracle pour 
fixer le numéro de clients. La valeur du numéro de client est retournée par la fonction. 

Il est également possible d’utiliser cette clause RETURNING dans une instruction DELETE afin d’obtenir une ou plusieurs 
informations sur la ligne supprimée. 

- 2- © ENI Editions - All rigths reserved


Syntaxe 

DELETE FROM table[WHERE ...] RETURNING colonne INTO variable

Enfin il est possible d’utiliser cette clause RETURNING avec l’instruction de mise à jour UPDATE. Comme pour les instructions 
INSERT et DELETE, la clause RETURNING n’est concevable que dans le cas où l’instruction UPDATE met à jour une seule ligne 
d’informations dans la base. 
Syntaxe 

UPDATE table SET colonne=valeur [,... WHERE ...] RETURNING


colonne[,...] INTO variable[,...]

© ENI Editions - All rigths reserved - 3-


SQL dynamique 
Le  SQL  dynamique  est  une  technique  qui  permet  de  construire  des  ordres  SQL  de  façon  dynamique  à  l’exécution  de 
code PL/SQL. Le SQL dynamique permet de créer des applications plus souples car les noms des objets utilisés par un 
bloc PL/SQL peuvent être inconnus au moment de la compilation. Par exemple, une procédure peut travailler avec une 
table dont le nom est inconnu avant l’exécution de la procédure. 
Il faut rappeler que dans le SQL statique toutes les informations sont connues au moment de la compilation et bien sûr 
les ordres SQL statiques ne changent pas d’une exécution à une autre. Toutefois cette solution offre des avantages car 
le succès de la compilation garantit que les ordres SQL font référence à des objets valides de la base de données. La 
compilation vérifie également que les privilèges nécessaires sont en place pour accéder et travailler avec les objets de 
la base de données. De plus, la performance du code SQL statique est de meilleure qualité que celle du SQL dynamique. 
À cause de tous ces avantages, le SQL dynamique ne doit être utilisé que si le SQL statique ne peut pas répondre à nos 
besoins, ou bien si la solution en statique est beaucoup plus compliquée qu’en SQL dynamique. 
Cependant,  le  SQL  statique  possède  certaines  limites  qui  sont  dépassées  par  le  SQL  dynamique.  On  choisira  le  SQL 
dynamique si par exemple on ne connaît pas à l’avance les ordres SQL qui vont devoir être exécutés par le bloc PL/SQL, 
ou bien si l’utilisateur doit donner des informations qui vont venir construire les ordres SQL à exécuter. 

De plus, par l’intermédiaire du SQL dynamique, il devient possible d’exécuter des instructions du DDL (CREATE, ALTER, 
DROP, GRANT et REVOKE) ainsi que les commandes ALTER SESSION et SET ROLE à l’intérieur du code PL/SQL, ce qui est 
impossible avec le SQL statique. 
Le SQL dynamique sera donc utilisé pour répondre à l’un des points suivants : 

● La commande SQL n’est pas connue au moment de la compilation. 

● L’ordre à exécuter n’est pas supporté par le SQL statique. 

● Pour exécuter des requêtes construites lors de l’exécution. 

● Pour référencer un objet de la base de données qui n’existe pas au moment de la compilation. 

● Pour pouvoir optimiser la requête lors de son exécution. 

● Pour créer des blocs PL/SQL de façon dynamique. 

● Pour travailler sur les droits des utilisateurs de façon dynamique. 
 

Le SQL dynamique offre de meilleures performances que le package DBMS_SQL et plus de possibilités.

1. EXECUTE IMMEDIATE 

La commande EXECUTE IMMEDIATE permet de vérifier la syntaxe et d’exécuter de façon dynamique un ordre SQL ou 
un bloc anonyme PL/SQL. 
Syntaxe 

EXECUTE IMMEDIATE chaîne_dynamique


[ INTO {variable, ...| enregistrement}]
[ USING [IN|OUT|IN OUT] argument ...]
[ {RETURNING|RETURN } INTO argument, ...]

chaîne_dynamique 

représente l’ordre SQL ou le bloc PL/SQL. Depuis la version 11, la taille du code dynamique n’est plus limitée à 32 ko ; 
si besoin, une variable de type CLOB peut être utilisée. 

variable 

est une variable qui va stocker la valeur issue d’une colonne sélectionnée. 

© ENI Editions - All rigths reserved - 1-


enregistrement 

est une variable structurée qui va contenir une ligne sélectionnée. 

argument 

valeurs passées à l’ordre SQL ou au bloc PL/SQL. Ces arguments peuvent représenter des valeurs en lecture/écriture. 

À l’exception des requêtes qui retournent plusieurs lignes, il est possible d’exécuter n’importe quel ordre SQL ou bloc 
PL/SQL. Les arguments ne peuvent pas contenir le nom d’objets de la base de données qui vont être utilisés par les 
ordres SQL ou PL/SQL. 

La commande INTO ne doit être utilisée que pour des requêtes SELECT ne retournant qu’une seule ligne de valeur. 
Pour  chaque  colonne  retournée  par  la  commande  SELECT,  doit  correspondre  une  variable  ou  bien  un  champ  dans 
l’enregistrement. 

Les arguments peuvent être tous placés derrière l’instruction USING. Leur mode par défaut est alors IN, c’est­à­dire 
qu’ils fournissent une valeur à la commande dynamique. Les arguments de type OUT peuvent être précisés derrière le 
mot clé  RETURN INTO ou RETURNING INTO. Les arguments peuvent contenir des valeurs de type numérique ou bien 
des chaînes de caractères, mais il n’est pas possible d’y passer des valeurs booléennes (TRUE ou FALSE). 

Exemple 
SQL  Dynamique  :  l’exemple  ci­après  montre  une  utilisation  possible  du  SQL  dynamique  et  des  différentes  possibilités  de 
l’ordre EXECUTE IMMEDIATE. 

Lorsqu’un ordre INSERT, UPDATE ou DELETE possède une clause de type RETURNING, il est possible de placer 
les arguments de sortie soit dans la clause USING, soit dans la clause RETURNING INTO. Dans les nouvelles 
applications, il faut utiliser la clause RETURNING INTO. 

Utilisation de la clause RETURNING INTO : 

- 2- © ENI Editions - All rigths reserved


 

En utilisant la clause USING, il n’est pas nécessaire de préciser le mode d’utilisation pour les paramètres entrants car 
le mode par défaut est IN. Avec la clause RETURNING INTO, on ne peut pas préciser le mode d’utilisation du paramètre, 
c’est obligatoirement OUT. Lorsque cela est nécessaire, il faut spécifier le mode d’utilisation des paramètres en OUT ou 
IN OUT, par exemple lors de l’appel d’une procédure. 

Définition d’une procédure avec des paramètres en mode IN, OUT et IN OUT : 

Dans l’exemple suivant, la procédure définie ci­dessus va être appelée de façon dynamique. Le mode d’utilisation des 
différents paramètres sera précisé derrière la clause USING. 
Les modes d’utilisation des paramètres : 

2. OPEN FOR, FETCH et CLOSE 

Ces  trois  commandes  seront  utilisées  pour  traiter  les  requêtes  dynamiques  qui  vont  ramener  plusieurs  lignes 
d’information.  Comme  pour  les  curseurs  traditionnels,  dans  un  premier  temps,  il  faut  ouvrir  le  curseur  à  l’aide  de  la 
commande OPEN FOR qui correspond à une requête de type SELECT. Puis toutes les lignes d’information pourront être 
ramenées une par une dans le bloc PL/SQL par l’intermédiaire de la commande FETCH. Enfin, lorsque toutes les lignes 

© ENI Editions - All rigths reserved - 3-


seront traitées, il faudra fermer le curseur par l’intermédiaire de la commande CLOSE. 

a. Ouvrir un curseur (OPEN FOR) 

La  commande  OPEN  FOR  permet  d’associer  à  une  variable  de  type  curseur  une  requête  SELECT  qui  retourne 
plusieurs  lignes  d’information.  La  requête  est  exécutée  et  le  curseur  est  placé  sur  la  première  ligne  d’information. 
Contrairement  au  curseur  statique,  l’instruction  OPEN  FOR  des  curseurs  dynamiques  possède  une  clause  USING 
optionnelle afin de passer des arguments à la requête. 

Syntaxe 

OPEN {variable_curseur | :variable_hote} FOR


requête_dynamique
[USING argument, ...]

Exemple 

Dans  l’exemple  suivant,  une  variable  de  type  curseur  est  déclarée,  puis  elle  est  associée  à  une  commande  SELECT  qui 
ramène des informations depuis une table. 

declare
type CliCurTyp is ref cursor;
ccli CliCurTyp; -- variable curseur
vno clients.nocli%type;
vville clients.ville%type:=’Nantes’;
begin
open ccli for ’Select nocli, ville from clients where ville=:v’
using vville;
...
end;
/

Tous les arguments de la requête sont évalués uniquement lorsque le curseur est ouvert. Donc, pour ramener des 
informations correspondant à différentes valeurs de l’argument, il faut rouvrir le curseur en lui passant une nouvelle 
valeur pour le paramètre. 
Depuis la version 11, la taille de la requête dynamique n’est plus limitée à 32 ko ; si besoin, une variable de type 
CLOB peut être utilisée. 

b. FETCH 

La  commande  FETCH  retourne  une  ligne  de  données  issue  du  jeu  de  résultats  correspondant  à  l’exécution  de  la 
requête  SELECT  lors  de  l’ouverture  du  curseur.  Pour  chacune  des  colonnes  précisées  derrière  le  SELECT,  il  faut 
prévoir une variable dans l’environnement PL/SQL qui exécute le curseur dynamique. 
Syntaxe 

FETCH varible_curseur
INTO {variable, ...|enregistrement}

Exemple 
Il est possible de compléter l’exemple ci­dessus en ajoutant le code correspondant au traitement des lignes. 

declare
type CliCurTyp is ref cursor;
ccli CliCurTyp; -- variable curseur
vno clients.nocli%type;
vville clients.ville%type:=’Nantes’;
begin
open ccli for ’Select nocli, ville from clients where ville=:v’
using vville;
loop
fetch ccli into vno, vville; --ramener la ligne suivante
exit when ccli%notfound; --quitter la boucle si plus de lignes
--traiter les informations
end loop;
...
end;

- 4- © ENI Editions - All rigths reserved


La variable dans laquelle est stockée une valeur issue d’une colonne doit correspondre en tout point à la définition 
de la colonne : même type et même précision. 

Il est possible d’utiliser des clauses INTO différentes sur des commandes séparées de FETCH travaillant sur 
le même curseur. 

Chaque exécution de la commande FETCH ramène une ligne du jeu de résultats et place le curseur sur la 
ligne suivante. 

Si un FETCH est exécuté sur un curseur fermé ou bien jamais ouvert, alors l’exception INVALID_CURSOR est 
levée. 

c. CLOSE 

La commande CLOSE désactive une variable de type curseur. Après cette commande, le jeu de résultats, construit 
par la commande OPEN FOR n’existe plus. 
Syntaxe 

CLOSE variable_curseur

Exemple 
Dans cet exemple lorsque la dernière ligne a été traitée, alors le curseur est fermé : 

declare
type CliCurTyp is ref cursor;
ccli CliCurTyp; -- variable curseur
vno clients.nocli%type;
vville clients.ville%type:=’Nantes’;
begin
open ccli for ’Select nocli, ville from clients where ville=:v’
using vville;
loop
fetch ccli into vno, vville; --ramener la ligne suivante
exit when ccli%notfound; --quitter la boucle si plus de lignes
--traiter les informations
end loop;
close ccli;
end;
 
Lors de la tentative de fermeture d’un curseur qui est déjà fermé, PL/SQL lève l’exception INVALID_CURSOR.

3. Utilisation des curseurs dynamiques 

Quelques règles existent pour essayer de tirer le meilleur parti des curseurs dynamiques en terme de performances et 
de qualité de programmation. 

a. Amélioration des performances 

Dans  le  code  exposé  ci­dessous,  Oracle  est  obligé  de  mettre  en  place  un  nouveau  curseur  pour  chaque  nouvelle 
ouverture. Cette génération de curseurs très similaires peut dégrader les performances du serveur. 

create or replace procedure supp_clients(vnocli number) as


begin
execute immediate ’DELETE FROM clients WHERE nocli=’||
to_char(vnocli);
end;

© ENI Editions - All rigths reserved - 5-


La  conversion  du  numéro  de  client  contenu  dans  vnocli  en  chaîne  de  caractères  permet  de  construire 
proprement la commande dynamique SQL. 

L’amélioration des performances passe par l’utilisation d’un argument. Cette solution permet à Oracle de réutiliser le 
même curseur pour différentes valeurs de l’argument. 

create or replace procedure supp_clients(vnocli number) as


begin
execute immediate ’DELETE FROM clients WHERE nocli= :v’
using vnocli;
end;

b. Passer le nom d’un objet 

La  procédure  suivante  se  propose  de  supprimer  n’importe  quelle  table  de  la  base  de  données.  En  utilisant  le  SQL 
dynamique, le code suivant est saisi : 

create or replace procedure supp_table(nom_table in varchar2) as


begin
execute immediate ’DROP TABLE :t’ using nom_table;
end;

Au moment de son exécution, cette procédure lèvera une erreur du type "nom de table invalide". Ceci est dû au fait 
que les arguments ne peuvent pas servir à passer des noms d’objets de la base de données. À la place de ce code, 
il faudrait saisir le code suivant : 

CREATE PROCEDURE supp_table(nom_table IN VARCHAR2) AS


BEGIN
EXECUTE IMMEDIATE ’DROP TABLE ’|| nom_table ;
END ;

c. Utiliser plusieurs fois le même argument 

Les variables qui apparaissent dans les ordres SQL dynamiques sont associées à des arguments présents derrière 
la  clause  USING  en  respectant  leur  position  et  non  leur  nom  pour  les  identifier  à  un  argument.  Ainsi,  si  la  même 
variable apparaît deux fois dans la commande SQL dynamique, alors le même argument devra apparaître deux fois 
derrière la clause USING. 
On obtient alors le code suivant : 

requete:=’insert into commandes values (:x, :x, :y, :z)’;


execute immediate requete using a,a,b,c;

Cependant, si on utilise un bloc PL/SQL, il n’est pas nécessaire de passer deux fois le même argument. En effet, dans 
les blocs PL/SQL, les variables sont associées aux arguments en respectant leur ordre de définition bien sûr, mais, si 
la  même  variable  apparaît  plusieurs  fois,  alors  seule  la  première  occurrence  sera  associée  à  un  argument.  D’où  le 
code suivant qui est plus simple à écrire : 

bloc_plsql:=’begin ajout_cde(:x, :x, :y, :z); end;’;


execute immediate bloc_plsql using a,b,c;

d. Les attributs des curseurs 

Les curseurs explicites possèdent les quatre attributs suivants : %FOUND, %NOTFOUND, %ISOPEN et %ROWCOUNT 
qui permettent d’obtenir des informations concernant la bonne exécution du curseur, qu’il provienne d’un ordre SQL 
statique ou dynamique. Pour mener à bien l’ensemble de ces traitements, Oracle utilise des curseurs implicites. Il est 
possible de connaître les attributs de ces curseurs en utilisant le mot clé SQL. Ainsi, l’attribut %ROWCOUNT sur les 
curseurs implicites va permettre de connaître le bon déroulement ou non du dernier ordre SQL dynamique qui a été 
exécuté. 

Exemple 
Fonction  utilisant  l’attribut  du  curseur  implicite  pour  connaître  le  bon  déroulement  de  l’ordre  SQL  dynamique  :  dans 
l’exemple  suivant,  après  la  suppression  de  lignes,  l’attribut  %ROWCOUNT  est  utilisé  pour  connaître  le  nombre  de  lignes 
affectées par cette commande. 

- 6- © ENI Editions - All rigths reserved


 

Il est nécessaire de tester la fonction depuis un bloc PL/SQL car il est impossible d’exécuter une fonction du 
DML depuis une requête SELECT. 

e. Passer des valeurs NULL 

Il  peut  parfois  être  nécessaire  de  passer  des  valeurs  NULL  en  tant  qu’arguments  à  des  ordres  SQL  dynamiques. 
L’opération la plus naturelle serait d’écrire la commande suivante : 

EXECUTE_IMMEDIATE ’UPDATE clients SET ville= :x’ USING NULL ;

Comme  bien  souvent,  la  valeur  NULL  ne  se  gère  pas  aussi  simplement.  En  effet,  il  n’est  pas  possible  d’utiliser  le 
littéral  NULL  derrière  la  clause  USING.  Pour  pouvoir  contourner  cette  limite,  l’opération  consiste  à  initialiser  une 
variable avec la valeur NULL et à l’utiliser en tant que paramètre. 

declare
c_null char(1); --la variable est initialisée à NULL
begin
execute immediate ’UPDATE clients set ville=:x’ using c_null;
end;

f. Utiliser les droits de l’utilisateur 

Par défaut, une procédure stockée s’exécute en utilisant les droits de l’utilisateur Oracle qui définit cette procédure 
et  non  pas  en  utilisant  les  droits  de  l’utilisateur  qui  appelle  cette  procédure.  Certaines  procédures  sont  liées  au 
schéma sur lequel elles sont définies. 
Par exemple, si la procédure suivante est définie sur le schéma de l’utilisateur livre : 

La procédure supprime permet de supprimer n’importe quel objet du schéma, il faut simplement passer en paramètre 
le  type  de  l’objet  à  supprimer  et  son  nom.  Afin  de  faciliter  la  gestion  des  objets  dans  chaque  schéma,  le  privilège 
EXECUTE a été accordé à l’utilisatrice Marie. Lorsque l’utilisatrice Marie souhaite supprimer sa table CLIENTS de son 
schéma, elle fait appel à la procédure supprime de la façon suivante : 

Exécution de la procédure supprime depuis le schéma de Marie : 

© ENI Editions - All rigths reserved - 7-


 

Comme le nom d’objet est passé sans référence au schéma, c’est en fait la table Clients, située dans la schéma livre, 
qui est le créateur de cette procédure que Marie tente de supprimer. 
Afin  de  résoudre  tous  ces  problèmes  et  pour  garantir  que  la  procédure  stockée  va  être  exécutée  en  fonction  des 
droits de l’utilisateur qui en fait usage et non pas de ceux de son propriétaire, il faut utiliser la clause AUTHID lors de 
la définition de la procédure. Ainsi, les noms d’objets sont résolus dans le schéma de l’utilisateur de la procédure et 
non pas dans celui de son propriétaire. 
Redéfinition de la procédure en utilisant la clause AUTHID : 

g. La directive de compilation RESTRICT_REFERENCES 

Une fonction appelée depuis une commande SQL doit obéir à un certain nombre de règles pour contrôler les effets 
de  bords.  Pour  outrepasser  ces  contraintes,  il  est  possible  d’utiliser  la  directive  de  compilation 
RESTRICT_REFERENCES.  La  commande  pragma  assure  que  la  fonction  ne  va  pas  travailler  en  lecture/écriture  avec 
une table de la base ou une variable d’un package. 
Cependant,  si  le  corps  de  la  fonction  contient  un  ordre  dynamique  de  type  INSERT,  UPDATE  ou  DELETE,  alors  la 
fonction viole les règles de non­écriture dans la base (Write No Database State : WNDS) et de non­lecture de la base 
(Read  No  Database  State  :  RNDS).  C’est  pourquoi  les  règles  concernant  les  ordres  dynamiques  ne  sont  vérifiées 
qu’au moment de leur exécution. Pour un ordre EXECUTE IMMEDIATE, seule la clause INTO permet de détecter une 
violation de RNDS au moment de la compilation. 

h. Éviter les verrous mortels 

Il n’est pas possible de supprimer tous les verrous mortels qui peuvent se produire. Néanmoins, il est possible de 
prendre  certaines  précautions  pour  éviter  de  se  bloquer  soi­même.  Ainsi,  il  ne  faut  jamais  essayer  de  modifier 
(ALTER)  ou  de  supprimer  (DROP)  un  sous­programme  ou  un  package  que  l’on  est  en  train  d’utiliser,  comme  dans 
l’exemple suivant : 

create procedure calcul_ca (nocli number) as


begin
...
execute immediate ’DROP PROCEDURE calcul_ca’;
...
end;

4. Le package DBMS_SQL 

En plus du SQL dynamique, Oracle fournit le package DBMS_SQL pour exécuter de façon dynamique des ordres SQL. 

Pour utiliser le SQL dynamique la base de données doit être compatible avec la version 8.1.0 ou supérieure au 
serveur de base de données. 

Le package DBMS_SQL est une librairie PL/SQL afin d’autoriser l’exécution d’ordres SQL construits dynamiquement. 

- 8- © ENI Editions - All rigths reserved


Les principaux avantages du SQL dynamique par rapport au package DBMS_SQL sont : 

● la facilité d’utilisation, 

● de meilleures performances d’exécution, 

● le support de types de données définis par l’utilisateur. 

Néanmoins, le package DBMS_SQL possède quelques avantages par rapport au SQL Dynamique : 

● il est supporté par les applications clientes, 

● il supporte la procédure DESCRIBE_COLUMNS qui permet de connaître les informations relatives aux colonnes 
d’un curseur ouvert au travers de DBMS_SQL, 

● il supporte la copie de données par blocs pour transférer les données issues d’une requête de type SELECT 
vers une collection. 

© ENI Editions - All rigths reserved - 9-


Collections et enregistrements 
Dans le chapitre précédent, la déclaration et l’initialisation des collections et des enregistrements ont été abordées. Ce 
type de variable est très pratique et une bonne connaissance de leur utilisation permet souvent de gagner du temps 
lors de l’écriture de traitements en PL/SQL. 

L’utilisation des tableaux en PL/SQL n’est pas forcément évident au premier abord. En effet, pourquoi s’obliger à utiliser 
une telle structure alors que pour stocker un ensemble d’informations, il est très facile de créer une table temporaire. 

La  raison  est  très  simple  :  en  stockant  l’ensemble  des  données  sous  forme  de  collection  directement  dans  le  bloc 
PL/SQL,  tous  les  traitements  peuvent  être  effectués  par  le  moteur  PL/SQL.  En  limitant  les  requêtes  SQL,  on  limite  les 
accès à la base, ce qui permet d’accélérer le temps de traitement du bloc PL/SQL, mais on limite également l’occupation 
du moteur SQL et les requêtes des autres utilisateurs peuvent donc être traités plus rapidement. 
On voit donc qu’il existe des bénéfices à travailler avec les collections même si dans un premier temps le code PL/SQL à 
mettre  en  place  est  un  peu  plus  compliqué.  Il  est  à  noter  que  l’instruction  FORALL  (vue  plus  loin  dans  ce  chapitre) 
permet de faciliter considérablement les étapes de codages nécessaire pour pouvoir travailler avec les collections dans 
un bloc PL/SQL. 

1. Référencer un élément d’une collection 

Pour  pouvoir  travailler  avec  une  collection,  il  faut  d’abord  savoir  comment  accéder  à  un  élément  d’une  collection. 
Toutes les références possèdent la même structure : le nom de la collection suivi d’un indice entre parenthèses. 

nom_collection (indice)
 
L’indice doit être un nombre valide compris entre ­2 31  et 2 31 .

Pour les collections de type nested table, la plage normale des indices va de 1 à 2 31  et pour les tableaux (VARRAY) elle 
va de 1 à la taille maximale du tableau. 
Il est possible de faire référence à un élément d’une collection partout où il est possible d’utiliser une variable PL/SQL. 

Exemple 
Déclaration et utilisation d’une collection : 

DECLARE
TYPE liste IS TABLE OF VARCHAR2(15);
lesnoms liste:=liste(’B Martin’,’MP Macraigne’,’S Guegan’,’
T Groussard’);
i BINARY_INTEGER;
BEGIN
...
IF lesnoms(i) =’G Viaud’ THEN
...
END IF;
...
END;

Lorsqu’une fonction retourne une collection, il est possible de faire référence à un élément de la collection en 
utilisant la syntaxe suivante : nom_fonction(paramètre)(indice) 

2. Assigner une valeur et comparer des collections 

Il  est  possible  d’assigner  une  collection  à  une  autre  à  condition  qu’elles  soient  toutes  les  deux  de  même  type. 
L’assignation peut être réalisée par l’opérateur :=, les commandes INSERT, UPDATE, FETCH et SELECT ou par l’appel 
d’un sous­programme. 

De plus, il est important de respecter certaines contraintes comme l’illustre l’exemple suivant : 

DECLARE
TYPE Clientele IS VARRAY(100) OF Client ;
TYPE Fidele IS VARRAY(100) OF Client ;
grp1 Clientele :=Clientele(...) ;

© ENI Editions - All rigths reserved - 1-


grp2 Clientele :=Clientele(...) ;
grp3 Fidele :=Fidele(...) ;
BEGIN
grp2 :=grp1 ;
grp3 :=grp2 ;-- Illégale car de types différents
...
END ;

Si on assigne la collection NULL à une autre collection, alors cette seconde devient NULL et il faudra la réinitialiser. 
Il est possible d’assigner une valeur précise à un élément d’une collection en utilisant la syntaxe suivante : 

nom_collection(indice) :=expression

L’expression contient une valeur de même type que la collection. 
Si l’indice est NULL ou si ce n’est pas un entier, alors PL/SQL lève l’exception VALUE_ERROR. 

Lorsque  l’on  tente  d’accéder  à  un  élément  en  dehors  de  la  collection,  alors  PL/SQL  lève  l’exception 
SUBSCRIPT_BEYOND_COUNT. 

Si l’on tente d’accéder à un élément d’une collection NULL alors PL/SQL lève l’exception COLLECTION_IS_NULL. 
L’exemple suivant illustre les différents cas dans lesquels peuvent être levées les exceptions énumérées ci­dessus. 

DECLARE
TYPE tableau IS TABLE OF INTEGER ;
montab tableau ;
BEGIN
montab(1) :=5 ;-- exception COLLECTION_Is_NULL
montab :=tableau(10,5,3,6) ;
montab(1) :=length(’Hello’) ;
montab(2) :=montab(3)*2 ;
montab(’H’) :=10 ;-- exception VALUE_ERROR
montab(10) :=1 ;--exception SUBSCRIPT_BEYOND_COUNT ;
END ;

Les collections de type nested table et varray sont automatiquement assignées à NULL lors de leur déclaration. Il est 
donc possible de tester leur nullité. 

DECLARE
TYPE tableau IS TABLE OF INTEGER ;
montab tableau ;
BEGIN
...
IF montab IS NULL THEN
...
END IF ;
...
END ;

Toutefois, les collections ne peuvent pas être comparées globalement à l’idée d’une égalité (=) ou d’une inégalité (<,>, 
<=, >=, <>). Par exemple, le test de l’instruction If ci­après pose une erreur de compilation. 

DECLARE
TYPE tableau IS TABLE OF INTEGER ;
montab tableau :=tableau(5,6,7) ;
montab2 tableau :=tableau(1,2,3) ;
BEGIN
...
-- la ligne suivante provoque une erreur de compilation
IF montab=montab2 THEN
...
END IF ;
...
END ;

Cette limitation est levée depuis la version 10 pour les collections de type nested table (voir plus loin). 

3. Travailler avec les collections 

- 2- © ENI Editions - All rigths reserved


Les collections ajoutent une certaine souplesse au langage procédural PL/SQL pour manipuler et travailler simplement 
avec des données issues de la base. 

a. Travailler avec les collections de type NESTED TABLE 

À l’aide de SQL*Plus, définissons le type Typestock : 

Il faut ensuite définir le type Tabstock comme étant une collection d’éléments de type Typestock. 
Définition du tableau tabstock : 

Il est maintenant possible de définir la table Depot de la façon suivante : 

Chaque  élément  présent  dans  la  colonne  stock  est  une  collection  de  type  nested  table,  qui  va  permettre  de 
conserver le stock de chaque dépôt. La clause NESTED TABLE est nécessaire lors de la création de la table Depot car 
la colonne stock est une collection. 
Ajout  de  données  dans  la  table  à  l’aide  de  la  commande  INSERT  :  il  est  possible  d’insérer  des  valeurs  dans  cette  table 
Depot de la façon suivante : 

La modification des données de la table Depot est également possible par l’intermédiaire d’une clause UPDATE : 

© ENI Editions - All rigths reserved - 3-


 

Afin de rendre le travail avec les collections encore plus facile, il est possible de s’appuyer sur l’instruction %ROWTYPE pour 
définir une collection qui possède exactement la même structure qu’une table. 

Dans l’exemple ci­dessus une collection de type identique à la table des clients est déclarée. 

b. Travailler avec les tableaux 

Il est également possible de définir des colonnes basées sur un tableau à l’intérieur d’une table. Pour illustrer ce cas 
de figure, la table Facture va être créée. Chaque facture correspond à un seul client, et une facture peut être établie 
pour plusieurs commandes. Le numéro et le montant de chaque commande présents sur la facture sont enregistrés 
dans une colonne de type tableau. 
La première étape consiste à construire un type, composé du numéro de commande et du montant de la commande. 

Création du type LaCommande : 

Ensuite, le type correspondant à un tableau de 50 commandes (numéro et montant) est créé. 
Création du type TabCommandes : 

Enfin, la table Facture est mise en place. 

Création de la table Facture : 

- 4- © ENI Editions - All rigths reserved


 

Pour travailler avec les colonnes de type tableau, il est bien sûr possible d’utiliser les ordres SQL INSERT et UPDATE 
comme illustré dans l’exemple ci­après. 

Exemple d’utilisation des ordres INSERT et UPDATE : 

4. Manipuler les éléments des collections 

Jusqu’à maintenant les instructions montrées permettent simplement de manipuler des collections dans leur globalité, 
mais rien ne permet de manipuler un élément précis d’une collection. 

Pour réaliser ces opérations à l’aide du langage SQL, il faut utiliser la clause TABLE dont la sous­requête retourne une 
seule colonne dont on va manipuler les données à l’aide des opérations SQL classiques. Dans l’exemple ci­après, une 
ligne d’informations est ajoutée à la collection stock dans la table dépôt puis la collection Lescommandes de la table 
Facture est interrogée pour connaître le montant total d’une facture. 

Manipuler une ligne de la collection : 

© ENI Editions - All rigths reserved - 5-


 

Il  est  également  possible  de  définir  des  collections  non  pas  dans  des  tables  mais  localement  dans  un  bloc  PL/SQL, 
pour faciliter la manipulation et le traitement des données à l’intérieur de ce bloc. Même si la logique de manipulation 
des collections reste la même, il faut utiliser le mot réservé CAST afin de convertir la collection locale en un type bien 
précis.  Dans  l’exemple  suivant,  le  but  est  de  comparer  deux  collections,  l’une  est  définie  localement  dans  le  bloc 
PL/SQL et l’autre provient d’une table. La valeur retournée correspond au nombre d’écarts entre les deux collections. 
Manipuler une collection définie dans le bloc PL/SQL : 

5. Les méthodes 

Il existe un certain nombre de méthodes qui facilitent le travail avec les collections. Les méthodes sont des fonctions 
ou  des  procédures  qui  travaillent  uniquement  sur  les  collections  et  dont  l’appel  s’effectue  en  préfixant  le  nom  de  la 
méthode par le nom de la collection. 

Syntaxe 

nom_collection.nom_methode[(paramètre, ...)]
 

Les méthodes ne peuvent pas être utilisées à l’intérieur de commandes SQL.

Seule  la  méthode  EXISTS  peut  être  utilisée  sur  une  collection  NULL.  L’utilisation  de  n’importe  quelle  autre 
méthode sur une collection NULL provoque la levée de l’exception COLLECTION_IS_NULL. 

a. EXISTS 

Cette méthode accepte en paramètre l’indice de la collection dont on cherche l’existence. Ainsi nom_collection.EXISTS

- 6- © ENI Editions - All rigths reserved


(15) retourne la valeur TRUE si le quinzième élément de la collection existe et retourne FALSE dans le cas contraire. 
La  méthode  EXISTS  va  être  utilisée  afin  d’être  sûr  de  réaliser  des  opérations  conformes  sur  la  collection.  Par 
exemple, pour éviter de supprimer un élément de la collection qui n’existe pas. 

Lorsque  l’on  teste  l’existence  d’un  élément  en  dehors  de  la  collection,  alors  la  méthode  EXISTS  retourne 
FALSE au lieu de lever l’exception SUBSCRIPT_OUTSIDE_LIMIT. 

IF MesCommandes.EXISTS(5) THEN
MesCommandes(5):=nouvelle_commande;
END IF

b. COUNT 

La méthode COUNT permet de connaître le nombre d’éléments présents dans la collection. Il est fréquent d’utiliser 
cette méthode, car le nombre d’éléments contenus dans une collection n’est pas connu a priori, par exemple lorsque 
la collection est stockée dans la base Oracle. 

Attention,  dans  le  cas  où  l’on  applique  cette  méthode  sur  une  collection  de  type  NESTED  TABLE,  le  nombre 
d’éléments peut être inférieur à l’indice du plus grand élément, car les collections de ce type acceptent des éléments 
NULL suite à des suppressions. Avant d’accéder à un élément il faudra donc tester son existence à l’aide de EXISTS. 

parcours:=1;
i:=1
WHILE(i<MesCommandes.COUNT) LOOP
IF MesCommandes.EXISTS(parcours) THEN
...
i:=i+1;
END IF;
parcours:=parcours+1
END LOOP;

c. LIMIT 

Pour les collections de type NESTED TABLE, qui n’ont pas de nombre maximum d’éléments, cette méthode retourne 
NULL. Pour les collections de type VARRAYS, la méthode LIMIT permet de connaître le nombre maximum d’éléments 
possibles dans la collection. 
Par exemple, le type TabCommandes est une collection de 50 élements de type LaCommande, donc, si une collection 
est définie de type TabCommandes, il est possible d’écrire le code suivant : 

i:=1
FOR parcours IN 1 .. MesCommandes.LIMIT LOOP
WHILE(i<MesCommandes.COUNT) LOOP
IF MesCommandes.EXISTS(parcours) THEN
...
i:=i+1;
END IF;
END LOOP;
END LOOP;

d. FIRST, LAST 

Les méthodes FIRST et LAST permettent de connaître le plus petit indice de la collection ainsi que le plus grand. Si la 
collection est vide, alors les méthodes FIRST et LAST retournent la valeur NULL. Bien sûr, si l’indice retourné par ces 
deux méthodes est le même, cela signifie que la collection ne contient qu’un seul élément. 

Pour une collection de type VARRAY, la méthode FIRST retourne toujours 1 et la valeur retournée par LAST 
est la même que celle retournée par COUNT. 

e. PRIOR, NEXT 

La  méthode  PRIOR(i)  permet  de  connaître  l’indice  de  l’élément  précédant  l’élément  d’indice  i  dans  la  collection.  La 

© ENI Editions - All rigths reserved - 7-


méthode NEXT(i) permet de connaître l’indice de l’élement suivant. Si l’élément d’indice i est le premier, alors l’appel à 
PRIOR(i) retourne la valeur NULL. Le résultat est le même lors de l’appel de la méthode NEXT sur le dernier élément 
de la collection. 
L’exemple suivant montre comment il est possible de parcourir tous les éléments d’une collection : 

i:=MesCommandes.FIRST;
WHILE (i IS NOT NULL) LOOP
...
i:=MesCommandes.NEXT(i);
END LOOP;

f. EXTEND 

Il  est  possible  de  modifier  la  taille  d’une  collection,  en  l’agrandissant,  par  l’intermédiaire  de  la  méthode  EXTEND. 
Cette méthode possède trois formes différentes d’appel : 

MaCollection.EXTEND 

un élément NULL est ajouté à la collection. 

MaCollection.EXTEND(n) 

n éléments NULL sont ajoutés à la collection. 

MaCollection.EXTEND(n,i) 

n  éléments  sont  ajoutés  à  la  collection.  Chaque  élément  contient  une  copie  des  valeurs  contenues  dans  l’élément 
d’indice i. 

Exemple d’utilisation de EXTEND : 

g. TRIM 

Cette méthode, qui permet de supprimer un ou plusieurs éléments à la fin de la collection, peut être utilisée sous les 
deux formes suivantes : 

MaCollection.TRIM 

Le dernier élément de la collection est supprimé. 

MaCollection.TRIM(n) 

Les n derniers éléments de la collection sont supprimés. 

Si le nombre d’élément  que  l’on tente de supprimer est plus important que le nombre d’éléments présents 


dans  la  collection  (cette  valeur  est  connue  par  la  méthode  COUNT),  alors  l’exception  SUBSCRIPT_ 
BEYOND_COUNT est levée. 

Exemple 

- 8- © ENI Editions - All rigths reserved


Utilisation de TRIM : dans l’exemple ci­après, la méthode TRIM est utilisée pour supprimer les deux derniers éléments de la 
collection. 

h. DELETE 

Cette  méthode,  qui  possède  trois  formes  d’appels,  permet  de  supprimer  un  élément,  plusieurs  éléments  ou  la 
totalité d’une collection. 

MaCollection.DELETE 

Supprime tous les éléments de la collection. 

MaCollection.DELETE(n) 

Supprime l’élément numéro n de la collection. 

MaCollection.DELETE(n,m) 

Supprime tous les éléments dont les indices sont compris entre n et m. Les indices numéros n et m sont inclus. Si n 
est plus grand que m, alors aucun élément n’est supprimé. 

Dans  les  collections  de  type  VARRAY,  il  n’est  pas  possible  de  supprimer  des  éléments  à  l’intérieur  de  la 
collection. La seule possibilité est de supprimer le dernier élément. 

Si un élément à supprimer n’existe pas, alors la méthode DELETE saute simplement cet élément. Aucune erreur n’est 
levée. 
PL/SQL  conserve  l’espace  mémoire  des  éléments  supprimés,  il  est  donc  possible  de  les  remplacer  en  assignant 
simplement une nouvelle valeur. 

Exemple d’utilisation de DELETE : 

i. COLLECT 

Cette fonction de calcul d’agrégat permet d’extraire les données d’une colonne et de stocker le résultat sous forme 

© ENI Editions - All rigths reserved - 9-


d’une collection. Il est ainsi facile de travailler avec ces données depuis un bloc PL/SQL. Avec cette fonction, il n’est 
plus nécessaire de passer par un curseur pour travailler avec des informations issues d’une requête d’extraction. 

Pour avoir la possibilité de travailler avec le résultat de cette fonction, il est nécessaire d’inclure la fonction 
COLLECT comme paramètre de la fonction CAST. 

Création du tableau destiné à être alimenté par COLLECT : 

Valorisation du tableau par la fonction COLLECT : 

6. Les exceptions 

Dans la plupart des cas, lorsque l’on tente d’accéder à un élément qui n’existe pas dans une collection, PL/SQL lève 
une exception prédéfinie. Il est intéressant de citer les principales exceptions qui peuvent être levées : 
COLLECTION_IS_NULL 

La collection n’est pas initialisée. 

NO_DATA_FOUND 

L’élément accédé n’existe plus. 

SUBSCRIPT_BEYOND_COUNT 

L’indice de l’élément accédé a été supprimé. 

SUBSCRIPT_OUTSIDE_LIMIT 

L’indice est en dehors des valeurs autorisées. 

VALUE_ERROR 

L’indice est NULL ou n’est pas convertible en un entier. 

L’exemple suivant illustre la levée de ces exceptions par PL/SQL. 

DECLARE
TYPE LaListe IS TABLE OF VARCHAR2(50);
LesCourses LaListe; -- initialisé à NULL
BEGIN
LesCourses(1):=’Carotte’;-- exception COLLECTION_IS_NULL
LesCourses:=LaListe(’Tomates’,’Melon’,’Salade’);--initialise
la collection
LesCourses(NULL):=’Pommes’;-- exception VALUE_ERROR

- 10 - © ENI Editions - All rigths reserved


LesCourses(0):=’Poires’;-- exception SUBSCRIPT_OUTSIDE_LIMIT
LesCourses(4):=’Kiwis’;-- exception SUBSCRIPT_BEYOND_COUNT
LesCourses.DELETE(1);--Suppression de l’élément 1
IF LesCourses(1)=’Choux’ THEN-- Exception NO_DATA_FOUND
...
END IF;
END;

© ENI Editions - All rigths reserved - 11 -


La copie des données par blocs 
Complètement intégré au SGBDR Oracle, le moteur procédural PL/SQL traite toutes les commandes procédurales et le 
moteur  SQL  s’occupe  de  traiter  toutes  les  commandes  SQL.  L’interaction  entre  les  deux  moteurs  est  fréquente  car  le 
code PL/SQL travaille avec des données issues de la base de données, et extraites par l’intermédiaire de commandes 
SQL. 
Lors de chaque passage du moteur PL/SQL au moteur SQL, et inversement, une charge de travail supplémentaire est 
demandée  au  serveur.  Afin  d’améliorer  les  performances,  il  est  important  de  réduire  ce  nombre  de  changements  de 
moteur.  Les  copies  de  données  par  blocs  offrent  une  solution  pour  réduire  le  nombre  d’interactions  entre  ces  deux 
moteurs. 

Répartition du travail entre les deux moteurs : 

Avec les copies par blocs, les ordres SQL vont pouvoir concerner toute la collection et non seulement les éléments les 
uns après les autres. 
L’exemple  suivant,  qui  concerne  l’insertion  de  lignes  dans  une  table,  permet  de  comparer  le  gain  de  temps  entre  le 
traitement classique des ordres SQL dans les blocs PL/SQL et le traitement par blocs. 
Création de la table Composants : 

La  table  créée  ci­dessus  va  être  remplie  par  l’intermédiaire  d’un  bloc  PL/SQL.  Pour  chacune  des  deux  méthodes 
d’insertion, le temps d’exécution sera mesuré. 
Les avantages du traitement par blocs : 

© ENI Editions - All rigths reserved - 1-


 

Pour  traiter  tous  les  éléments  d’une  collection,  il  faut  utiliser  le  mot  clé  FORALL.  Son  utilisation  est  détaillée 
ultérieurement. 

L’utilisation du package DBMS_OUTPUT est traité plus loin dans cet ouvrage. Pour pouvoir exécuter ce script 
correctement,  il  faut  commencer  par  positionner  la  variable  d’environnement  SERVEROUTPUT  à  On  dans 
SQL*Plus par l’intermédiaire de la commande : SET SERVEROUTPUT ON. 

1. FORALL 

Le mot clé FORALL indique au moteur PL/SQL de travailler par blocs avec la collection avant d’envoyer  la  commande 


SQL au moteur SQL. Bien que le mot clé FORALL propose une borne de début et de fin, il ne permet pas de mettre en 
place une boucle FOR. 
Syntaxe 

FORALL index IN borne_inférieur..borne_supérieur commande_SQL;

La commande SQL doit être un ordre INSERT, UPDATE ou DELETE, qui travaille avec une collection. L’ordre  SQL  peut 


tout  à  fait  travailler  avec  plusieurs  collections  comme  c’est  le  cas  dans  l’exemple  précédent.  Il  faut  alors  utiliser  les 
mêmes indices d’éléments dans les différentes collections. 
Exemple 

Dans l’écran ci­dessous, on retrouve différents cas d’utilisation de la commande FORALL. 

- 2- © ENI Editions - All rigths reserved


 

Les copies d’informations par blocs peuvent être effectuées directement dans des collections d’enregistrement. Cette 
fonctionnalité  est  offerte  à  partir  d’Oracle  9i.  Elle  permet  de  gagner  en  souplesse  au  niveau  de  l’utilisation  des 
données dans un bloc PL/SQL. 
L’exemple  suivant  montre  différentes  utilisations  possibles  du  travail  avec  les  collections  d’enregistrements  et  plus 
particulièrement  la  mise  en  place  de  la  collection  avec  des  données  issues  de  la  base  avec  les  commandes  FOR..IN  et 
FORALL. 

create table table1(col1 number, col2 char(30));


create table table2(col1 number, col2 char(30));

declare
type tableauRec is table of table1%rowtype;
type tableauNumerique is table of number;
type tableauCaracteres is table of char(30);
cursor ctable2 is select col1, col2 from table2;

tabrec tableauRec;
tabnum tableauNumerique:=tableauNumerique(2,3,5);
tabCar tableauCaracteres:=tableauCaracteres(’Godel’,’Escher’,’Bach’);
begin
-- ajouter des données dans la table1
forall i in 1..3
insert into table1 values (tabnum(i), tabcar(i));
-- ajouter des données dans le tableau des enregistrements
select col1, col2 bulk collect into tabrec from table1;

-- insérer des données dans la table2


forall i in tabrec.first..tabrec.last
insert into table2 values tabrec(i);

-- mettre à jour les données dans le tableau des enregistrements


for i in tabrec.first..tabrec.last loop
tabrec(i).col1:=tabrec(i).col1*2;
end loop;

-- utilisation du curseur
open ctable2;
fetch ctable2 bulk collect into tabrec;
close ctable2;

end;
/
select * from table1;
select * from table2;
drop table table1;
drop table table2;

a. Limitations 

© ENI Editions - All rigths reserved - 3-


● Il n’est possible d’utiliser la commande FORALL que dans les programmes côté serveur. 

● Les commandes INSERT, UPDATE ou DELETE doivent faire référence à au moins une collection pour pouvoir 
bénéficier de la commande FORALL. 

● Il doit exister des éléments dans la collection, pour toutes les valeurs d’indice précisées dans la commande 
FORALL. 

● Il n’est pas possible d’exprimer l’indice sous forme d’un calcul. 

b. Les transactions et la commande FORALL 

À l’intérieur  d’une  commande  FORALL,  si  l’une  des  commandes  SQL  provoque  une  erreur  d’exécution, c’est  alors  la 
totalité des instructions réalisées à l’intérieur de la commande FORALL qui est annulée (ROLLBACK). 

Cependant,  si  l’exception  qui  est  levée  par  un  ordre  SQL  est  traitée  dans  le  bloc  PL/SQL,  alors  les  opérations 
réalisées  par  la  commande  FORALL  sont  annulées  jusqu’à un point de transaction (SAVEPOINT) qui est marqué de 
façon  implicite  après  chaque  commande  SQL.  C’est­à­dire  que  seule  la  commande  SQL  qui  est  à  l’origine  de 
l’exception est annulée de façon automatique. C’est dans le code de traitement de l’exception qu’il faudra décider, si 
l’on conserve les modifications déjà effectuées (COMMIT) ou si l’on annule toute l’instruction FORALL (ROLLBACK). 

c. Les clauses INDICES OF et VALUES OF 

Le parcours des listes n’est pas toujours aussi facile que dans l’exemple précédent. 
Pour pouvoir parcourir une liste sans avoir à tenir compte de l’indice du premier et du dernier élément, il est possible 
d’utiliser la clause INDICES OF. Cette clause s’avère d’autant plus intéressante que l’on va retrouver uniquement les 
éléments de la collection même s’il existe des emplacements non valorisés. La clause INDICES OF permet de garantir 
le parcours complet de la collection sans qu’une exception ne soit levée. 

Au contraire, si l’on souhaite parcourir simplement un sous­ensemble d’une collection alors il est nécessaire d’utiliser 
la clause VALUES OF. Cette clause permet de récupérer les indices depuis une autre collection qui doit être de type 
NESTED  TABLE  ou  bien  un  tableau  associé  à  un  index  numérique.  Cette  collection  est  donc  une  collection  de 
parcours. 

2. L’attribut %BULK_ROWCOUNT 

Lors  de  l’exécution  des  ordres  SQL,  un  curseur  est  ouvert  implicitement  par  le  moteur.  Il  est  possible  de  tester  les 
attributs  %FOUND,  %ISOPEN,  %NOTFOUND  et  %ROWCOUNT,  pour  s’assurer  du  bon  déroulement  de  la  commande 
SQL. 

Le  curseur  implicite  (SQL)  possède  un  attribut  supplémentaire  :  %BULK_ROWCOUNT,  qui  est  utilisé  avec  une 
commande  FORALL.  Cet  attribut  est  en  fait  une  collection  de  type  index  by  table,  pour  lequel  l’élément  numéro  i 
contient  le  nombre  de  lignes  affectées  par  l’exécution  de  l’ordre  SQL  numéro  i.  Si  aucune  ligne  n’a  été  affectée  par 
l’instruction numéro i alors l’attribut SQL%BULK_ROWCOUNT(i) retourne la valeur 0. 

Exemple d’utilisation de l’attribut %BULK_ROWCOUNT : 

- 4- © ENI Editions - All rigths reserved


 

3. BULK COLLECT 

Le mot clé BULK COLLECT indique au moteur SQL que les données seront retournées dans une collection, avant de 
retourner dans le moteur PL/SQL. Il est possible d’utiliser cette commande avec les clauses SELECT INTO, FETCH INTO 
et RETURNING INTO. 
Syntaxe 

... BULK COLLECT INTO nom_collection [,nom_collection, ...]

Exemple 
Utilisation  de  BULK  COLLECT  :  dans  l’exemple  suivant,  les  informations  extraites  depuis  la  table  clients  sont  conservées 
dans la collection les Clients. 

 
 
Il est bien sûr possible de réaliser le même genre d’opération avec un curseur.

Les gains de temps d’exécution des blocs PL/SQL sont spectaculaires pour les volumes de données importants, si l’on 
travaille  avec  les  collections.  Il  est  facile  de  ramener  les  données  depuis  la  table  par  l’intermédiaire  de  l’instruction 
BULK COLLECT. Puis, le traitement des données est effectué directement dans la collection et enfin les modifications 
sont propagées dans la table en utilisant l’instruction FORALL pour parcourir la collection. 

4. LIMIT 

La clause optionnelle LIMIT qui est limitée à la copie par blocs depuis un curseur, permet de limiter le nombre de lignes 
d’informations ramenées lors de chaque FETCH. 
Syntaxe 

FETCH ... BULK COLLECT INTO ... [LIMIT nombre_lignes]

Le nombre de lignes doit être un nombre entier. 

© ENI Editions - All rigths reserved - 5-


Exemple 
Utilisation de LIMIT : dans l’exemple suivant, les lignes sont ramenées par paquets de 10. 

5. Comparer les collections 

Le travail avec une collection est relativement aisé. Mais très rapidement, il va être nécessaire de travailler avec deux 
ou plusieurs collections afin de comparer leurs contenus. Avant la version 10g d’oracle, pour pouvoir réaliser ce type 
de  travail,  il  était  nécessaire  d’écrire  ses  propres  fonctions  de  comparaisons.  Ce  travail,  en  plus  d’être  rébarbatif, 
représente l’inconvénient que la solution optimale est rarement trouvée rapidement, surtout que les parcours de liste 
et  les  tests  de  comparaisons  sont  des  sources  d’erreurs  communes  même  pour  les  programmeurs  chevronnés.  En 
introduisant des instructions permettant de travailler avec les collections comme avec des ensembles, Oracle facilite le 
travail avec ce type de structure. 
Les  instructions  introduites  sont  :  MULTISET  UNION,  MULTISET  UNION  DISTINCT,  MULTISET  INTERSECT,  MULTISET 
EXCEPT  et  SET.  Ces  instructions  représentent  les  opérateurs  disponibles  sur  les  ensembles  pour  effectuer  l’union, 
l’intersection, la différence et extraire les éléments distincts. 
Pour illustrer le fonctionnement de chacune de ces instructions et comprendre ainsi leur intérêt, on va travailler sur un 
petit exemple. 
Exemples 
Un package pkg_test va être créé. Ce package va contenir deux collections et une procédure qui permet d’afficher le 
contenu de la collection passée en paramètre. 
La première étape consiste à définir le type qui va servir de base à la collection. 

Ensuite, il est nécessaire de définir l’en­tête du package. 

- 6- © ENI Editions - All rigths reserved


 

Puis, il faut définir le corps du package afin de donner la définition de la procédure affiche. Cette procédure correspond à un 
simple parcours de collection en demandant l’affichage de chacune des valeurs. 

Maintenant que la base est posée, il est possible d’illustrer les instructions. 
Par exemple pour connaître l’ensemble de nos amis il est nécessaire de réaliser une union entre les deux collections. 
Pour  cela,  on  dispose  des  instructions  MULTISET  UNION  et  MULTISET  UNION  DISTINCT.  La  distinction  entre  ces  2 
instructions provient du fait que la première, MULTISET UNION, va retourner l’ensemble des valeurs contenues dans 
les  deux  collections  sans  chercher  à  éliminer  les  doublons  tandis  que  la  seconde,  MULTISET  UNION  DISTINCT,  va 
permettre d’éliminer les doublons dans la collection résultante. 

L’exemple  ci­après  illustre  le  résultat  de  l’exécution  de  l’instruction  MULTISET  UNION.  On  remarque  que  Dupont  apparaît 
deux fois, en première et en quatrième position. 

Au contraire, avec l’instruction MULTISET UNION DISTINCT, les doublons sont éliminés. 
Cette fonctionnalité est illustrée par l’exemple ci­dessous dans lequel le nom Dupont n’apparaît qu’une seule fois. 

© ENI Editions - All rigths reserved - 7-


 

Pour connaître les éléments communs aux deux collections, il faut utiliser MULTISET INTERSECT afin de définir la collection 
d’intersection. 

L’exemple ci­dessus permet d’obtenir la liste des amis communs. 
Pour pouvoir faire la différence entre deux collections, il va être nécessaire d’utiliser l’instruction MULTISET EXCEPT. 

L’exemple ci­dessus permet de connaître parmi la collection mesAmis ceux qui ne sont pas connus par l’autre collection 
(sesAmis). 

Il  est  bien  sûr  évident  que  pour  cette  instruction  l’ordre,  dans  lequel  les  collections  sont  introduites  par  rapport  à 
l’instruction, possède une influence directe sur le résultat. 

Enfin,  lorsque  l’on  travaille  avec  des  collections  de  grande  importance,  il  est  possible  d’éliminer  les  doublons  en 
produisant une nouvelle collection par l’intermédiaire de l’instruction SET.  

- 8- © ENI Editions - All rigths reserved


 

La collection résultant de l’union des deux collections initiales possède des doublons. La collection résultante produite 
par l’instruction SET ne possède quant à elle aucune redondance. 

© ENI Editions - All rigths reserved - 9-


Fonctions et ensemble de lignes 
Il  est  maintenant  possible  de  définir  en  PL/SQL  des  fonctions  qui  acceptent  en  paramètres  d’entrée  et/ou  qui 
retournent, non pas une valeur simple mais un ensemble de lignes. L’avantage de ces fonctions est qu’il n’est alors plus 
nécessaire de stocker les données dans une table temporaire avant d’appeler l’exécution de la fonction. Il est possible 
d’utiliser de telles fonctions à tous les endroits où il est possible de faire référence à un nom de table et notamment 
avec la clause FROM d’une requête SELECT. 

Afin d’améliorer les temps de réponses de ces fonctions qui retournent un ensemble de données, l’instruction pipelined 
précise que les données vont être retournées au fur et à mesure de l’exécution de la fonction. C’est d’ailleurs avec ce 
type de fonction que la gestion des ensembles de valeurs renvoyées est la plus simple. 
Lors de la déclaration de la fonction, le mot clé PIPELINED est ajouté dans l’en­tête et les informations sont retournées à 
l’aide de la commande PIPE ROW. 

Ces fonctions peuvent accepter en paramètre d’entrée un ensemble de lignes sous la forme d’une collection (comme un 
tableau de type VARRAY) ou bien sous la forme d’un REF CURSOR (référence à un curseur). 

Exemple 
L’exemple suivant montre la mise en place d’une fonction qui retourne une collection de chiffres en mode pipelined c’est­à­dire 
au fur et à mesure de l’exécution de la fonction. 

SQL> -- création du type


SQL> create type MtLigne as object(
2 nolig number(2),
3 montant number(12,2)
4 );
5 /

Type créé.

SQL> -- création de la table


SQL> create type MtLignesTab as table of MtLigne;
2 /

Type créé.

SQL> -- exemple de fct pipelined


SQL> create or replace function LigneVal (clig in SYS_REFCURSOR)
2 return MtLignesTab pipelined is
3 out_mt MtLigne:=MtLigne(NULL, NULL);
4 vlig ligcdes%rowtype;
5 vprix number(12,2);
6 vmontant number(12,2);
7 BEGIN
8 loop
9 fetch clig into vlig;
10 exit when clig%notfound;
11 -- prix de chaque article
12 select prix into vprix
13 from articles
14 where refart=vlig.refart;
15 -- calcul du montant de la ligne
16 vmontant:=vlig.qtecde*vprix;
17 -- construire la valeur à retourner
18 out_mt.nolig:=vlig.nolig;
19 out_mt.montant:=vmontant;
20 -- retourner la valeur
21 pipe row(out_mt);
22 end loop;
23 return;
24 END;
25 /

Fonction créée.

SQL> -- utilisation de la fct pipelined


SQL> select sum(montant) as total
2 from table(LigneVal(CURSOR(select * from ligcdes where

© ENI Editions - All rigths reserved - 1-


nocde=1301)));

TOTAL
----------
750

- 2- © ENI Editions - All rigths reserved


L’utilitaire Wrap 
L’utilitaire  Wrap  est  un  programme  qui  permet  de  coder  le  code  source  PL/SQL.  Il  est  ainsi  possible  de  distribuer  du 
code PL/SQL sans que les utilisateurs puissent avoir accès au code source. 

Wrap va donc permettre de masquer l’algorithme utilisé mais en aucun cas les chaînes de caractères, les nombres, le 
nom des variables, des colonnes et des tables ne sont codés. L’utilitaire ne permet donc pas de masquer les mots de 
passe ou bien les noms des tables. 
 
Cet utilitaire est entièrement compatible avec Oracle. La compatibilité descendante n’est pas assurée.

Cet utilitaire accepte deux paramètres : 
iname 

Permet de préciser le fichier qui contient le code PL/SQL qui va être codé. 

oname (optionnel) 

Permet de spécifier le nom du fichier qui va contenir la version codée du fichier précisé à l’aide de iname. Par défaut, ce 
fichier de sortie porte l’extension plb. 

Syntaxe 

wrap iname=fichier_entrée [oname=fichier_sortie]

Exemple d’utilisation de l’utilitaire Wrap 

Quelques  éléments  de  la  nouvelle  syntaxe  SQL  ne  sont  pas  supportés  en  standard.  Pour  que  tous  les 
éléments de la nouvelle syntaxe soit supportés, il faut utiliser le paramètre edebug=wrap_new_sql. 

© ENI Editions - All rigths reserved - 1-


DBMS_OUTPUT 
Le  package  DBMS_OUTPUT  permet  d’envoyer  des  messages  depuis  une  procédure,  une  fonction,  un  package  ou  un 
déclencheur (trigger) de base de données. Les procédures PUT et PUT_LINE de ce package permettent de placer des 
informations  dans  un  tampon  qui  pourra  être  lu  par  un  autre  bloc  PL/SQL  qui  utilisera  la  procédure  GET_LINE  pour 
récupérer l’information. 

Si la récupération et l’affichage des informations placées dans le tampon ne sont pas gérés et si l’exécution 
ne se déroule pas sous SQL*Plus, alors les informations sont ignorées. Le principal intérêt de ce package est 
de faciliter la mise au point des programmes. 

SQL*Plus  possède  le  paramètre  SERVEROUTPUT  qu’il  faut  activer  à  l’aide  de  la  commande  SET 
SERVEROUTPUT ON pour connaître les informations qui ont été écrites dans le tampon. 

1. ENABLE 

Cette  procédure  permet  d’activer  les  appels  aux  procédures  PUT,  PUT_LINE,  NEW_LINE,  GET_LINE  et  GET_LINES. 
L’appel à cette procédure sera ignoré si le package DBMS_OUTPUT n’est pas activé. 

Il n’est pas nécessaire de faire appel à cette procédure lorsque le paramètre SERVEROUTPUT est fixé depuis 
SQL*Plus. 

Syntaxe 

DBMS_OUTPUT.ENABLE (taille_tampon IN INTEGER DEFAULT 20000) ;

Lorsqu’elle est spécifiée, la taille du tampon est au maximum de 1 000 000 d’octets et au minimum de 2 000 octets. 
La valeur NULL permet d’avoir un tampon de taille illimitée. 
 
Si plusieurs appels à cette procédure sont effectués, alors c’est la taille maximale du tampon qui est retenue.

2. DISABLE 

Cette procédure permet de désactiver les appels aux procédures PUT, PUT_LINE, NEW_LINE, GET_LINE et GET_LINES 
et vide le tampon de toutes les informations qu’il contient. 

Il n’est pas nécessaire de faire appel à cette procédure lorsque le paramètre SERVEROUTPUT est fixé depuis 
SQL*Plus. 

Syntaxe 

DBMS_OUTPUT.DISABLE

Cette procédure ne possède aucun paramètre. 

3. PUT et PUT_LINE 

Il  est  possible  de  placer  directement  une  ligne  d’informations  dans  le  tampon  à  l’aide  de  PUT_LINE,  ou  bien  de 
construire  petit  à  petit  la  ligne  d’informations  en  plaçant  les  informations  les  unes  à  la  suite  des  autres  dans  le 
tampon par l’intermédiaire de la commande PUT. Ces deux procédures permettent de placer indifféremment dans le 
tampon des données de type caractère (VARCHAR2), de type numérique (NUMBER) ou de type DATE. 

Dans tous les cas, les données sont converties au format chaîne de caractères. Les données de type numérique ou 
date  sont  formatées  en  utilisant  la  fonction  de  conversion  TO_CHAR  et  en  utilisant  les  formats  de  conversion  par 
défaut.  Si  l’on  souhaite  obtenir  d’autres  formats  de  conversion,  alors  il  faut  convertir  les  données  en  chaîne  de 

© ENI Editions - All rigths reserved - 1-


caractères avant de placer ces données dans le tampon. 
La  procédure  PUT_LINE  permet  d’insérer  automatiquement  le  marqueur  de  fin  de  ligne  après  chaque  ajout 
d’informations dans le tampon. Au contraire, avec l’utilisation de la procédure PUT, il faudra insérer les marqueurs de 
fin de ligne par l’appel à la procédure NEW_LINE. En effet, les procédures GET_LINE et GET_LINES, qui permettent de 
lire les informations placées dans le tampon, ne sont capables de lire que les lignes d’informations qui se terminent 
par un marqueur de fin de ligne. 

Si le volume des données à placer dans le tampon est supérieur à la taille du tampon alors une erreur est 
levée. 

Syntaxe 

DBMS_OUTPUT.PUT(element IN NUMBER) ;
DBMS_OUTPUT.PUT(element IN VARCHAR2) ;
DBMS_OUTPUT.PUT(element IN DATE) ;
DBMS_OUTPUT.PUT_LINE(element IN NUMBER) ;
DBMS_OUTPUT.PUT_LINE(element IN VARCHAR2) ;
DBMS_OUTPUT.PUT_LINE(element IN DATE) ;

4. NEW_LINE 

Cette procédure permet de placer un marqueur de fin de ligne dans le tampon. 

Syntaxe 

DBMS_OUTPUT.NEW_LINE ;

5. GET_LINE et GET_LINES 

Il est possible de lire depuis le tampon une ligne simple d’informations en utilisant la procédure GET_LINE, ou bien de 
ramener un tableau de lignes par l’intermédiaire de la procédure GET_LINES. 

Après  la  lecture  du  tampon  par  les  procédures  GET_LINE  ou  GET_LINES,  toutes  les  lignes  non  lues  encore 
présentes  dans  le  tampon  lors  de  l’appel  suivant  à  PUT,  PUT_LINE  ou  NEW_LINE  sont  supprimées  afin 
d’éviter toute confusion possible d’informations. 

Syntaxe 

DBMS_OUTPUT.GET_LINE( ligne OUT VARCHAR2, état IN OUT


INTEGER)
DBMS_OUTPUT.GET_LINES(lignes OUT CHARARR, nb_lignes IN OUT
INTEGER)

Les paramètres sont les suivants : 
ligne 

Contient  une  seule  ligne  d’informations  en  provenance  du  tampon.  Le  marqueur  de  fin  de  ligne  n’est  pas  contenu 
dans la ligne retournée. La longueur maximale de cette ligne est de 32767 caractères. 

état 

Si l’appel a été un succès, alors l’état contient la valeur 0 et il contient 1 lorsque le tampon ne contient plus aucune 
ligne d’informations. 

lignes 

C’est un tableau de VARCHAR2(32767). 

nb_lignes 

- 2- © ENI Editions - All rigths reserved


Nombre de lignes d’informations contenues dans le tableau. 

Le  package  DBMS_OUTPUT  est,  en  règle  générale,  utilisé  pour  la  mise  au  point  des  fonctions  et  des  procédures 
stockées, car l’affichage des informations placées dans le tampon est automatique depuis SQL*Plus. 
Exemple 

Procédure utilisant le package DBMS_OUTPUT : 

Puis il faut exécuter cette fonction depuis SQL*Plus : 

© ENI Editions - All rigths reserved - 3-


Le package UTL_FILE 
Le package PL/SQL UTL_FILE permet aux programmes PL/SQL de travailler en lecture et écriture avec des fichiers texte 
du système de fichiers. Le flux d’entrée/sortie ouvert vers le système d’exploitation est limité au seul travail avec ces 
fichiers. 
Ce package est utilisable pour du code PL/SQL écrit aussi bien côté client que sur le serveur. L’exécution côté client est 
soumise  aux  règles  de  sécurité  du  système  d’exploitation  côté  client  pour  accéder  et  utiliser  le  système  de  fichiers. 
Côté  serveur,  l’exécution  du  programme  PL/SQL  qui  travaille  avec  le  package  UTL_FILE,  doit  être  réalisée  dans  un 
mode  de  sécurité  privilégié,  et  d’autres  options  de  sécurité  limitent  la  possibilité  des  actions  menées  au  travers  de 
UTL_FILE. 
En  effet,  côté  serveur,  les  répertoires  accessibles  par  UTL_FILE  doivent  être  précisés  dans  le  fichier  des  paramètres 
(INIT.ORA) par l’intermédiaire du paramètre UTL_FILE_DIR. 

Syntaxe 

UTL_FILE_DIR=c:\temp.

Pour  rendre  tous  les  répertoires  accessibles  par  UTL_FILE  côté  serveur,  il  faut  préciser  le  paramètre  suivant 
dans le fichier INIT.ORA : UTL_FILE_DIR=* 

À partir la version 9i il est préférable d’utiliser la commande CREATE DIRECTORY pour gérer les répertoires accessibles 
depuis le package UTL_FILE à la place du paramètre d’initialisation UTL_FILE_DIR. 

Il est possible de connaître la liste des répertoires définis sur le serveur à l’aide de la vue ALL_DIRECTORIES. 

Syntaxe 

CREATE OR REPLACE DIRECTORY nom_repertoire AS ’chemin’;


 

Un exemple d’utilisation de cette instruction est donné dans l’exemple récapitulatif du package.

1. FOPEN, FOPEN_NCHAR 

Cette fonction permet d’ouvrir un fichier en vue d’effectuer des opérations de lecture ou d’écriture. Le chemin d’accès 
au fichier doit correspondre à un répertoire valide défini à l’aide de CREATE DIRECTORY. 

Le chemin complet d’accès doit exister, et FOPEN ne peut pas créer de répertoires. 

La fonction FOPEN retourne un pointeur sur le fichier. Ce pointeur devra être précisé pour l’ensemble des opérations 
de lecture/écriture qui seront effectuées par la suite. 
 
Il n’est pas possible d’ouvrir plus de 50 fichiers de façon simultanée.

Syntaxe 

UTL_FILE.FOPEN(
chemin IN VARCHAR2,
nom_fichier IN VARCHAR2,
mode_ouverture IN VARCHAR2,
taille_max_ligne IN BINARY_INTEGER DEFAULT 1024)
RETURN UTL_FILE.FILE_TYPE ;

chemin 

Nom de l’objet DIRECTORY qui correspond au répertoire du système d’exploitation qui contient le fichier à ouvrir. 

nom_fichier 

Nom du fichier avec son extension, sans aucune information concernant le chemin d’accès. 

© ENI Editions - All rigths reserved - 1-


mode_ouverture 

Chaîne de caractères précisant le mode d’ouverture du fichier. Les valeurs possibles peuvent être : 

­ r ouverture du fichier en lecture seule. 

­ w ouverture du fichier en mode écriture. 

­ a ouverture d’un fichier existant en mode ajout. 

Lors  de  l’ouverture  en  mode  a  (ajout)  d’un  fichier  qui  n’existe  pas,  alors  il  est  créé  et  ouvert  en  mode  w 
(écriture). 

taille_max_ligne 

Longueur  maximum  d’une  ligne  (caractère  de  fin  de  ligne  compris).  Doit  être  compris  entre  1  et  32767  ;  1024  par 
défaut. 

La fonction FOPEN peut lever les exceptions suivantes : INVALID_PATH, INVALID_MODE ou INVALID_OPERATION. 
La  fonction  FOPEN_NCHAR  qui  accepte  les  mêmes  paramètres  que  la  fonction  FOPEN  permet  d’ouvrir  un  fichier  en 
mode UNICODE pour les lectures et les écritures. Avec cette méthode il est alors possible de lire et d’écrire un fichier 
en UNICODE au lieu d’utiliser le jeu de caractères de la base de données. 

2. IS_OPEN 

La fonction IS_OPEN a pour but de tester si un pointeur de fichier correspond à un flux vers un fichier qui a bien été 
ouvert et non encore fermé. La fonction IS_OPEN permet de tester la validité au niveau du package UTL_FILE et ne 
permet en aucun cas d’être sûr que l’opération se déroulera sans problème de la part du système d’exploitation. 

Si le pointeur de fichier passé en paramètre correspond à un flux ouvert, alors la fonction IS_OPEN retourne la valeur 
TRUE, sinon elle retourne FALSE. 
Syntaxe 

UTL_FILE.IS_OPEN(
ptr_fichier IN FILE_TYPE)
RETURN BOOLEAN ;

3. FCLOSE 

Cette procédure permet de fermer proprement un flux vers un fichier, et de s’assurer que les données situées dans le 
tampon  d’écriture  sont  bien  enregistrées  dans  le  fichier  avant  de  fermer  le  flux  vers  celui­ci.  Si  des  données  sont 
encore présentes dans le tampon au moment de la fermeture du fichier, alors la fonction FCLOSE peut lever l’erreur 
WRITE_ERROR. 
Syntaxe 

UTL_FILE.FCLOSE(ptr_fichier IN OUT FILE_TYPE) ;

4. FCLOSE_ALL 

Cette procédure permet de fermer tous les flux vers des fichiers qui ont été ouverts au cours de la session actuelle. 
Cette procédure ne doit être exécutée qu’avec parcimonie, par exemple lorsque l’on sort du bloc PL/SQL suite à une 
levée d’exception. 
De plus, la fonction FCLOSE_ALL n’affecte pas l’état des autres pointeurs de fichiers détenus par le même utilisateur. 
C’est­à­dire que la fonction IS_OPEN, continuera à retourner vrai (TRUE) lors du test du flux, mais que toute tentative 
d’utilisation de ce flux, soit en lecture, soit en écriture, est vouée à l’échec. 

Syntaxe 

ULT_FILE.FCLOSE_ALL ;

- 2- © ENI Editions - All rigths reserved


5. GET_LINE, GET_LINE_NCHAR, GET_RAW 

Cette procédure permet de lire une ligne entière de texte depuis le fichier identifié par le pointeur qui lui est passé en 
paramètre,  et  retourne  cette  ligne  d’informations  dans  une  variable  tampon  qui  lui  est  également  passée  en 
paramètre. On trouve dans cette variable tampon, l’intégralité du texte sans le marqueur de fin de ligne ou de fin de 
fichier (pour la lecture de la dernière ligne). 

Cette procédure n’est autorisée que si le fichier a été ouvert en mode lecture (r). Dans tous les autres cas, 
l’exception INVALID_OPERATION est levée. 

Si  la  ligne  est  trop  grande  pour  être  contenue  intégralement  dans  la  variable  tampon,  alors  une  exception 
VALUE_ERROR est levée. Au contraire, si l’on tente de lire le texte situé après la marque de fin de fichier, alors une 
exception de type NO_DATA_FOUND est levée. 

Comme le marqueur de fin de ligne n’est pas contenu dans la variable tampon, lors de la lecture, une ligne 
blanche se traduit par une chaîne vide. 

Syntaxe 

UTL_FILE.GET_LINE(
ptr_fichier IN FILE_TYPE,
tampon OUT VARCHAR2,
octets_a_lire IN PLS_INTEGER DEFAULT NULL);

L’opération  GET_LINE_NCHAR  permet  de  lire  du  texte  au  format  UNICODE  depuis  un  fichier  ouvert  à  l’aide  de 
FOPEN_NCHAR. 

Syntaxe 

UTL_FILE.GET_LINE_NCHAR(
ptr_fichier IN FILE_TYPE,
tampon OUT NVARCHAR2,
octets_a_lire IN PLS_INTEGER DEFAULT NULL);

L’opération GET_RAW va, quant à elle, permettre de lire des données de type RAW depuis un fichier. 
Syntaxe 

UTL_FILE.GET_LINE_RAW(
ptr_fichier IN FILE_TYPE,
tampon OUT NOCOPY RAW,
octets_a_lire IN PLS_INTEGER DEFAULT NULL);

6. PUT, PUT_NCHAR, PUT_RAW 

La  procédure  PUT  permet  d’écrire  le  texte  contenu  dans  une  variable  tampon  vers  le  fichier.  Le  fichier  doit  bien 
entendu  avoir  été  ouvert  en  mode  écriture  (w  ou  a).  Aucun  marqueur  de  fin  de  ligne  n’est  ajouté  de  façon 
automatique.  Il  faudra  faire  appel  à  la  procédure  NEW_LINE  pour  ajouter  ce  caractère  de  fin  de  ligne  ou  bien  à  la 
procédure PUT_LINE pour compléter la ligne en cours et la terminer. 
Syntaxe 

UTL_FILE.PUT (
ptr_fichier IN FILE_TYPE,
tampon IN VARCHAR2) ;

La  procédure  PUT_NCHAR  permet  d’écrire une chaîne de caractères UNICODE dans un fichier. La taille maximum du 


tampon est de 32767 octets. La syntaxe de cette procédure est identique à celle de PUT à l’exception du fait que le 
tampon est de type NVARCHAR2. 

La  procédure  PUT_RAW  donne  la  possibilité  d’inscrire  des  données  de  type  RAW  dans  un  fichier.  Il  est  possible  de 
réclamer un vidage automatique du tampon à l’aide du troisième paramètre. 
Syntaxe 

© ENI Editions - All rigths reserved - 3-


UTL_FILE.PUT_RAW(
ptr_fichier IN FILE_TYPE,
tampon IN RAW,
vidageauto IN BOOLEAN DEFAULT FALSE);

7. NEW_LINE 

Cette procédure permet d’ajouter un ou plusieurs caractères de fin de ligne au fichier. Cette procédure est à utiliser 
pour  terminer  une  ligne  écrite  à  l’aide  de  la  procédure  PUT.  Le  nombre  de  caractères  de  fin  de  ligne  ajoutés  par 
défaut est un. 
Syntaxe 

UTL_FILE.NEW_LINE(
ptr_fichier IN FILE_TYPE,
nombre IN NATURAL :=1) ;

8. PUT_LINE 

Contrairement à la procédure PUT, cette procédure permet d’ajouter une ligne d’informations et son marqueur de fin 
au fichier. Cette procédure peut être utilisée pour écrire une ligne dans sa totalité ou pour continuer et terminer une 
ligne dont l’écriture a commencé avec la procédure PUT. 
Syntaxe 

UTL_FILE.PUT_LINE(
ptr_fichier IN FILE_TYPE,
tampon IN VARCHAR2),
vidage_auto IN BOOLEAN DEFAULT FALSE) ;

vidage_auto 

Indique si le tampon doit être écrit sur disque immédiatement. 

9. PUTF, PUTF_NCHAR 

Cette procédure correspond à la procédure PUT, mais il est possible de formater les données. Son fonctionnement est 
similaire à celui de la fonction printf du langage C. Il est possible d’écrire dans le fichier n’importe quel texte, mais les 
caractères suivants possèdent un sens particulier : 

%s 

Ce caractère est remplacé par le paramètre de type caractère qui lui correspond. 

\n 

Ce caractère permet de marquer la fin d’une ligne. 

Syntaxe 

UTL_FILE.PUTF(
ptr_fichier IN FILE_TYPE,
tampon_formaté IN VARCHAR2[,
param1 IN VARCHAR2 DEFAULT NULL,
...
param5 IN VARCHAR2 DEFAULT NULL]);

Les paramètres sont optionnels. Ils sont au maximum au nombre de cinq. Le premier paramètre vient se substituer à 
la  première  occurrence  du  caractère  %s  trouvée  dans  la  chaîne  tampon,  le  deuxième  à  la  deuxième  occurrence  et 
ainsi de suite. 
Exemple 

- 4- © ENI Editions - All rigths reserved


Utilisation de PUTF : 

L’exemple suivant effectue le même travail mais il utilise un objet de type DIRECTORY pour accéder au système de fichiers. 

create directory file_dir as ’c:\temp’;

DECLARE
-- TYPE ptr_fichier IS RECORD (id BINARY_INTEGER);
f_out UTL_FILE.FILE_TYPE;
BEGIN
-- ouvrir le fichier
f_out:=UTL_FILE.FOPEN(’FILE_DIR’,’test.txt’,’w’);
-- ecrire une ligne
UTL_FILE.PUT(f_out,’Ceci est un exemple’);
-- positionner une fin de ligne
UTL_FILE.NEW_LINE(f_out);

-- ecrire une ligne complète


UTL_FILE.PUT_LINE(f_out,’ligne2’);
-- écriture formatée de 2 lignes
UTL_FILE.PUTF(f_out,’Bonjour\n Exemple de %s\n’,’la procédure PUTF’);
UTL_FILE.FFLUSH(f_out);
-- fermer le fichier
UTL_FILE.FCLOSE(f_out);
END;
/

Le nom de l’objet DIRECTORY doit être mis en majuscules dans l’appel à FOPEN. 
La  procédure  PUTF_NCHAR  permet,  quant  à  elle,  l’écriture  de  chaînes  de  caractères  UNICODE  dans  le  fichier  de 
destination. 

10. FFLUSH 

Cette procédure permet d’écrire physiquement les données dans les fichiers, notamment celles qui se trouvent dans 
le tampon d’écriture. En effet, normalement toutes les écritures vers les fichiers sont buffeurisées afin d’optimiser les 
performances  du  disque.  La  procédure  FFLUSH,  permet  de  vider  ce  buffeur.  Naturellement  les  données  doivent  se 
terminer par un caractère de fin de ligne. 

11. FSEEK, FGETPOS 

La  procédure  FSEEK  permet  de  se  déplacer  dans  le  fichier,  en  avant  ou  en  arrière,  du  nombre  d’octets  désiré.  Le 
déplacement peut être absolu, le paramètre offset_absolu prend alors l’adresse sur laquelle il faut se positionner, la 
valeur par défaut est null. 
Dans le cas d’un déplacement relatif, c’est le troisième paramètre (offset_relatif) qui contient le nombre d’octets dont 

© ENI Editions - All rigths reserved - 5-


il faut se déplacer. Si ce nombre est positif, alors le déplacement a lieu vers l’avant, si le nombre est négatif alors le 
déplacement a lieu vers l’arrière. 
Syntaxe 

UTL_FILE.FSEEK(
ptr_fichier IN FILE_TYPE,
offset_absolu IN PLS_INTEGER DEFAULT NULL,
offset_relatif IN PLS_INTEGER DEFAULT NULL);

La fonction FGETPOS permet de connaître l’offset de la position courante dans le fichier. 

Syntaxe 

UTL_FILE.FGETPOS(ptr_fichier IN FILE_TYPE)
RETURN PLS_INTEGER;

12. FREMOVE, FCOPY, FRENAME 

Ces  procédures  permettent  de  réaliser  un  certain  nombre  d’opérations  sur  les  fichiers  du  système  d’exploitation 
lorsque l’accès au répertoire a été accordé. 

Ces  procédures  apportent  une  certaine  souplesse  dans  la  gestion  des  fichiers  extérieurs  à  la  base  de  données  et 
complètent la notion de DIRECTORY (répertoire) qui est introduite à partir de la version 9i. 

L’emplacement est le nom d’un objet de type DIRECTORY qui a été créé à l’aide de la méthode CREATE DIRECTORY. 

Syntaxe 

UTL_FILE.FREMOVE(
emplacement IN VARCHAR2,
nom_fichier IN VARCHAR2);
UTL_FILE.FCOPY(
repertoire_origine IN VARCHAR2,
nom_fichier_origine IN VARCHAR2,
repertoire_destination IN VARCHAR2,
nom_fichier_destination IN VARCHAR2,
numero_ligne_debut IN PLS_INTEGER DEFAULT 1,
numero_ligne_fin IN PLS_INTEGER DEFAULT NULL);
UTL_FILE_FRENAME(
repertoire_origine IN VARCHAR2,
nom_fichier_origine IN VARCHAR2,
repertoire_destination IN VARCHAR2,
nom_fichier_destination IN VARCHAR2,
ecraser IN BOOLEAN DEFAULT FALSE);

13. FGETATTR 

Cette procédure permet de lire et de retourner les attributs courants d’un fichier. 
Syntaxe 

UTL_FILE.FGETATTR(
emplacement IN VARCHAR2,
nom_fichier IN VARCHAR2,
existe OUT BOOLEAN,
taille_fichier OUT NUMBER,
taille_block OUT NUMBER);

14. Les exceptions 

Les principales exceptions qui peuvent être levées lors de l’exécution de ce package sont : 

INVALID_PATH 

- 6- © ENI Editions - All rigths reserved


Chemin d’accès ou nom de fichier incorrect. 

INVALID_MODE 

Le mode d’ouverture du fichier précisé dans FOPEN est incorrect. 

INVALID_FILEHANDLE 

Le pointeur vers le fichier est invalide. 

INVALID_OPERATION 

Il est impossible de travailler avec le fichier. 

READ_ERROR 

Une erreur du système d’exploitation est survenue durant la lecture du fichier. 

WRITE_ERROR 

Une erreur du système d’exploitation est survenue durant une opération d’écriture sur le fichier. 

INTERNAL_ERROR 

Erreur PL/SQL non spécifiée. 

CHARSETMISMATCH 

Un fichier a été ouvert au moyen de la méthode FOPEN_NCHAR mais les opérations suivantes utilisent les fonctions 
PUTF ou GET_LINE et non leur équivalent NCHAR. 

FILE_OPEN 

Echec de l’opération car le fichier est ouvert. 

INVALID_MAXLINESIZE 

La  valeur  du  paramètre  MAX_LINESIZE  lors  de  l’exécution de FOPEN est incorrecte. Ce paramètre doit être compris 


entre 1 et 32767. 

INVALID_FILENAME 

Le nom du fichier n’est pas correct. 

ACCESS_DENIED 

Permission d’accès au fichier refusée. 

INVALID_OFFSET 

Position incorrecte. La position passée en paramètre de la méthode FSEEK doit être plus grande que 0 et inférieure 
au nombre total d’octets dans le fichier. 

DELETE_FAILED 

Échec de suppression du fichier. 

RENAME_FAILED 

Échec lors de la tentative de changement de nom du fichier. 

Les  procédures  du  package  peuvent  également  lever  des  exceptions  Oracle  prédéfinies  comme 
NO_DATA_FOUND ou VALUE_ERROR. 

© ENI Editions - All rigths reserved - 7-


- 8- © ENI Editions - All rigths reserved
Le package DBMS_LOB 
Les initiales LOB permettent d’identifier les objets de grande dimension (Large OBject). 

Le travail avec les éléments de grande dimension (BLOB : Binary LOB, CLOB : Character LOB, NCLOB : uNicode CLOB et 
BFILE:  fichier  binaire)  n’est  pas  aussi  facile  qu’avec  les  données  de  type  plus  classique  (caractère,  nombre,  date).  Le 
langage PL/SQL permet de travailler avec ces données à partir du moment où elles sont présentes dans la base mais 
les opérations de chargement depuis un fichier du système d’exploitation de comparaison ou de modification ne peuvent 
être réalisées qu’à l’aide du package DBMS_LOB. 

1. Les constantes 

Les constantes suivantes sont définies dans le package DBMS_LOB. Leur utilisation permet de clarifier l’utilisation des 
différentes fonctions et procédures du package. 

file_readonly CONSTANT BINARY_INTEGER :=0;


lob_readonly CONSTANT BINARY_INTEGER :=0;
lob_readwrite CONSTANT BINARY_INTEGER :=1;
lobmaxsize CONSTANT INTEGER :=18446744073709551615;
call CONSTANT PLS_INTEGER :=12;
session CONSTANT PLS_INTEGER :=10;

2. APPEND 

Cette procédure permet d’ajouter la totalité de la variable LOB d’origine à la variable LOB de destination. 
Syntaxe 

DBMS_LOB.APPEND(
destination IN OUT NOCOPY BLOB,
source IN BLOB);
DBMS_LOB.APPEND(
destination IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,
source IN CLOB CHARACTER SET destination%CHARSET);

3. CLOSE 

Cette procédure permet de fermer un élément LOB interne ou externe qui a été ouvert précédemment. 
Syntaxe 

DBMS_LOB.CLOSE(
{lob_origine IN OUT NOCOPY BLOB
| lob_origine IN OUT NOCOPY CLOB CHARACTER SET ANY CS
| fichier_origine IN OUT NOCOPY BFILE);

4. COMPARE 

Cette  fonction  permet  de  comparer  deux  LOB  dans  leur  totalité  ou  partiellement.  Il  est  uniquement  possible  de 
comparer des LOB de même type (BLOB, CLOB ou BFILE). Pour les fichiers (BFILE) les éléments doivent être ouverts 
avec FILEOPEN, avant leur comparaison. 

La  fonction  COMPARE  retourne  0  si  les  deux  éléments  à  comparer  sont  parfaitement  identiques  et  une  valeur 
différente de zéro dans le cas contraire. 

Syntaxe 

DBMS_LOB.COMPARE(
lob1 IN {BLOB|CLOB CHARACTER SET ANY_CS|BFILE},
lob2 IN {BLOB|CLOB CHARACTER SET ANY_CS|BFILE},
nombre_octets_a_comparer NUMBER :=DBMS_LOB.LOBMAXSIZE,
octet_origine1 IN INTEGER:=1,

© ENI Editions - All rigths reserved - 1-


octet_origine2 IN INTEGER:=1);

5. COPY 

Cette  procédure  permet  de  réaliser  la  copie  totale  ou  partielle  depuis  un  LOB  d’origine  vers  un  LOB  de  destination. 
Dans  le  cas  d’une  copie  partielle  il  est  possible  de  préciser  la  longueur  (en  nombre  d’octets)  à  copier  ainsi  que  les 
adresses dans le LOB d’origine et de destination. 
Syntaxe 

DBMS_LOB.COPY(
lob_destination IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS},
lob_origine IN{BLOB|CLOB CHARACTER SET lob_destination%CHARSET},
octets_a_copier IN INTEGER,
adr_destination IN INTEGER:=1,
adr_origine IN INTEGER:=1);

6. CREATETEMPORARY, FREETEMPORARY, ISTEMPORARY 

La procédure CREATETEMPORARY permet de créer un CLOB ou un BLOB temporaire. L’espace nécessaire est pris sur le 
tablespace temporaire. 

Le paramètre cache permet de dire si le LOB doit être lu ou non depuis le tampon mémoire. 

Le troisième paramètre permet d’indiquer si l’élément est temporaire à la session (par défaut) ou bien à l’appel. 

Syntaxe 

DBMS_LOB.CREATETEMPORARY(
lob IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS},
cache IN BOOLEAN,
validite IN PLUSIEURS_INTEGER:=DBMS_LOB.SESSION);

La  procédure  FREETEMPORARY  permet  de  libérer  un  objet  temporaire  de  type  CLOB  ou  BLOB  créé  à  l’aide  de 
CREATETEMPORARY. Il est bien sûr recommandé de ne pas attendre la fin de la session ou de l’appel pour que l’objet 
temporaire soit supprimé mais de libérer l’espace qu’il occupe sur le tablespace temporaire le plus rapidement possible 
à l’aide de la procédure FREETEMPORARY. 
Syntaxe 

DBMS_LOB.FREETEMPORARY(
lob IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS});

Enfin  la  fonction  ISTEMPORARY  qui  retourne  un  booléen  permet  de  savoir  si  l’élément  LOB  passé  en  paramètre  est 
temporaire ou non. 

Syntaxe 

DBMS_LOB.ISTEMPORARY(
lob IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS})
return INTEGER;

Exemple 
L’exemple ci­dessous montre la mise en place de ces trois méthodes concernant les éléments LOB temporaires. 

SQL> declare
2 b blob;
3 c clob;
4 begin
5 -- creation des éléments temporaires
6 dbms_lob.createtemporary(b, true);
7 dbms_lob.createtemporary(c,true);
8 -- test et suppression
9 if (dbms_lob.istemporary(b)=1) then
10 dbms_lob.freetemporary(b);
11 end if;
12

- 2- © ENI Editions - All rigths reserved


13 if (dbms_lob.istemporary(c)=1) then
14 dbms_lob.freetemporary(c);
15 end if;
16 end;
17 /

Procédure PL/SQL terminée avec succès.

7. ERASE 

Cette  procédure  a  pour  but  d’effacer  totalement  ou  partiellement  un  objet  LOB.  Dans  le  cas  d’une  suppression 
partielle il est nécessaire de préciser le nombre d’octets à supprimer ainsi que l’adresse de départ. 

Syntaxe 

DBMS_LOB.ERASE(
lob IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANAY_CS},
octets_a effacer IN OUT NOCOPY INTEGER,
adr_depart IN INTEGER:=1);

La  taille  d’un  LOB  n’est pas réduite lorsqu’une partie seulement est effacée. Pour réduire cette taille, il faut 


utiliser la procédure TRIM. 

8. FILEOPEN, FILECLOSE, FILECLOSEALL et ISOPEN 

La procédure FILEOPEN permet d’ouvrir un fichier afin d’y effectuer des lectures. Il n’est pas possible d’écrire dans un 
fichier ouvert à l’aide de cette procédure. 
Syntaxe 

DBMS_LOB.FILEOPEN(
ptr_fichier IN OUT NOCOPY BFILE,
mode_ouverture IN BINARY_INTEGER:=file_readonly);

Les procédures FILECLOSE et FILECLOSEALL permettent de fermer un fichier particulier ou tous les fichiers qui ont été 
utilisés dans le cadre du travail avec les éléments de grande dimension à l’aide du package DBMS_LOB. 
Syntaxe 

DBMS_LOB.FILECLOSE(fichier IN OUT NOCOPY BFILE);


DBMS_LOB.FILECLOSEALL();

Enfin, la fonction ISOPEN qui retourne un entier, permet de savoir si un élément LOB est ouvert ou non. 
Syntaxe 

DBMS_LOB.ISOPEN(
element_lob IN {BLOB|CLOB CHARACTER SET ANY_CS|BFILE})
RETURN INTEGER;

9. FILEEXIST, FILEISOPEN 

Cette fonction retourne un entier indiquant si le fichier existe ou non. Il est intéressant de faire appel à cette fonction 
avant de commencer à travailler avec le fichier, car on peut ainsi éviter de lever un certain nombre d’exceptions. Cette 
fonction vérifie simplement l’existence physique du fichier. 
La fonction retourne 0 si le fichier n’existe pas physiquement et 1 dans le cas contraire. 

Syntaxe 

DBMS_LOB.FILEEXISTS(ptr_fichier IN BFILE) RETURN INTEGER;

© ENI Editions - All rigths reserved - 3-


La fonction FILEISOPEN permet de déterminer si un pointeur de fichier (objet BFILE) correspond à un fichier ouvert (la 
valeur 1 est retournée) ou non (la valeur 0 est retournée). 

Syntaxe 

DBMS_LOB.FILEISOPEN(ptr_fichier IN BFILE) RETURN INTEGER;

10. FILEGETNAME 

Cette  procédure  permet  de  connaître  l’emplacement  et  le  nom  du  fichier  correspondant  à  un  objet  de  type  BFILE. 
Cette procédure n’indique en aucun cas si le répertoire et le fichier existent physiquement. 

Syntaxe 

DBMS_LOB.FILEGETNAME(
fichier IN BFILE,
repertoire OUT VARCHAR2,
nomfichier OUT VARCHAR2);

11. GETLENGTH, GETCHUNKSIZE 

La fonction GETLENGTH permet de connaître la taille de l’élément LOB, BLOB ou BFILE passé en paramètre. La taille est 
un nombre entier qui correspond au nombre d’octets de l’élément passé en paramètre. 
Syntaxe 

DBMS_LOB.GETLENGTH(
{lob_loc IN BLOB
| lob_loc IN CLOB CHARACTER SET ANY_CS
| file_loc IN BFILE}) RETURN INTEGER;

La  fonction  GETCHUNKSIZE  permet  quant  à  elle  de  connaître  la  taille  réellement  utilisée  pour  le  stockage  des 
informations de l’élément LOB à l’intérieur des morceaux (CHUNK) d’espace physique accordés au LOB. Cette taille est 
exprimée en octets. 
Syntaxe 

DBMS_LOB.GETCHUNKSIZE(
{lob_loc IN BLOB
| lob_loc IN CLOB CHARACTER SET ANY_CS
| file_loc IN BFILE}) RETURN INTEGER;

12. INSTR 

Cette  fonction  retourne  un  entier  correspondant  à  la  n ième   occurrence  de  l’élément  cible  recherché.  Le  numéro  de 
l’occurrence  est  indiqué  par  le  paramètre  nième,  et  la  cible  est  contenue  dans  le  paramètre  cible.  La  recherche 
commence  dans  l’élément LOB à partir d’une adresse de départ absolue contenue dans le paramètre adr_depart et 
qui correspond à un nombre d’octets ou de caractères suivant la nature de l’élément LOB. 
Syntaxe 

DBMS_LOB.INSTR(
element_lob IN BLOB,
cible IN RAW,
adr_depart IN INTEGER:=1,
nieme IN INTEGER:=1);

DBMS_LOB.INSTR(
element_lob IN CLOB CHARACTER SET ANY_CS,
cible IN VARCHAR2 CHARACTER SET element_lob%CHARSET,
adr_depart IN INTEGER:=1,
nieme IN INTEGER:=1);

DBMS_LOB.INSTR(
element_lob IN BFILE,

- 4- © ENI Editions - All rigths reserved


cible IN RAW,
adr_depart IN INTEGER:=1,
nieme IN INTEGER:=1);

13. LOADFROMFILE, LOADBLOBFROMFILE, LOADCLOBFROMFILE 

Ces  procédures  permettent  de  charger  des  éléments  LOB  actuellement  contenus  dans  des  fichiers,  à  l’intérieur 
d’éléments LOB de la base de données. Il est bien sûr possible de préciser les adresses absolues du début de la copie 
dans le cadre d’un chargement partiel par l’intermédiaire des paramètres depart_origine et depart_destination. Ces 
adresses sont exprimées en octets. 

Dans tous les cas, il est nécessaire d’indiquer le nombre d’octets à lire depuis le fichier pour construire l’élément LOB 
en mémoire. 
Syntaxe 

DBMS_LOADFROMFILE(
lob_destiniation IN OUT NOCOPY BLOB,
fichier_origine IN BFILE,
nombre_octets IN INTEGER,
depart_destination IN INTEGER:=1,
depart_origine IN INTEGER:=1);

DBMS_LOADBLOBFROMFILE(
lob_destiniation IN OUT NOCOPY BLOB,
fichier_origine IN BFILE,
nombre_octets IN INTEGER,
depart_destination IN OUT INTEGER:=1,
depart_origine IN OUT INTEGER:=1);

DBMS_LOADCLOBFROMFILE(
lob_destiniation IN OUT NOCOPY BLOB,
fichier_origine IN BFILE,
nombre_octets IN INTEGER,
depart_destination IN OUT INTEGER:=1,
depart_origine IN OUT INTEGER:=1,
jeu_caractere_org IN NUMBER,
contexte_langue IN OUT INTEGER,
avertissement OUT INTEGER);

Exemple 
L’exemple ci­dessous illustre comment il est possible d’utiliser les différentes méthodes du package pour charger des images 
dans une table. 

SQL> -- creation de la table de destinations


SQL> create table mesphotos (
2 id number,
3 img blob);

Table créée.

SQL> create sequence seq_id_photos;

Séquence créée.

SQL>
SQL> -- mise en place du répertoire
SQL> create or replace directory img_dir as ’C:\img’;

Répertoire créé.

SQL>
SQL> -- chargement des données
SQL> declare
2 fic_in BFILE;
3 taille number;
4 dest_blob BLOB;
5 vid number;

© ENI Editions - All rigths reserved - 5-


6 begin
7 fic_in:= bfilename(’IMG_DIR’,’BPR.gif’);
8
9 -- ouvrir le fichier
10 dbms_lob.fileopen(fic_in, dbms_lob.file_readonly);
11
12 if (dbms_lob.fileexists(fic_in)=1) then
13
14 -- taille du fichier
15 taille:=dbms_lob.getlength(fic_in);
16 insert into mesphotos values (seq_id_photos.nextval,
empty_blob())
17 return id,img into vid,dest_blob;
18
19 -- lire les données et mémoriser dans une variable
20 dbms_lob.loadfromfile(dest_blob,fic_in, taille);
21
22 -- insérer dans la table
23 update mesphotos set img=dest_blob where id=vid;
24 commit;
25
26 -- fermer le fichier
27 dbms_lob.fileclose(fic_in);
28
29 end if;
30
31 exception
32
33 when dbms_lob.invalid_argval then
34 raise_application_error(-20001,’Mauvais argument’);
35
36 when dbms_lob.access_error then
37 raise_application_error(-20002,’Dépassement capacité’);
38
39 when dbms_lob.noexist_directory then
40 raise_application_error(-20003,’Répertoire inexistant’);
41
42 when dbms_lob.nopriv_directory then
43 raise_application_error(-20004,’Privilèges insuffisant sur
le répertoire’);
44
45 when dbms_lob.unopened_file then
46 raise_application_error(-20007,’Fichier non ouvert’);
47
48 when others then
49 dbms_lob.fileclose(fic_in);
50 raise_application_error(-20008,’ERR’||SQLCODE||’ ’||SQLERRM);
51
52 end;
53 /

Procédure PL/SQL terminée avec succès.

SQL>

14. OPEN 

Cette  procédure  permet  d’ouvrir  un  élément  LOB  dans  le  mode  indiqué  (lob_readonly  ou  lob_readwrite)  à  l’aide  du 
second paramètre. 
Syntaxe 

DBMS_LOB.OPEN(
lob_origine IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS},
mode_ouverture IN BINARY_INTEGER);

- 6- © ENI Editions - All rigths reserved


15. READ 

Cette  procédure  permet  de  lire  en  totalité  ou  en  partie  un  élément  LOB  et  de  placer  le  résultat  de  cette  lecture  en 
mémoire tampon. 

Syntaxe 

DBMS_LOB.READ(
lob_origine IN {BLOB|BFILE},
nombre_octets IN OUT NOCPY BINARY_INTEGER,
adr_depart INT INTEGER,
tampon OUT RAW);
DBMS_LOB.READ(
lob_origine IN CLOB CHARACTER SET ANY_CS,
nombre_octets IN OUT NOCPY BINARY_INTEGER,
adr_depart INT INTEGER,
tampon OUT VARCHAR2 CHARACTER SET lob_
origine%CHARSET);

16. SUBSTR 

Cette fonction offre la possibilité d’extraire une sous­chaîne depuis l’élément LOB. C’est en fait l’ensemble des octets 
lus à partir de l’adresse de départ passé en paramètre ainsi que le nombre d’octets à lire qui est retourné. 
Syntaxe 

DBMS_LOB.SUBSTR(
lob_origine IN BLOB,
nombre_octets IN INTEGER:=32767,
adr_depart IN INTEGER:=1) RETURN RAW;

DBMS_LOB.SUBSTR(
lob_origine IN CLOB CHARACTER SET ANY_CS,
nombre_octets IN INTEGER:=32767,
adr_depart IN INTEGER:=1)
RETURN VARCHAR2 CHARACTER SET lob_origine%CHARSET;

17. TRIM 

Cette  procédure  permet  de  réduire  la  taille  d’un  élément  LOB  au  nombre  d’octets  ou  de  caractères  précisé  dans  le 
paramètre nouvelle_taille. 

Syntaxe 

DBMS_LOB.TRIM(
lob_origine IN OUT NOCOPY {BLOB|CLOB CHARACTER SET ANY_CS},
nouvelle_taille IN INTEGER);

18. WRITE, WRITEAPPEND 

La procédure WRITE permet de d’écrire un nombre d’octets dans un élément LOB interne, à partir d’une adresse de 
départ.  La  procédure  WRITE  remplace  toutes  les  informations  qui  existent  déjà  dans  l’élément  LOB  cible  à  partir  de 
l’adresse de départ. 
Syntaxe 

DBMS_LOB.WRITE(
lob_destination IN OUT NOCOPY BLOB,
nombre_octets IN BINARY_INTEGER,
adr_depart IN INTEGER,
tampon IN RAW);
DBMS_LOB.WRITE(
lob_destination IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,
nombre_octets IN BINARY_INTEGER,

© ENI Editions - All rigths reserved - 7-


adr_depart IN INTEGER,
tampon IN VARCHAR2 CHARACTER SET lob_origine%CHARSET);

La  procédure  WRITEAPPEND  permet  d’écrire  les  données  de  type  LOB  actuellement  dans  le  tampon  à  la  fin  de 
l’élément LOB de destination. 
Syntaxe 

DBMS_LOB.WRITEAPPEND(
lob_destination IN OUT NOCOPY BLOB,
nombre_octets IN BINARY_INTEGER,
tampon IN RAW);

DBMS_LOB.WRITEAPPEND(
lob_destination IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,
nombre_octets IN BINARY_INTEGER,
tampon IN VARCHAR2 CHARACTER SET
lob_origine%CHARSET);

19. Les exceptions 

Les principales exceptions du package DBMS_LOB sont : 
INVALID_ARGVAL 

Les arguments des fonctions et des procédures attendent des valeurs non NULL, mais un argument a reçu la valeur 
NULL ou bien une valeur en dehors du domaine de définition de l’argument. 

ACCESS_ERROR 

Tentative d’écriture sur un LOB qui dépasse la taille limite. 

NOEXIST_DIRECTORY 

L’élément de type DIRECTORY n’existe pas pour le fichier actuel. 

NOPRIV_DIRECTORY 

L’utilisateur ne possède pas les droits nécessaires sur le DIRECTORY (répertoire) ou sur les fichiers pour mener à bien 
ses opérations. 

INVALID_DIRECTORY 

La référence au répertoire (DIRECTORY) n’est pas valide dans le cas d’un premier accès ou sa définition a été modifiée 
par l’administrateur de bases de données depuis la dernière utilisation. 

OPERATION_FAILED 

Échec de l’opération. 

UNOPENED_FILE 

Le fichier n’est pas ouvert. 

OPEN_TOOMANY 

Le  nombre  de  fichiers  ouverts  simultanément  a  atteint  la  limite  supérieure.  Il  est  donc  nécessaire  de  fermer  des 
fichiers pour pouvoir continuer. 

- 8- © ENI Editions - All rigths reserved


Introduction 
À partir de la version 8i du SGBDR Oracle, le langage Java est totalement intégré au moteur de la base de données. Il 
va donc être possible d’écrire du code en Java qui sera stocké et exécuté directement dans la base de données. 

La machine virtuelle Java intégrée dans le moteur Oracle, est totalement compatible avec le JDK de Sun. 
 
La version du JDK est fixée suivant la version Oracle utilisée.

Cette machine virtuelle s’exécute dans le même processus et partage le même espace mémoire que le moteur de la 
base  de  données.  Cette  solution  offre  de  très  bons  temps  d’accès  aux  données.  La  machine  virtuelle  est  un 
environnement d’exécution Java qui supporte toutes les structures, les méthodes et la gestion des erreurs propres à 
Java. 

Choisir Java pour développer du code côté serveur, c’est obtenir une solution applicative écrite entièrement en Java et 
donc limiter le nombre de langages différents à apprendre. 
Le langage Java peut intervenir pour l’écriture de procédures, de fonctions et de déclencheurs (triggers) de base de 
données. 
Les avantages des procédures stockées sont nombreux. Les plus importants sont : 

● la performance : car le code exécutable est géré par le serveur et il y est maintenu en mémoire. 

● la facilité de mise en place et de déploiement : tous les utilisateurs accèdent au même code. 

● la sécurité : il est possible, en utilisant la sécurité Oracle, d’obliger les utilisateurs à manipuler les données au 
travers des procédures stockées et de ne leur accorder aucun droit sur les tables accédées par les procédures. 

Le développement d’applications Java en lien avec la base Oracle n’entre pas dans le cadre de cet ouvrage. 

La  présentation  suivante  permet  d’explorer  les  capacités  d’Oracle  à  travailler  avec  des  procédures  stockées 
Java.  Ce  chapitre  ne  peut  pas  être  considéré  comme  un  apprentissage  de  Java  et  suppose  d’avoir  déjà 
quelques notions de langage Java. 

© ENI Editions - All rigths reserved - 1-


Chargement des procédures stockées 
Avant  de  pouvoir  utiliser  les  procédures,  elles  doivent  être  chargées  dans  la  base  de  données.  Le  chargement  des 
procédures et leur publication sont deux étapes distinctes. De nombreuses classes Java sont chargées mais ne sont 
jamais publiées car elles ne présentent pas d’interface utilisateur. 
 
Ici un utilisateur représente un programmeur PL/SQL.

Pour charger les classes Java dans la base de données, nous utiliserons l’utilitaire en ligne de commandes 
loadjava. 

1. Généralités 

Pour chaque classe chargée dans la base de données par loadjava, un objet est créé et le nom de cet objet est issu 
du nom complet de la classe Java. Dans cet objet sont conservés le code source, le code exécutable et les différentes 
ressources nécessaires à la bonne exécution de la classe. Loadjava conserve également les différentes valeurs des 
options dans une table. 
Le  programme  Java  peut  être  mis  au  point  par  un  outil  de  développement  externe  à  la  base  de  données,  puis  le 
fichier  .class  est  chargé  par  loadjava.  Mais  on  peut  tout  à  fait  charger  le  fichier  source  (.java)  et  le  code  est  alors 
compilé dans la base de données. 
Le  nom  de  l’objet  créé  reprend  le  nom  complet  de  la  classe  Java,  c’est­à­dire  le  nom  du  package  et  le  nom  de  la 
classe. Ces noms peuvent avoir une longueur maximum de 4000 caractères dans la base de données. Mais Oracle 
autorise  des  identifiants  d’une  longueur  maximum  de  30  caractères  pour  les  objets  de  la  base  de  données.  Il  faut 
donc mettre en place une résolution de nom afin de pouvoir manipuler ces objets depuis PL/SQL. 

2. Les droits d’utilisation 

Par  défaut,  les  procédures  stockées  Java  utilisent  les  privilèges  accordés  à  l’utilisateur  Oracle  qui  exécute  la 
procédure.  Ce  type  de  résolution  de  droits  permet  de  personnaliser  au  mieux  les  privilèges  accordés  à  chaque 
utilisateur. De plus, le code peut être centralisé en un point précis de la base de données et être utilisé de différentes 
façons. 

© ENI Editions - All rigths reserved - 1-


Ce problème est expliqué par l’exemple suivant : 

Dans  cet  exemple  les  deux  utilisateurs  Pierre  et  Anne  utilisent  la  même  procédure  stockée  Java  (Analyse)  qui 
intervient sur la table Ventes. Comme la procédure stockée s’exécute en utilisant les droits accordés à l’utilisateur qui 
l’exécute, elle accède aux tables que l’utilisateur possède. Donc dans ce cas le même code est partagé pour analyser 
deux tables totalement différentes. 

3. L’utilitaire Loadjava 

Syntaxe 

loadjava {-user| -u} nom_utilisateur /mot_de_passe[@service]


[ {andresolve | a}
| debug
| {definer | d} nom_du_schéma_d’encodage
| {encoding | e} schéma_codage
| {force | f}
| {grant | g} {utilisateur|role}
| {oci8 | o}
| oracleresolver
| {resolve | r}
| {resolver | R} "spécification"
| {schema | S} nom_schema
| {synonym | s}
| {thin | t}
| {verbose | v}
]
nom_de_fichier ...

andresolve 

Avec cette option, chaque classe chargée est marquée comme valide, c’est­à­dire que toutes les classes auxquelles 
elle fait référence sont censées être dans la base. 

resolve 

Avec  cette  option,  la  classe  est  chargée  dans  la  base  puis  une  résolution  est  effectuée  pour  savoir  si  toutes  les 

- 2- © ENI Editions - All rigths reserved


classes Java utilisées sont présentes dans la base. Si c’est le cas, alors la classe chargée est marquée comme valide. 

Les options resolve et andresolve sont mutuellement exclusives. Si aucune des deux options n’est précisée, 
alors la résolution des classes est effectuée au moment de l’exécution. 

resolver 

Cette option permet d’indiquer un chemin (ensemble de schémas) à utiliser pour trouver les objets référencés dans la 
classe  nouvellement  chargée.  Cette  option  s’apparente  à  la  variable  CLASSPATH  que  l’on  utilise  dans  une 
programmation Java classique. 

oracleresolver 

Cherche  les  objets  dans  le  schéma  de  l’utilisateur  courant  et  dans  le  schéma  public.  Si  les  classes  demandées  n’y 
sont pas, alors l’objet nouvellement chargé est marqué comme invalide. 

debug 

Permet de générer des informations de débogage. Cette option est similaire à javac ­g. 

definer 

Permet  d’utiliser  la  méthode  avec  les  droits  de  l’utilisateur  qui  a  créé  cette  méthode  et  non  pas  ceux  accordés  à 
l’utilisateur qui utilise la méthode. 

encoding 

Cette option permet de fixer la table de caractères utilisée par le JDK pour encoder les fichiers. Par défaut, la page de 
caractères utilisée est latin1. 

force 

La  classe  va  être  chargée  dans  la  base  même  si  elle  y  existe  déjà.  Sans  cette  option,  l’action  de  chargement  est 
rejetée. Cette option est particulièrement intéressante dans les opérations de mise à jour des classes. 

grant 

Permet  d’accorder  le  droit  d’exécution  de  la  procédure  dès  son  chargement.  Cette  action  est  similaire  à  celle  de 
l’ordre SQL GRANT. 

oci8 

Autorise loadjava à communiquer avec la base en utilisant le pilote OCI JDBC. C’est le mode de communication par 
défaut. 

thin 

Loadjava utilise dans ce cas le pilote thin JDBC pour communiquer avec la base. 
 

Les options oci8 et thin sont mutuellement exclusives.

schema 

Les objets Java nouvellement créés sont affectés au schéma précisé par ce paramètre. Par défaut ils sont créés dans 
le schéma de l’utilisateur courant. 

synonym 

Un synonyme public est créé pour rendre les classes facilement accessibles. 

verbose 

© ENI Editions - All rigths reserved - 3-


Active le mode "bavard", des messages de progression sont affichés. 

Exemple 

Le code source 

La classe est chargée dans la base de données. 

Utilisation de loadjava pour charger la classe dans le schéma livre 

4. L’utilitaire Dropjava 

À l’inverse de l’utilitaire Loadjava, Dropjava permet de supprimer un objet Java depuis la base de données. Cet outil 
permet de supprimer aussi bien des fichiers source (.java), des fichiers .class, ou bien de ressources .jar ou .zip. 
Syntaxe 

dropjava {-user| -u} nom_utilisateur /mot_de_passe[@service]


[{oci8 | o}
| {schema | S} nom_schema
| {thin | t}
| {verbose | v}
]
nom_de_fichier ....

Les options disponibles pour cet outil ont la même signification que dans l’utilitaire Loadjava. 

Exemple 
Suppression de la classe depuis le schéma livre 

- 4- © ENI Editions - All rigths reserved


5. L’accès aux données 

Que le programme Java s’exécute sur le poste client ou sur le serveur de base de données comme c’est le cas ici, le 
problème  de  l’accès  aux  données  se  pose  toujours.  Avec  Java,  Oracle  offre  deux  solutions  distinctes  d’accès  aux 
données. Il est possible d’utiliser la solution classique JDBC qui est déjà bien connue et c’est son principal avantage. 
Une alternative à cette solution est proposée par l’intermédiaire de SQLJ. Avec cette technique, les commandes SQL 
sont saisies directement dans le programme Java. Puis le fichier est enregistré avec l’extension sqlj au lieu de java. 
La compilation du fichier SQLJ peut avoir lieu sur le poste client sur lequel est développé le code Java ou bien sur le 
serveur.  Il  est  préférable  de  réaliser  une  compilation  sur  le  poste  de  développement  car  cela  permet  une  mise  au 
point plus facile si des erreurs de compilation sont présentes. 
Les fichiers .class ou .jar peuvent alors être chargés sur le serveur par l’intermédiaire de la commande loadjava. 

a. JDBC 

La mise en place d’une solution JDBC va permettre d’utiliser des outils connus et indépendants de la base Oracle. 
Cette méthode est particulièrement bien adaptée dans le développement d’outils clients en Java qui ne doivent pas 
être  liés  de  façon  trop  contraignante  à  la  base  de  données  Oracle.  Pour  l’écriture  de  procédures  stockées,  la 
syntaxe JDBC peut s’avérer un peu lourde comparée au SQLJ. 
Dans cet ouvrage, de nombreux exemples Java utilisent la technologie JDBC pour travailler avec les données issues 
de la base de données. 

b. SQLJ 

SQLJ  est  une  solution  d’accès  aux  données,  spécifique  à  Oracle,  qui  est  bien  adaptée  dans  le  cadre  des 
développements Java étroitement liés à la base Oracle. En effet, grâce à SQLJ il est possible de faire référence à 
des  variables  Java  directement  dans  les  instructions  SQL,  et  pour  les  applications  s’exécutant  sur  le  serveur  de 
base de données, la gestion de la connexion est implicite, ce qui simplifie encore le code. 

Pour  que  le  précompilateur  SQLJ  transforme  les  instructions  SQLJ  en  appels  de  méthodes,  les  instructions  SQLJ 
doivent obligatoirement commencer par #SQL et l’instruction SQL est entre accolades {}. 

Exemple 
Le code Java ci­dessous montre comment il est possible d’intégrer les commandes SQLJ dans le code Java. 

import java.sql.*;
class Comptes{
public static int CompteClients(){
int nombre=0;
try{
#sql{SELECT COUNT(*) INTO :nombre FROM CLIENTS};
return nombre;
} catch(SQLException e){
}finally{
return nombre;
}
}
}

Il est ensuite nécessaire de compiler le fichier sqlj afin de générer le fichier class. 

sqlj Comptes.sqlj

Enfin, le fichier class doit être chargé dans la base à l’aide de l’utilitaire loadjava. 

loadjava -user scott/tiger@bdeni -v Comptes.class

© ENI Editions - All rigths reserved - 5-


Publication des procédures stockées 
Avant  de  pouvoir  utiliser  une  procédure  stockée  Java  directement  depuis  SQL,  il  faut  inscrire  les  références  de  cette 
procédure dans le dictionnaire de données. Cette opération n’est pas automatique car le moteur Oracle ne peut pas 
savoir quelles méthodes seront accessibles depuis le SQL. 
Pour une méthode Java, il faut créer une fonction (méthode de type void) ou une procédure PL/SQL à l’aide des ordres 
CREATE FUNCTION et CREATE PROCEDURE. Ces fonctions et procédures peuvent éventuellement être regroupées dans 
un  package.  Le  corps  de  ces  fonctions  et  procédures  contiendra  la  clause  LANGUAGE  JAVA  afin  d’enregistrer  le  nom 
complet de la méthode, la valeur de retour et les paramètres. 

1. Correspondance des types de données 

La correspondance entre les types de données SQL et Java est régie par le tableau page suivante. 

Type SQL  Classe Java 

CHAR ­ NCHAR ­ LONG ­ VARCHAR2 ­ NVARCHAR2  oracle.sql.CHAR 

java.lang.String 

java.sql.Date 
java.sql.Time 

java.sql.Timestamp 

java.lang.Byte 

java.lang.Short 

java.lang.Integer 

java.lang.Long 
java.lang.Float 

java.lang.Double 

java.lang.BigDecimal 

byte ­ short ­ int ­ long ­ float ­ double 

DATE  oracle.sql.DATE 

java.sql.Date 

java.sql.Time 
java.sql.Timestamp 

java.lang.String 

NUMBER  oracle.sql.NUMBER 
java.lang.Byte 
java.lang.Short 

java.lang.Integer 
java.lang.Long 

java.lang.Float 
java.lang.Double 
java.lang.BigDecimal 

byte ­ short ­ int ­ long ­ float ­ double 

RAW ­ LONG RAW  oracle.sql.RAW 
byte[] 

© ENI Editions - All rigths reserved - 1-


ROWID  oracle.sql.CHAR 
oracle.sql.ROWID 

java.lang.String 

BFILE  oracle.sql.BFILE 

BLOB  oracle.sql.BLOB 
oracle.jdbc2.Blob 

CLOB ­ NCLOB  oracle.sql.CLOB 

oracle.jdbc2.Clob 

OBJECT  oracle.sql.STRUCT 
oracle.jdbc2.Struct 

REF  oracle.sql.REF 

oracle.jdbc2.Ref 

TABLE ­ VARRAY  oracle.sql.ARRAY 

oracle.jdbc2.ArrayArray 

2. Création d’une fonction Java ou d’une procédure Java 

Syntaxe 

CREATE [OR REPLACE]


{PROCEDURE nom_procédure [(paramètre, ...)]
| FUNCTION nom_fonction [(paramètre, ...)] RETURN type_sql}
[AUTHID {DEFINER|CURRENT_USER}]
[PARALLEL_ENABLE]
[DETERMINISTIC]
{AS | IS } LANGUAGE JAVA
NAME ’nom_méthode_java (paramètre_java,...)’;

AUTHID 

Permet de définir le type de privilèges à utiliser lors de l’exécution de la méthode, soit ceux de l’auteur de la méthode, 
soit ceux de l’utilisateur de la méthode (par défaut). 
 

Il n’est pas possible d’écraser un choix réalisé avec Loadjava.

PARALLEL_ENABLE 

La méthode peut s’exécuter dans un environnement parallèle car elle ne fait référence à aucune valeur de type static. 

DETERMINISTIC 

Lorsque le résultat de la fonction ne dépend pas de variables de session, alors l’optimiseur peut réutiliser le résultat 
déjà obtenu lors d’un appel précédent avec les mêmes paramètres. 

Exemples 

Définition de la procédure associée à la méthode Supprime : 

- 2- © ENI Editions - All rigths reserved


 

L’exemple  ci­après  définit  une  fonction  qui  retourne  le  nombre  d’éléments  dans  la  table  dont  le  nom  est  passé  en 
paramètre. 
Le code java 

Par l’intermédiaire de l’utilitaire Loadjava, la classe est chargée dans la base. 

Puis une fonction de type PL/SQL est créée afin de pouvoir utiliser la fonction Java dans la base. 

Définition de la fonction associée à la méthode Compte 

© ENI Editions - All rigths reserved - 3-


 

3. CREATE JAVA 

L’instruction DDL CREATE JAVA permet de créer une procédure, une fonction ou une ressource Java depuis l’invite SQL 
sans passer par l’utilitaire loadjava. L’utilisation d’une telle commande est réservée au code java pour lequel le risque 
d’erreurs de compilation est rare car la mise au point est plus difficile. 

Comme toutes les commandes du DDL il est nécessaire d’avoir un privilège particulier (ici CREATE PROCEDURE) pour 
pouvoir exécuter cette instruction. 

Syntaxe 

CREATE [OR REPLACE] [AND {COMPILE|RESOLVE}]


JAVA {{SOURCE|RESOURCE}NAMED nom_procedure | CLASS}
{AS code_source_java|USING BFILE(repertoire,fichier)};

La  syntaxe  ci­dessus  est  un  extrait  de  la  syntaxe  complète  de  la commande  CREATE  JAVA.  C’est  cette  syntaxe  qui 
servira le plus souvent mais il possible de la compléter lors de l’utilisation de données de type BLOB, CLOB ou BFILE 
ou lorsque la procédure doit être créée sur un schéma différent de l’utilisateur courant. 
Exemple 

L’exemple ci­dessous montre la mise en place d’une fonction Java à l’aide de la commande CREATE JAVA. 

create or replace and compile java source named "Compte" as


public class Compte{
public static int Compte(int a, int b){
int resultat;
resultat=a+b;
return resultat;
}
};
/

Dans l’exemple suivant c’est, cette fois, un fichier class qui est chargé dans la base à l’aide de la commande CREATE JAVA. 

create or replace directory bfile_dir as ’c:\O9i’;

create or replace java class using bfile (bfile_dir,’Comptes.class’);


/

- 4- © ENI Editions - All rigths reserved


Utilisation des procédures stockées 
Après avoir chargé et publié les procédures stockées écrites en Java, il faut les utiliser. Le but de cette section est de 
montrer les différents moyens possibles pour appeler les procédures Java. 

1. Appel d’une procédure Java depuis SQL*Plus 

L’instruction CALL

L’instruction CALL permet d’appeler depuis le prompt PL/SQL une procédure stockée Java qui a été publiée en tant que 
fonction, procédure ou élément d’un package. 

Syntaxe 

CALL [nom_schéma.][nom_package.]
{nom_procedure(paramètre,...)|nom_fonction(paramètre,...)}

Les paramètres sont définis dans SQL*Plus et peuvent être des littéraux ou bien des variables hôtes. 
Exemple 

Utilisation de la fonction Compte pour connaître le nombre de clients présents dans la table. 

Création de la table TTEST puis suppression par la procédure Java Supprime_le. 

Rediriger les sorties

Certaines  procédures  stockées  Java  utilisent  le  flux  standard  d’erreur  (System.err)  ou  de  sortie  (System.out)  pour 
afficher  certaines  informations.  Il  est  possible  de  rediriger  ces  flux  vers  SQL*Plus  en  utilisant  simplement  les  deux 
commandes suivantes : 

SET SERVEROUTPUT ON [SIZE taille]


CALL dbms_java.set_output(taille)

Avec ce principe, les données sont affichées dès que la procédure est terminée. Le paramètre taille, dont la valeur par 
défaut est 2000 octets permet de préciser la taille du tampon. Cette taille ne peut pas être supérieure à 1 000 000 
d’octets. 

© ENI Editions - All rigths reserved - 1-


Exemple 
Le code source. La procédure Java est utilisée pour afficher directement le nom des différents clients. 

La  classe  va  être  chargée  dans  la  base  par  l’intermédiaire  de  Loadjava.  Une  procédure  PL/SQL  est  associée  à  la  méthode 
Java. 

La publication dans la base. 

Utilisation de la procédure depuis SQL*Plus. 

- 2- © ENI Editions - All rigths reserved


 

2. Appel d’une procédure Java depuis un déclencheur de base de données 

Un déclencheur de base de données est un programme associé à une table ou une vue. Ce programme est exécuté 
automatiquement par Oracle lorsque l’opération DML (INSERT, UPDATE ou DELETE) à laquelle le déclencheur est lié, est 
exécutée sur la table ou sur la vue. Après la définition du trigger : nom, table ou vue associée, ordre DML déclencheur, 
avant ou après vérification des contraintes d’intégrité, la procédure liée à la méthode Java est appelée à l’aide de la 
fonction CALL. Le corps déclencheur est alors réduit au maximum. 
Exemple 
La  classe  Declencheurs  propose  une  méthode  qui  permet  de  réduire  le  stock  à  chaque  nouvelle  commande  d’articles.  La 
classe est chargée dans la base à l’aide de l’utilitaire Loadjava. Création de la procédure MAJStock. 

Le déclencheur est posé sur la table LIGNESCDE et il est associé à l’ordre INSERT. Le déclencheur est exécuté pour chaque 
ligne créee. Création du déclencheur. 

3. Appel d’une procédure Java depuis une instruction SQL DML ou un bloc PL/SQL 

Comme une fonction ou une procédure de type PL/SQL est associée à la méthode Java, l’utilisation de cette fonction 
ou procédure est similaire à celle d’une fonction ou procédure écrite entièrement en PL/SQL. 

Les packages

La mise en place de méthodes Java n’est pas toujours évidente et de plus il est aberrant de créer autant de classe 
Java  que  de  méthodes.  Au  niveau  Java,  toutes  les  méthodes  traitant  d’un  même  sujet,  par  exemple  la  gestion  des 
commandes, sont regroupées dans la même classe. Pour maintenir cette cohérence de regroupement au niveau de la 
programmation dans la base de données, les fonctions et les procédures associées aux méthodes sont regroupées 
dans un package. 
Bien  sûr,  un  tel  package  ne  diffère  pas  d’un  package  PL/SQL  et  se  comporte  de  la  même  façon.  Le  point  le  plus 
important étant que le package reste entièrement en mémoire et permet ainsi d’offrir de meilleurs temps de réponse 

© ENI Editions - All rigths reserved - 3-


que si les fonctions et les procédures étaient indépendantes les unes des autres. 
Exemple 

Création de la classe Commandes. 

import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;

public class Commandes{


public static float montant(int nocde) throws SQLException{
Connection conn=new OracleDriver().defaultConnection();
String requete="Select sum(qtecde*prix) from lignescde l, articles a where
a.refart=l.refart and l.nocde="+nocde;
float mt=0;
try{
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(requete);
while (rs.next()){mt=rs.getFloat(1); }
rs.close();
stmt.close();
} catch(SQLException e){System.err.println(e.getMessage());}
return mt;
}

public static void livrer(int nocde) throws SQLException


{ changeEtat(nocde,"LI"); }
public static void solder(int nocde) throws SQLException
{ changeEtat(nocde,"SO"); }

private static void changeEtat(int nocde, String etat) throws


SQLException{
Connection conn=new OracleDriver().defaultConnection();
String requete="Update commandes set etat=’"+etat+"’
where nocde="+nocde;
try{ Statement ordre=conn.createStatement();
ordre.executeQuery(requete);
ordre.close();
} catch (SQLException e) {System.err.println(e.getMessage());}

}
}

La classe est chargée dans la base par l’intermédiaire de la commande Loadjava. Le package lui correspondant sera 
créé en deux étapes. Tout d’abord l’en­tête du package est défini : 

Puis le corps du package est défini. 

- 4- © ENI Editions - All rigths reserved


 

L’utilisation  d’une procédure ou d’une  fonction  de  ce  package  est  en  tout  point  identique  à  celle  d’un  package  écrit 
entièrement en PL/SQL. 
Exemple 

Utilisation de la fonction Montant pour connaître le montant de la commande n°1. 

© ENI Editions - All rigths reserved - 5-


Introduction 
Le parser (analyseur) XML permet de manipuler des fichiers XML depuis le langage PL/SQL. Il est ainsi possible de lire et 
de générer des fichiers au format XML. Pour pouvoir mettre en place ces éléments, le langage PL/SQL utilise le package 
xmldom afin de connaître et d’analyser la structure du document XML. 

Le  langage  PL/SQL,  qui  est  couramment  utilisé  par  les  développeurs  Oracle,  voit  ainsi  ses  possibilités  évoluer  vers  le 
XML.  Le  parser  XML  pour  PL/SQL  a  été  écrit  en  PL/SQL  et  en  Java.  Il  supporte  toutes  les  spécifications  émises  par  le 
W3C pour la norme 1.0 de XML. En plus du respect total de la norme, le parser XML pour PL/SQL permet une analyse 
simplifiée  du  document  par  le  respect  des  consignes  du  W3C  concernant  le  modèle  de  document  (DOM  :  Document 
Object Model). Il respecte également les recommandations concernant XSLT (les feuilles de styles) et Xpath. 

Le parser est situé dans le répertoire $ORACLE_HOME\xdk\plsql\parser. Il est inclus en standard à partir de la 
version 9i. 

Le schéma suivant résume simplement comment fonctionne le parser pour l’analyse d’un document. Cette arborescence est 
ensuite  mise  en  œuvre  dans  les  exemples  qui  suivent  afin  de  connaître  la  structure  d’un  document  ainsi  que  les  données 
contenues dans ce document. 

Ainsi, tous les programmes possèdent la même structure pour pouvoir analyser un document XML, qui est la suivante : 

● Créer un nouvel objet de type Parser à l’aide de la fonction newParser et commencer l’analyse du document XML 
ainsi que de sa DTD si elle est disponible. 

● Ensuite, il faut utiliser la source XML ou DTD qui peut être de type varchar2, CLOB (Character Large Object Binary) 
ou un fichier. 

● Suivant  le  type  de  la  source,  les  méthodes  possibles  sont  parse()  ou  parseDTD()  si  les  informations  sont 
contenues  dans  un  fichier,  parseBuffer()  ou  parseDTDBuffer()  si  les  informations  sont  contenues  dans  un 
élément  de  type  varchar2  et  enfin  parseClob()  ou  bien  parseDTDClob()  si  les  informations  sources  sont 
conservées dans un élément de type CLOB. 

● Pour  les  documents  XML  uniquement  qui  sont  analysés  à  l’aide  d’une  des  fonctions  parse,  parseBuffer  ou 
parseClob, le résultat de l’exécution de ces méthodes est placé dans un document accessible par getDocument
(). 

© ENI Editions - All rigths reserved - 1-


● La méthode getDocument() va permettre d’obtenir le résultat de l’analyse et permet également d’appliquer les 
autres méthodes du modèle DOM. 

● La  méthode  freeDocument  va  permettre  de  libérer  les  ressources  actuellement  détenues  par  le  parser  sur  le 
document actif afin de rendre possible l’analyse d’un autre document. 

● Enfin, l’instruction freeParser() permet de libérer toutes les ressources. 

- 2- © ENI Editions - All rigths reserved


Lire un fichier XML 
La  première  étape  consiste  à  être  capable  de  lire  un  fichier  au  format  XML  depuis  le  langage  PL/SQL  et  de  bien 
interpréter  les  données  issues  de  ce  fichier.  Pour  bien  comprendre  comment  fonctionne  le  parser,  la  méthode  la  plus 
simple consiste sans doute à passer par un petit programme d’exemple. Toutes les fonctionnalités du parser ne seront 
pas illustrées mais à partir d’un exemple qui fonctionne, il est toujours possible de compléter les éléments manquants 
de façon relativement simple. 

Le  script  suivant  va  donc  permettre  la  création  d’une  procédure  qui  accepte  en  paramètre  un  nom  de  fichier  xml  et  qui  va 
l’ouvrir afin d’interpréter les données qu’il contient. 

rem Cette procédure permet d’afficher les différents éléments


du document XML
create or replace procedure afficherElements(doc xmlDom.DOMDocument) is
lesNoeuds xmlDom.DOMNodeList;
longueur number;
noeud xmlDom.DOMNode;
begin
-- obtenir tous les éléments du document
lesNoeuds:=xmlDom.getElementsByTagName(doc,’*’);
longueur:=xmlDom.getLength(lesNoeuds);

-- parcourir tous les éléments à l’aide d’une boucle


for i in 0 ..longueur-1 loop
noeud:=xmlDom.item(lesNoeuds, i);
dbms_output.put(xmlDom.getNodeName(noeud)||’ ’);
end loop;
-- passer à la ligne suivante
dbms_output.put_line(’ ’);
end;
/
show errors;

create or replace procedure afficherAttributs(doc xmlDom.DOMDocument) is


lesNoeuds xmlDom.DOMNodeList;
lg1 number;
lg2 number;
noeud xmlDom.DOMNode;
element xmlDom.DOMElement;
lesAttributs xmlDom.DOMNamedNodeMap;
nomAttr varchar2(100);
valeurAttr varchar2(100);
begin

-- obtenir tous les éléments


lesNoeuds:=xmlDom.getElementsByTagName(doc,’*’);
lg1:=xmlDom.getLength(lesNoeuds);

-- parcourir tous les éléments


for i in 0..lg1-1 loop
noeud:=xmldom.item(lesNoeuds, i);
element:=xmldom.makeElement(noeud);
-- nom de la balise
dbms_output.put_line(xmldom.getTagName(element)||’:’);

-- obtenir tous les attributs de cet élément


lesAttributs:=xmldom.getAttributes(noeud);

if (xmldom.isNull(lesAttributs)= FALSE) then


lg2:=xmldom.getLength(lesAttributs);

-- parcourir tous les attributs


for j in 0..lg2-1 loop
noeud:=xmldom.item(lesAttributs,j);
nomAttr := xmldom.getNodeName(noeud);
valeurAttr := xmldom.getNodeValue(noeud);
dbms_output.put(’ ’||nomAttr||’=’||valeurAttr);
end loop;
dbms_output.put_line(’ ’);

© ENI Editions - All rigths reserved - 1-


end if;
end loop;
end;
/
show errors;

create or replace procedure lirexml(repertoire in varchar2,


fichier in varchar2,
fichier_erreur in varchar2) is
p xmlparser.parser;
doc xmldom.DOMDocument;
begin
-- nouveau parser
p:=xmlparser.NewParser;

-- fixer quelques caractéristiques du parser


xmlParser.SetValidationMode(p,FALSE);
xmlParser.SetErrorLog(p, repertoire||’\’||fichier_erreur);
xmlParser.setBaseDir(p, repertoire);

--analyser le fichier XML


xmlParser.Parse(p,repertoire||’\’||fichier);

-- obtenir le document
doc:=xmlParser.GetDocument(p);

-- afficher les différents éléments


dbms_output.put_line(’Les éléments du documents sont :’);
afficherElements(doc);

-- afficher les attributs de chaque élément


dbms_output.put_line(’Les attributs des éléments sont:’);
afficherAttributs(doc);

-- libérer le document
xmlDom.freeDocument(doc);
-- libérer le parser
xmlParser.freeParser(p);
end;
/
show errors;

C’est  la  procédure  lireXml  qui  va  permettre  de  lire  et  d’analyser  un  document  XML.  Le  document  XML  va  être  fourni  en 
paramètre de la procédure : 

<?xml version ="1.0" standalone="no"?>


<!DOCTYPE equipe SYSTEM "equipe.dtd">
<equipe nom="US Postal" pays="USA">
<coureur numero="001">ARMSTRONG</coureur>
<coureur numero="002">EKIMOV</coureur>
<coureur numero="003">HERAS</coureur>
<coureur numero="004">HINCAPIE</coureur>
<coureur numero="005">JOACHIM</coureur>
<coureur numero="006">LANDIS</coureur>
<coureur numero="007">PADRNOS</coureur>
<coureur numero="008">PENA</coureur>
<coureur numero="009">RUBIERA</coureur>
</equipe>

L’exécution de la procédure et le résultat de cette exécution sont les suivants : 

SQL> set serveroutput on


SQL> execute lireXml(’c:\xml’,’equipe.xml’,’erreurs.txt’);
Les éléments du documents sont :
equipe coureur coureur coureur coureur coureur coureur coureur coureur coureur
Les attributs des éléments sont:
equipe:
nom=US Postal pays=USA
coureur:
numero=001

- 2- © ENI Editions - All rigths reserved


coureur:
numero=002
coureur:
numero=003
coureur:
numero=004
coureur:
numero=005
coureur:
numero=006
coureur:
numero=007
coureur:
numero=008
coureur:
numero=009

Procédure PL/SQL terminée avec succès.

SQL>

© ENI Editions - All rigths reserved - 3-


Appliquer une feuille de style à un document XML 
L’un  des  grands  avantages  du  langage  XML  est  de  pouvoir  séparer  de  façon  très  distincte  les  données  de  la 
présentation, ce qu’il est plus ou moins possible de faire en HTML. L’exemple suivant, qui utilise les fonctionnalités de 
l’analyseur XML pour PL/SQL, va permettre de produire un fichier de sortie. 

set serveroutput on;


create or replace procedure appliqueXSL(
repertoire varchar2, fichierXml varchar2,
fichierXsl varchar2, fichierResultat varchar2,
fichierErreur varchar2) is
-- les variables
p xmlParser.Parser;-- l’analyseur
documentXML xmlDom.DOMDocument; -- document
noeud xmlDom.DOMNode;
---- les éléments pour la feuille de style
moteur xslProcessor.Processor;
feuilleStyle xslProcessor.Stylesheet;
documentXSL xmlDom.DOMDocument;
elementXsl xmlDom.DOMElement;

espaceNom varchar2(50);
-- les éléments pour produire le résultat
documentF xmlDom.DOMDocumentFragment;
elementF xmlDom.DomNode;

begin
-- création d’un nouveau parser
p:=xmlParser.newParser;

-- fixer quelques caractéristiques de fonctionnement


xmlParser.setValidationMode(p,FALSE); -- pas de validation
du document
xmlParser.setErrorLog(p,repertoire||’\’||fichierErreur);
-- fichier des erreurs
xmlParser.setPreserveWhiteSpace(p, TRUE); -- conserver les espaces
xmlParser.setBaseDir(p, repertoire); -- repertoire de travail

-- analyser le document XML


xmlParser.parse(p,repertoire || ’\’ || fichierXml);

-- obtenir le document
documentXml:=xmlParser.getDocument(p);

-- analyser le document XML


xmlParser.parse(p,repertoire||’\’||fichierXsl);

-- obtenir le document
documentXsl:=xmlParser.getDocument(p);

-- obtenir les noeuds de la feuille de style


elementXsl:= xmlDom.getDocumentElement(documentXsl);
-- obtenir l’espace de nom
espaceNom:=xmlDom.getNamespace(elementXsl);

-- fabriquer la feuille de style


feuilleStyle:=xslProcessor.newStylesheet(documentXsl,repertoire||’\’||fichierX
sl);
-- appliquer la feuille de style
moteur :=xslProcessor.newProcessor;
xslProcessor.showWarnings(moteur, true);
xslProcessor.setErrorLog(moteur,repertoire||’\’||fichierErreur);

-- production du document final


documentF:=xslProcessor.processXSL(moteur, feuilleStyle, documentXML);
elementF:=xmlDom.makeNode(documentF);
xmlDom.writeTofile(elementF,repertoire||’\’||fichierResultat);

© ENI Editions - All rigths reserved - 1-


end;
/
show errors

L’utilisation de cette procédure permet d’appliquer une feuille de style (XSL) à un document XML et le résultat est fourni 
sous la forme d’un troisième document. Le fichier des erreurs est passé en paramètre et c’est  à  l’intérieur de celui­ci 
que sont consignées toutes les erreurs trouvées lors de l’application de la feuille de style. 
L’appel de la procédure peut s’effectuer de la façon suivante : 

execute appliqueXsl(’c:\xml’,’equipe.xml’,’equipe.xsl’,’equipe.out’,
’erreurs.txt’);

- 2- © ENI Editions - All rigths reserved


XSU 
L’API XSU (Xml SQL utility) pour PL/SQL permet la génération et le stockage de documents XML depuis et dans la base 
de  données.  Ce  sont  les  packages  DBMS_XMLQuery  et  DBMS_XMLSave  qui  permettent  de  mettre  en  œ uvre  ces 
fonctionnalités. 

1. Génération de code XML avec DBMS_XMLQuery 

Pour pouvoir générer un document XML qui va contenir le résultat d’une requête simple à l’aide de DBMS_XMLQuery, il 
est nécessaire de suivre les cinq étapes suivantes : 

● Créer  un  pointeur  vers  un  contexte  en  appelant  la  méthode  DBMS_XMLQuery.getCtx  et  en  lui  passant  en 
paramètre la requête. 

● Saisir les valeurs des différents paramètres possibles de la requête à l’aide de DBMS_XMLQuery.bind. 

● Fixer les arguments optionnels comme le nom de la balise ROW ou ROWSET, le nombre de lignes à ramener... 

● Écrire les données XML dans un élément CLOB (Caractère LOB) à l’aide de la fonction DBMS_XMLQuery.getXML. 
Cette fonction peut travailler avec ou sans un fichier DTD ou un schéma. 

● Fermer le contexte. 

a. Génération de code XML depuis une requête 

L’exemple ci­dessous illustre de façon très simple comment générer des informations au format XML à partir de ce qui est 
contenu dans la base. 

set serveroutput on
-- Mise au format XML du résultat d’une requête
declare
contexteRqt DBMS_XMLQuery.ctxType;
resultat CLOB;
begin
-- mise en place du contexte de requête
contexteRqt:=DBMS_XMLQuery.newContext(’select * from clients’);

-- obtenir le résultat
resultat:= DBMS_XMLQuery.getXML(contexteRqt);

-- afficher le résultat
afficheCLOB(resultat);

-- fermer le contexte de requête


DBMS_XMLQuery.closeContext(contexteRqt);
end;
/

Afin de faciliter l’affichage des éléments au format CLOB, la méthode afficheCLOB a été écrite. 

create or replace procedure afficheClob(chaine in out nocopy CLOB) is


chaineXml varchar2(32767);
ligne varchar2(2000);
begin
-- copier le document CLOB dans un VARCHAR2
chaineXml:=dbms_lob.SUBSTR(chaine, 32767);
loop
exit when chaineXml is null;
-- A la recherche des fins de ligne
ligne:=substr(chaineXml,1,instr(chaineXml,chr(10))-1);
dbms_output.put_line(’| ’||ligne);
chaineXml:=substr(chaineXml, instr(chaineXml,chr(10))+1);

© ENI Editions - All rigths reserved - 1-


end loop;
end;
/

L’exécution de ce script donne alors le résultat suivant : 

<?xml version = ’1.0’?>


<ROWSET>
<ROW num="1">
<NOCLI>1</NOCLI>
<NOM>ROUSSEL</NOM>
<PRENOM>Gilles</PRENOM>
<ADRESSE>rue ENI</ADRESSE>
<TEL>0240731696</TEL>
</ROW>
<ROW num="2">
<NOCLI>2</NOCLI>
<NOM>MACRAIGNE</NOM>
<PRENOM>Marie Pierre</PRENOM>
<ADRESSE>rue Crebillon</ADRESSE>
<TEL>0240731696</TEL>
</ROW> <ROW num="3">
<NOCLI>3</NOCLI>
<NOM>MARTIN</NOM>
<PRENOM>Bruno</PRENOM>
<ADRESSE>Rue Charron</ADRESSE>
<TEL>0240731696</TEL>
</ROW>
<ROW num="4">
<NOCLI>4</NOCLI>
<NOM>GABILLAUD</NOM>
<PRENOM>Jerome</PRENOM>
<ADRESSE>rue Charron</ADRESSE>
<TEL>0240731696</TEL>
</ROW>
</ROWSET>

Le  résultat  est  bien  sûr  satisfaisant  sur  de  nombreux  points  mais  n’est  pas  encore  un  document  XML  utilisable  tel 
quel. 

b. Modifier les noms des balises ROW et ROWSET 

L’API XSU pour PL/SQL permet de modifier le nom des balises ROW et ROWSET. Dans le cadre de notre exemple, la 
balise  ROW  devrait  prendre  le  nom  de  CLIENT  et  la  balise  ROWSET  celle  de  CLIENTS.  En  modifiant  légèrement  le 
script  précédent  et  en  utilisant  les  méthodes  setRowTag  et  setRowSetTag  il  est  possible  d’effectuer  ces 
modifications. 
Le script de génération de code XML devient alors : 

set serveroutput on
-- Mise au format XML du résultat d’une requête
declare
contexteRqt DBMS_XMLQuery.ctxType;
resultat CLOB;
begin
-- mise en place du contexte de requête
contexteRqt:=DBMS_XMLQuery.newContext(’select * from clients’);

--modification du nom de la balise ROW


DBMS_XMLQuery.setRowTag(contexteRqt,’CLIENT’);

--modification du nom de la balise ROWSET


DBMS_XMLQuery.setRowSetTag(contexteRqt,’CLIENTS’);

-- obtenir le résultat
resultat:= DBMS_XMLQuery.getXML(contexteRqt);

-- afficher le résultat
afficheCLOB(resultat);

- 2- © ENI Editions - All rigths reserved


-- fermer le contexte de requête
DBMS_XMLQuery.closeContext(contexteRqt);
end;

Le résultat de l’exécution du script est alors : 

<?xml version = ’1.0’?>


<CLIENTS>
<CLIENT num="1">
<NOCLI>1</NOCLI>
<NOM>ROUSSEL</NOM>
<PRENOM>Gilles</PRENOM>
<ADRESSE>rue ENI</ADRESSE>
<TEL>0240731696</TEL>
</CLIENT>
<CLIENT num="2">
<NOCLI>2</NOCLI>
<NOM>MACRAIGNE</NOM>
<PRENOM>Marie Pierre</PRENOM>
<ADRESSE>rue Crebillon</ADRESSE>
<TEL>0240731696</TEL>
</CLIENT>
<CLIENT num="3">
<NOCLI>3</NOCLI>
<NOM>MARTIN</NOM>
<PRENOM>Bruno</PRENOM>
<ADRESSE>Rue Charron</ADRESSE>
<TEL>0240731696</TEL>
</CLIENT>
<CLIENT num="4">
<NOCLI>4</NOCLI>
<NOM>GABILLAUD</NOM>
<PRENOM>Jerome</PRENOM>
<ADRESSE>rue Charron</ADRESSE>
<TEL>0240731696</TEL>
</CLIENT>
</CLIENTS>

c. Limiter le nombre de lignes 

Les  lignes  de  données  extraites  à  partir  de  la  requête  peuvent  être  mises  en  page  à  l’aide  des  procédures 
setMaxRowset setSkipRows.  La  procédure setMaxRows permet de fixer le nombre maximum de lignes de données qui 
seront converties au format XML, la procédure setSkipRows permet quant à elle de préciser le nombre de lignes de 
données à ne pas prendre en compte avant de commencer la conversion au format XML. 

Ces procédures peuvent être utilisées pour, par exemple, limiter le nombre de lignes de données présentées dans 
chaque document XML. 

L’exemple suivant permet de limiter à 10 le nombre de clients présents dans chaque document XML généré. Afin qu’une 
exception soit levée lorsque toutes les lignes sont traitées, il faut faire appel à la méthode setRaiseNoRowsException. 

set serveroutput on
-- Mise au format XML du résultat d’une requête
declare
contexteRqt DBMS_XMLQuery.ctxType;
resultat CLOB;
begin
-- mise en place du contexte de requête
contexteRqt:=DBMS_XMLQuery.newContext(’select * from clients’);

--modification du nom de la balise ROW


DBMS_XMLQuery.setRowTag(contexteRqt,’CLIENT’);

--modification du nom de la balise ROWSET


DBMS_XMLQuery.setRowSetTag(contexteRqt,’CLIENTS’);

-- fixer le nombre de lignes par document XML


DBMS_XMLQuery.setMaxRows(contexteRqt,10);

© ENI Editions - All rigths reserved - 3-


DBMS_XMLQuery.setRaiseNoRowsException(contexteRqt, true);
-- extraction des informations
begin
loop -- boucle infinie
-- obtenir le résultat
resultat:= DBMS_XMLQuery.getXML(contexteRqt);

-- afficher le résultat
afficheCLOB(resultat);
end loop;
exception
when others then
null; --sortir du bloc en cas d’erreur
end;

-- fermer le contexte de requête


DBMS_XMLQuery.closeContext(contexteRqt);
end;
/

d. Les feuilles de styles 

L’API XSU permet, bien sûr, l’utilisation des feuilles de styles dans la génération des documents XML. 
La procédure setStyleSheetHeader()  permet  d’ajouter la référence à la feuille de style dans l’en­tête du document 
résultant. 
La  procédure  useStyleSheet()  permet,  quant  à  elle,  d’appliquer  la  feuille  de  style  directement  au  document 
résultant. La seconde solution est de meilleure qualité que la première car cela évite de retravailler le document pour 
appliquer la feuille de style dans un deuxième temps. 

2. Les requêtes paramétrées 

Lors de la création du contexte il est nécessaire de fournir la requête SQL qui sera utilisée pour extraire l’information. 
Toutefois, cette requête peut contenir des paramètres qui seront valorisés juste avant l’exécution de la requête. En 
effet la requête n’est exécutée que lors de la demande de construction du document XML final par l’intermédiaire de la 
méthode getXMLClob. 
Lors de l’écriture de la requête, les variables sont considérées comme des variables externes et sont donc préfixées 
par deux points (:). 
La  méthode  setBindValue  permet  de  fixer  la  valeur  qui  sera  utilisée  par  un  paramètre.  Il  est  bien  sûr  nécessaire 
d’initialiser l’ensemble des paramètres avant la première demande de génération de document XML. Cependant, entre 
deux  demandes  de  génération  de  document,  il  n’est  pas  nécessaire  de  réinitialiser  tous  les  paramètres  mais 
simplement ceux pour lesquels la valeur a changé. 
Exemple 
L’exemple  suivant  permet  d’illustrer  la  mise  en  place  de  requêtes  paramétrées  pour  travailler  avec  l’API  XSU.  Deux 
documents XML vont être générés, chacun d’eux correspondant à la définition d’un client particulier, mais pourtant un seul 
contexte XSU sera établi car les données sont issues de la même requête à un paramètre de restriction prêt. 

set serveroutput on
-- Mise au format XML du résultat d’une requête
declare
contexteRqt DBMS_XMLQuery.ctxType;
resultat CLOB;
begin
-- mise en place du contexte de requête
contexteRqt:=DBMS_XMLQuery.newContext(’select * from clients where
nocli=:numero’);

-- fixer la valeur du paramètre


DBMS_XMLQuery.setBindValue(contexteRqt,’numero’,15);

-- obtenir le résultat
resultat:= DBMS_XMLQuery.getXML(contexteRqt);
-- afficher le résultat
afficheCLOB(resultat);

- 4- © ENI Editions - All rigths reserved


-- fixer un autre valeur pour la paramètre
DBMS_XMLQuery.setBindValue(contexteRqt,’numero’,20);

-- obtenir le résultat
resultat:= DBMS_XMLQuery.getXML(contexteRqt);
-- afficher le résultat
afficheCLOB(resultat);
-- fermer le contexte de requête
DBMS_XMLQuery.closeContext(contexteRqt);
end;
/

3. Stocker les informations au format XML avec DBMS_XMLSave 

L’API XSU pour PL/SQL est également constituée du package DBMS_XMLSave qui permet d’enregistrer dans des tables 
de la base de données Oracle des données qui se trouvent initialement dans des documents au format XML. Avec ce 
second package, XSU permet de montrer que XML est un véritable format d’échange des données qui peut être utilisé 
pour effectuer des transferts de données entre des bases de données. 

Il sera possible de travailler avec les données fournies au format XML pour réaliser des commandes Insert, Update ou 
Delete. 
D’une façon générale, tous les scripts PL/SQL utilisant le package DBMS_XMLSave respectent la structure suivante : 

● Créer un contexte d’exécution par l’intermédiaire de la fonction DBMS_XMLSave.getCtx. Cette fonction admet 
en paramètre le nom de la table sur laquelle seront effectuées les opérations Insert, Delete ou Update. 

● Si le document XML est utilisé comme support à l’ajout de données (INSERT) dans la table, alors il est possible 
de  préciser  les  colonnes  pour  lesquelles  des  valeurs  vont  être  fournies  par  l’intermédiaire  de  la  fonction 
setUpadetColNames. Par défaut les valeurs sont fournies pour toutes les colonnes de la table. 

● Si le document XML est un support à une opération de mise à jour des données (UPDATE), alors il faut fournir 
la  ou  les  colonnes  qui  vont  être  utilisées  pour  identifier  de  façon  exacte  les  données  à  modifier.  Il  peut 
également être possible de préciser la ou les colonnes qui seront mises à jour. 

● Si le document XML sert de support à une opération de suppression (DELETE), alors il est possible de préciser 
quelles seront la ou les colonnes qui seront utilisées pour identifier précisément les données à supprimer. Par 
défaut toutes les informations du document XML servent à identifier les données qui seront supprimées. 

● Fournir  un  document  XML  à  l’une  des  méthodes  insertXML,  updateXML  ou  deleteXML  suivant  l’utilisation que 
l’on souhaite faire du document XML. 

● Fermer le contexte. 

a. Ajouter des données 

Pour utiliser les données présentes dans le document XML afin de les ajouter dans une table, il suffit simplement de 
préciser  le  nom  de  la  table  ou  de  la  vue,  ainsi  que  le  document  XML.  XSU  se  charge  de  générer  les  commandes 
INSERT. Par défaut, la commande INSERT concerne toutes les colonnes de la table ou de la vue et la valeur NULL est 
utilisée lorsque rien n’est précisé dans le document XML. 

Exemple 
L’exemple ci­après illustre l’utilisation de la fonction insertXML : 

create or replace procedure ajouter(documentXML in CLOB, nomTable


in varchar2) is
contexteAjout DBMS_XMLSave.ctxType;
nbreLignes number;
begin
-- créer le contexte d’insertion
contexteAjout:=DBMS_XMLSave.newContext(nomTable);

-- ajouter les lignes


nbreLignes:=DBMS_XMLSave.insertXML(contexteAjout, documentXML);

© ENI Editions - All rigths reserved - 5-


-- fermer le contexte
DBMS_XMLSave.closeContext(contexteAjout);
end;
/

Le document XML utilisé pour ajouter des données est : 

<?xml version = ’1.0’?>


<ROWSET>
<ROW num="1">
<NOCLI>200</NOCLI>
<NOMCLI>Etb LEROY</NOMCLI>
<CODE_POSTAL>37000</CODE_POSTAL>
<VILLE>TOURS</VILLE>
</ROW>
</ROWSET>

L’appel à la procédure est effectué de la façon suivante : 

-- mise en place du répertoire


create or replace directory "xml_dir" as ’C:\xml’;

-- chargement des données


declare

dest_clob CLOB;
fic_in BFILE;

taille number;
depart_destination integer:=1;
depart_origine integer:=1;
jeu_caractere number:=0;
contexte_langue number:=0;
avertissement number:=0;

vid number;
begin
fic_in:= bfilename(’xml_dir’,’donnees.xml’);

-- ouvrir le fichier
dbms_lob.fileopen(fic_in, dbms_lob.file_readonly);

if (dbms_lob.fileexists(fic_in)=1) then

-- taille du fichier
taille:=dbms_lob.getlength(fic_in);

-- lire les données et mémoriser dans une variable


contexte_langue:=1;
dbms_lob.createtemporary(dest_clob, true);
dbms_lob.loadclobfromfile(dest_clob,
fic_in,
taille,
depart_destination,
depart_origine,
jeu_caractere,
contexte_langue,
avertissement);

-- fermer le fichier
dbms_lob.fileclose(fic_in);

-- appeler la procédure d’ajout des données


ajouter(dest_clob, ’CLIENTS’);
-- valider les transformations
commit;

end if;

- 6- © ENI Editions - All rigths reserved


end;
/

Il est également possible d’utiliser cette méthode d’insertion pour ne renseigner que certaines colonnes de la table 
de  destination.  Il  est  alors  nécessaire  de  faire  appel  à  la  méthode  setUpdateColumn  afin  de  préciser  le  nom  des 
colonnes  qui  vont  contenir  des  valeurs  à  insérer.  Pour  éliminer  tout  risque  de  paramètre  mal  défini,  la  méthode 
clearUpdateColumnList permet d’enlever toute référence qui aurait déjà pu être faite sur des colonnes. 

Exemple 

L’exemple suivant va lire les données au format XML dans un fichier puis charge les données dans la table des clients : 

declare
-- la variables nécessaires à la lecture d’un fichier
documentXML CLOB;
fic_in BFILE;
taille number;
depart_destination integer:=1;
depart_origine integer:=1;
jeu_caractere number:=0;
contexte_langue number:=0;
avertissement number:=0;

-- les variables pour l’ajout des données


contexteAjout DBMS_XMLSave.ctxType;
nombreLignes number;

begin
fic_in:= bfilename(’xml_dir’,’donnees2.xml’);

-- ouvrir le fichier
dbms_lob.fileopen(fic_in, dbms_lob.file_readonly);

-- taille du fichier
taille:=dbms_lob.getlength(fic_in);

-- lire les données et mémoriser dans une variable


contexte_langue:=1;
dbms_lob.createtemporary(documentXML, true);
dbms_lob.loadclobfromfile(documentXML,
fic_in,
taille,
depart_destination,
depart_origine,
jeu_caractere,
contexte_langue,
avertissement);

-- fermer le fichier
dbms_lob.fileclose(fic_in);

-- ajouter les données au format XML dans la table


contexteAjout:=DBMS_XMLSave.newContext(’CLIENTS’);
-- effacer les paramètres
DBMS_XMLSave.clearUpdateColumnList(contexteAjout);
-- les colonnes pour lesquelles il exite une valeur
DBMS_XMLSave.setUpdateColumn(contexteAjout,’NOCLI’);
DBMS_XMLSave.setUpdateColumn(contexteAjout,’NOMCLI’);
-- effectuer les insertions
nombreLignes:=DBMS_XMLSave.insertXML(contexteAjout,documentXML);
--fermer le contexte
DBMS_XMLSave.closeContext(contexteAjout);

-- valider les transformations


commit;

end;
/

© ENI Editions - All rigths reserved - 7-


b. Mettre à jour des données 

La mise à jour est une opération légèrement plus délicate car il est nécessaire cette fois d’indiquer la ou les colonnes 
servant à l’identification de la ligne ainsi que la ou les colonnes dont les valeurs vont être mises à jour. 
Les colonnes servant à l’identification seront indiquées par l’intermédiaire de la procédure setKeyColumn et celles qui 
vont  être  mises  à  jour  par  l’intermédiaire  de  setUpdateColumn.  En  l’absence  de  cette  dernière  indication  ce  sont 
toutes les colonnes de la table qui sont mises à jour. 

Exemple 
L’exemple  ci­dessous  va  permettre  de  fixer  la  ville  et  le  code  postal  pour  les  clients  n°200  et  201  (ajoutés  dans  les 
exemples précédents) : 

declare
-- la variables nécessaires à la lecture d’un fichier
documentXML CLOB;
fic_in BFILE;
taille number;
depart_destination integer:=1;
depart_origine integer:=1;
jeu_caractere number:=0;
contexte_langue number:=0;
avertissement number:=0;

-- les variables pour la mise à jour


contexteMAJ DBMS_XMLSave.ctxType;
nombreLignes number;
begin
fic_in:= bfilename(’xml_dir’,’donnees3.xml’);

-- ouvrir le fichier
dbms_lob.fileopen(fic_in, dbms_lob.file_readonly);

-- taille du fichier
taille:=dbms_lob.getlength(fic_in);

-- lire les données et mémoriser dans une variable


contexte_langue:=1;
dbms_lob.createtemporary(documentXML, true);
dbms_lob.loadclobfromfile(documentXML,
fic_in,
taille,
depart_destination,
depart_origine,
jeu_caractere,
contexte_langue,
avertissement);
-- fermer le fichier
dbms_lob.fileclose(fic_in);

-- création du contexte de mise à jour


contexteMAJ:=DBMS_XMLSave.newContext(’CLIENTS’);
-- effacer les paramètres
DBMS_XMLSave.clearUpdateColumnList(contexteMAJ);
-- Colonne d’identifications
DBMS_XMLSave.setKeyColumn(contexteMAJ,’NOCLI’);
-- Colonnes à mettre à jour
DBMS_XMLSave.setUpdateColumn(contexteMAJ,’CODE_POSTAL’);
DBMS_XMLSave.setUpdateColumn(contexteMAJ,’VILLE’);
-- effectuer les mises à jour
nombreLignes:=DBMS_XMLSave.updateXML(contexteMAJ,documentXML);
--fermer le contexte
DBMS_XMLSave.closeContext(contexteMAJ);
-- valider les transformations
commit;

end;
/

Le fichier XML servant de base à la mise à jour : 

- 8- © ENI Editions - All rigths reserved


<?xml version = ’1.0’?>
<ROWSET>
<ROW>
<NOCLI>200</NOCLI>
<CODE_POSTAL>49000</CODE_POSTAL>
<VILLE>ANGERS</VILLE>
</ROW>
<ROW>
<NOCLI>201</NOCLI>
<CODE_POSTAL>74000</CODE_POSTAL
<VILLE>ANNECY</VILLE>
</ROW>
</ROWSET>

c. Supprimer des données 

Enfin,  il  est  possible  de  se  servir  d’un  document  XML  comme  support  à  la  suppression  de  données.  Les  colonnes 
présentes dans le document XML vont servir à la construction de la clause WHERE. Il est possible de restreindre le 
nombre de colonnes participant à la restriction des lignes en faisant appel à la procédure setKeyColumn. 

L’exemple  suivant  permet  de  supprimer  les  clients  n°  200  et  201.  Ces  informations  sont  stockées  dans  un  fichier  XML 
nommé donnees4.xml. 

declare
-- les variables nécessaires à la lecture d’un fichier
documentXML CLOB;
fic_in BFILE;
taille number;
depart_destination integer:=1;
depart_origine integer:=1;
jeu_caractere number:=0;
contexte_langue number:=0;
avertissement number:=0;

-- les variables pour la suppression


contexteSupp DBMS_XMLSave.ctxType;
nombreLignes number;

begin
fic_in:= bfilename(’xml_dir’,’donnees4.xml’);

-- ouvrir le fichier
dbms_lob.fileopen(fic_in, dbms_lob.file_readonly);

-- taille du fichier
taille:=dbms_lob.getlength(fic_in);

-- lire les données et mémoriser dans une variable


contexte_langue:=1;
dbms_lob.createtemporary(documentXML, true);
dbms_lob.loadclobfromfile(documentXML,
fic_in,
taille,
depart_destination,
depart_origine,
jeu_caractere,
contexte_langue,
avertissement);
-- fermer le fichier
dbms_lob.fileclose(fic_in);

-- création du contexte de suppression


contexteSupp:=DBMS_XMLSave.newContext(’CLIENTS’);

-- effacer les paramètres


DBMS_XMLSave.clearUpdateColumnList(contexteSupp);
-- Colonne d’identifications

© ENI Editions - All rigths reserved - 9-


DBMS_XMLSave.setKeyColumn(contexteSupp,’NOCLI’);
-- effectuer la suppression
nombreLignes:=DBMS_XMLSave.deleteXML(contexteSupp,documentXML);
--fermer le contexte
DBMS_XMLSave.closeContext(contexteSupp);
-- valider les transformations
commit;

end;
/

L’utilisation  telle  quelle  du  package  DBMS_XMLSave  est  un  peu  fastidieuse  dans  l’écriture  des  procédures, 
notamment au niveau de l’initialisation du contexte. Étant donné que le contexte est lié à une table, il est possible 
de créer un contexte unique puis de l’utiliser, aussi bien pour effectuer des opérations d’ajout que de mise à jour ou 
de  suppression.  Cette  opération  est  réalisable  en  regroupant  les  procédures  relatives  aux  différentes  opérations 
dans  un  package  et  en  déclarant  comme  variable  globale  au  package  le  contexte  d’exécution  des  commandes  du 
package DBMS_XMLSave. 

- 10 - © ENI Editions - All rigths reserved


Introduction 
Avec la version 11g de la base de données, Oracle installe par défaut le service Oracle Application Express (APEX). Ce 
service permet de mettre en place une structure de bases de données et de gérer les données contenues dans ces 
tables au travers d’interfaces Web conviviales. 
Pour les versions antérieures, Oracle Application Express peut être téléchargé et installé dans une base de données 
existante.  Oracle  Application  Express  est  anciennement  connu  sous  le  nom  HTML  DB.  Il  est  possible  de  tester  les 
fonctionnalités d’APEX depuis le site Internet suivant : http://apex.oracle.com. Après inscription (gratuite) sur ce site, il 
est possible d’utiliser APEX afin de tester le produit. 

Avec APEX, il est possible de travailler avec un serveur Oracle sans pour autant maîtriser le langage SQL. Cependant, 
des connaissances en SQL et PL/SQL vont permettre de travailler de façon précise. L’interface APEX est alors utilisée 
pour éviter les erreurs de syntaxe et faciliter la saisie des opérations fastidieuses. 

APEX permet de mettre en place, de façon très simple, une application de type Web qui utilise des données stockées 
dans la base de données Oracle. 

© ENI Editions - All rigths reserved - 1-


Activer Oracle Application Express 
Bien  qu’APEX  soit  installé  par  défaut  avec  Oracle11g,  quelques  opérations  sont  nécessaires  pour  l’activer  ;  ces 
opérations doivent être réalisées par l’administrateur de la base de données. 

Pour activer APEX, il faut procéder de la manière suivante : 

■ Sur le serveur Oracle, lancez SQL*Plus et connectez­vous en tant que SYS. 

C:\>sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on Mar. Nov. 25 08:53:02


2008

Copyright (c) 1982, 2007, Oracle. All rights reserved.

SQL> CONNECT / AS SYSDBA


Connecté.

■ Exécutez le script apxconf.sql situé dans le répertoire apex de l’installation Oracle et saisissez un mot de passe pour 
l’administrateur APEX ainsi que le port à utiliser pour le serveur HTTP (8080 par défaut). 

SQL> @?/apex/apxconf.sql

PORT
----------
8080

Enter values below for the XDB HTTP listener port and the password
for the Application Exp
ress ADMIN user.
Default values are in brackets [ ].
Press Enter to accept the default value.

Enter a password for the ADMIN user [] admin


Enter a port for the XDB HTTP listener [ 8080]
...changing HTTP Port

Procédure PL/SQL terminée avec succès.

Procédure PL/SQL terminée avec succès.

Session modifiée.

...changing password for ADMIN

Procédure PL/SQL terminée avec succès.

Validation effectuée.

■ Déverrouillez le compte ANONYMOUS. 

SQL> ALTER USER ANONYMOUS ACCOUNT UNLOCK;

Utilisateur modifié.

Par ailleurs, par défaut, seule la langue anglaise est installée dans APEX. 
Pour installer d’autres langues (par exemple, le français), vous pouvez procéder de la manière suivante : 

■ Toujours  sur  le  serveur  Oracle,  au  niveau  du  système  d’exploitation,  définissez  la  variable  d’environnement 
NLS_LANG pour utiliser le jeu de caractères AL32UTF8. 

© ENI Editions - All rigths reserved - 1-


C:\>set NLS_LANG=american_america.AL32UTF8

■ Lancez SQL*Plus, connectez­vous en tant que SYS et définissez le schéma APEX comme schéma courant. 

C:\>sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on Mar. Nov. 25 08:53:02


2008

Copyright (c) 1982, 2007, Oracle. All rights reserved.

SQL> CONNECT / AS SYSDBA


Connecté.

SQL> ALTER SESSION SET CURRENT_SCHEMA = FLOWS_030000;

Session altered.

■ Exécutez le script correspondant à la langue souhaitée. 

SQL> @?/apex/builder/fr/load_fr.sql
...

Le chargement dure plusieurs minutes. 

- 2- © ENI Editions - All rigths reserved


Créer un espace de travail 
Dans  la  terminologie  APEX,  un  espace  de  travail  (workspace)  désigne  l’environnement  utilisé  pour  développer  les 
applications. Un espace de travail peut contenir plusieurs applications et être partagé par plusieurs développeurs. Un 
espace de travail est associé à un schéma. 
Pour  créer  un  espace  de  travail,  il  faut  se  connecter  à  l’interface  d’administration  d’APEX  avec  une  URL  du  type 
http://serveur:port/apex/apex_admin, où serveur désigne le nom du serveur Oracle et port le port d’écoute du serveur 
HTTP indiqué lors de la configuration (8080 par défaut). 

Vous pouvez vous connecter avec le nom d’utilisateur admin et le mot de passe indiqué lors la configuration. 

Lors  de  la  première  connexion,  vous  serez  invité  à  modifier  le  mot  de  passe  et  la  page  de  connexion  vous  sera 
proposée une deuxième fois. 

La page d’accueil de l’interface d’administration a l’allure suivante : 

© ENI Editions - All rigths reserved - 1-


 

■ Cliquez sur l’icône Gérer les espaces de travail : 

Cette page permet de gérer les espaces de travail. 

■ Pour créer un nouvel espace de travail, cliquez sur le lien Créer un espace de travail. 

- 2- © ENI Editions - All rigths reserved


 

■ Sur la première page, saisissez un nom pour l’espace de travail puis cliquez sur le bouton Suivant >. 

■ Sur la page suivante, vous allez indiquer si l’espace de travail est associé à un schéma existant, ou si un nouveau 
schéma doit être créé. Dans cet exemple, nous allons créer un nouveau schéma. Pour cela, vous devez indiquer un 
nom, un mot de passe et une taille. Cliquez ensuite sur le bouton Suivant >. 

© ENI Editions - All rigths reserved - 3-


 

■ Pour terminer, vous devez créer un administrateur pour le nouvel espace de travail. Pour cela, saisissez un nom, un 
mot de passe et une adresse de courrier électronique. Cliquez sur le bouton Suivant > pour afficher une page de 
récapitulatif. 

Si  les  informations  sont  correctes,  vous  pouvez  cliquer  sur  le  bouton  Créer  pour  valider  la  création  de  l’espace  de 
travail. Lorsque la création est terminée, une page de confirmation s’affiche : 

- 4- © ENI Editions - All rigths reserved


 

■ Cliquez sur le bouton Terminé. 

À ce stade, il est possible de créer d’autres utilisateurs : développeurs d’applications qui vont pouvoir travailler dans un 
espace de travail, ou utilisateurs finaux des applications développées avec APEX. 

Dans cet ouvrage, le compte administrateur de l’espace de travail sera utilisé comme compte de développement. 

© ENI Editions - All rigths reserved - 5-


Développer une application 

1. Se connecter à l’espace de travail 

Pour  développer  une  application  avec  APEX,  il  faut  se  connecter  à  un  espace  de  travail  à  l’aide  d’un  compte 
développeur, avec une URL du type : http://serveur:port/apex, où serveur désigne le nom du serveur Oracle et port le 
port d’écoute du serveur HTTP indiqué lors de la configuration (8080 par défaut). 

■ Dans  la  page  de  connexion,  saisissez  le  nom  de  l’espace  de  travail,  ainsi  que  le  nom  et  le  mot  de  passe  d’un 
compte  développeur  habilité  à  travailler  dans  l’espace  de  travail.  Comme  indiqué  précédemment,  dans  nos 
exemples,  nous  utiliserons  le  compte  administrateur  de  l’espace  de  travail  comme  compte  développeur.  Cliquez 
ensuite sur le bouton Connexion pour accéder à la page d’accueil de l’espace de travail : 

© ENI Editions - All rigths reserved - 1-


 

L’espace de travail est divisé en trois outils principaux : 

● Application  Builder  permet  de  développer  une  application  dont  l’interface  graphique  se  présente  sous  la 
forme  de  pages  HTML,  contenant  des  formulaires  pour  saisir  des  données  et  des  rapports.  Les  données 
saisies dans l’application sont stockées dans des tables du schéma sous­jacent. 

● SQL Workshop propose plusieurs outils qui permettent de saisir et exécuter des requêtes SQL (ou des blocs 
PL/SQL), mais aussi de gérer les différents objets du schéma (tables, vues, etc.). 

● Utilitaires permet notamment d’exporter et d’importer très facilement des données. 

2. Créer les objets de l’application 

SQL Workshop propose un outil Navigateur d’objet qui permet de gérer les objets (tables, vues, séquences, etc.) 
de l’application. 

En guise d’exemple, nous allons utiliser cet outil pour créer les deux tables de notre application. 

■ Ouvrez le menu déroulant associé au bouton SQL Workshop et sélectionnez l’élément Navigateur d’objet ­ Créer 
­ Table. 

- 2- © ENI Editions - All rigths reserved


 

■ Sur la première page, saisissez le nom de la table et la liste des colonnes, puis cliquez sur le bouton Suivant >. 

Sur la deuxième page, vous pouvez définir la clé primaire. Si vous le souhaitez, vous pouvez demander à ce que la clé 
primaire soit renseignée automatiquement à partir d’une séquence (existante ou nouvelle). Sur l’exemple ci­dessus, 
la  clé  primaire  de  la  table  sera  renseignée  automatiquement  à  partir  d’une  nouvelle  séquence.  Dans  ce  cas,  il  faut 
renseigner le nom de la contrainte, le nom de la séquence et sélectionner la colonne de la table. Cliquez ensuite sur 
le bouton Suivant >. 

© ENI Editions - All rigths reserved - 3-


Cette page permet de définir des clés étrangères. Si la table ne comporte pas de clé étrangère (c’est le cas ici), vous 
pouvez cliquer directement sur le bouton Suivant >. 

■ Cette page permet de définir des contraintes uniques ou CHECK. Pour créer une contrainte, vous devez spécifier 
les  caractéristiques  de  la  contrainte,  puis  cliquer  sur  le  bouton  Ajouter.  Dans  l’exemple  ci­dessus,  il  existe  une 
contrainte unique sur la colonne NOM. Après avoir défini les différentes contraintes, cliquez sur le bouton Fin ; une 
page de confirmation s’affiche : 

■ Pour afficher le code SQL correspondant à la création de la table, vous pouvez cliquer sur le lien SQL. Cliquez sur le 
bouton Créer pour créer la table. 

Vous pouvez procéder de la même manière pour créer la deuxième table de notre application : 

- 4- © ENI Editions - All rigths reserved


 

Cette table comporte une clé étrangère vers la table COLLECTION que vous pouvez créer de la manière suivante : 

3. Créer l’application 

■ Sur la page d’accueil,  ouvrez  le  menu  déroulant  associé  au  bouton Application  Builder et sélectionnez l’élément 


Créer une application ­ Créer une application. 

© ENI Editions - All rigths reserved - 5-


 

■ Sur la première page, saisissez le nom de votre application puis cliquez sur le bouton Suivant >. 

■ Sur la deuxième page, vous allez pouvoir définir les premières pages de votre application. Pour commencer, nous 
allons créer une page d’accueil : sélectionnez le type de page Vierge, saisissez le nom de la page ("Accueil" par 
exemple) puis cliquez sur le bouton Ajouter une page. 

■ Ensuite, nous allons créer une page pour saisir les données de la table COLLECTION directement dans un tableau. 
Sélectionnez  le  type  de  page  Panneau  tabulaire,  subordonnez  la  page  à  la  page  d’accueil,  spécifiez  la  table 
COLLECTION comme nom de table, puis cliquez sur le bouton Ajouter une page. 

- 6- © ENI Editions - All rigths reserved


 

■ Pour terminer, pour saisir les données de la table LIVRE nous allons créer deux pages : une liste et un formulaire 
de saisie. Sélectionnez le type de page Etat et panneau, subordonnez la page à la page d’accueil, spécifiez la table 
LIVRE comme nom de table, puis cliquez sur le bouton Ajouter une page. 

Vous devez maintenant avoir les pages suivantes dans votre application : 

■ Cliquez sur le bouton Suivant >. 

■ Cette page permet de structurer les onglets de l’application. Sélectionnez l’option Un niveau d’onglets puis cliquez 
sur le bouton Suivant >. 

© ENI Editions - All rigths reserved - 7-


 

■ Cette  page  permet  de  copier  des  composants  partagés  d’une  autre  application.  Laissez  l’option  par  défaut  et 
cliquez sur le bouton Suivant >. 

■ Cette page permet de choisir le mode d’authentification à l’application et la langue de l’application. Sélectionnez le 
mode d’authentification Application Express et la langue française, puis cliquez sur le bouton Suivant >. 

- 8- © ENI Editions - All rigths reserved


■ Sélectionnez le thème de votre choix puis cliquez sur le bouton Suivant >. 

Pour  créer  l’application,  il  ne  reste  plus  qu’à  cliquer  sur  le  bouton  Créer ;  la  page  principale  de  l’éditeur  de 
l’application s’affiche : 

Cette page propose différents outils qui permettront de personnaliser l’application. 

L’application créée est opérationnelle ; nous allons pouvoir l’exécuter pour la tester. 

4. Tester l’application 

Pour exécuter l’application créée précédemment, il suffit de cliquer sur l’icône Exécuter l’application. 

La page de connexion s’affiche : 

© ENI Editions - All rigths reserved - 9-


 

Comme nous avons choisi le mode d’authentification Application Express pour cette application, il faut saisir ici le nom 
et le mot de passe d’un utilisateur APEX ; le compte administrateur de l’espace de travail peut être utilisé. 

Après connexion, la page d’accueil de l’application s’affiche : 

Cette page permet de naviguer vers les autres pages de l’application. 

■ Cliquez sur le lien COLLECTION pour afficher la page de saisie de la table COLLECTION : 

- 10 - © ENI Editions - All rigths reserved


 

■ Pour  créer  une  nouvelle  ligne,  il  suffit  de  cliquer  sur  le  bouton  Ajouter  une  ligne,  de  saisir  les  valeurs  puis  de 
cliquer sur le bouton Soumettre : 

■ Cliquez sur le lien Accueil en haut à gauche pour revenir sur la page d’accueil, puis sur le lien LIVRE pour accéder 
à la page de gestion des livres. Cette page affiche la liste des livres ; pour l’instant, cette liste est vide : 

© ENI Editions - All rigths reserved - 11 -


 

■ Cliquez sur le bouton Créer pour créer un enregistrement : 

■ Saisissez les différentes informations puis cliquez sur le bouton  Créer pour enregistrer la saisie et revenir sur la 
liste : 

- 12 - © ENI Editions - All rigths reserved


 

Comme  vous  pouvez  le  constater,  cette  application  créée  en  quelques  clics  est  parfaitement  opérationnelle :  elle 
permet de consulter et saisir les informations des tables COLLECTION et LIVRE. 

Par  contre,  l’interface  utilisateur  mériterait  sans  doute  d’être  améliorée ;  c’est  ce  que  nous  allons  faire  au  point 
suivant. 

5. Personnaliser l’application 

Application  Express  propose  un  très  grand  nombre  de  fonctionnalités  qui  permettent  de  personnaliser  les 
applications. Dans ce point, nous présenterons quelques possibilités correspondant à des besoins courants : 

● Modifier la présentation des pages. 

● Créer et utiliser des listes de valeurs (statiques ou dynamiques). 

● Ajouter des contrôles sur les données saisies. 

a. Modifier la présentation des pages 

■ Sur la page principale de l’éditeur, cliquez sur l’icône de la page que vous souhaitez modifier : 

© ENI Editions - All rigths reserved - 13 -


 

L’éditeur de page s’affiche : 

■ Dans  la  région  Eléments,  cliquez  sur  l’icône  de  modification  afin  d’afficher  une  page  permettant  de 
personnaliser les zones du formulaire : 

- 14 - © ENI Editions - All rigths reserved


 

Les différents onglets de cette page permettent notamment de modifier les libellés, la taille des zones ou d’associer 
une petite aide à un élément. 

À titre d’exemple, vous pouvez modifier les libellés, la largeur des zones et utiliser un modèle de champ qui indique 
que le titre est obligatoire : 

■ Cliquez sur le bouton Appliquer les modifications. 

Pour modifier tous les attributs d’un élément, vous pouvez cliquer sur l’icône de modification associée à l’élément 
 
.

© ENI Editions - All rigths reserved - 15 -


 

La  page  qui  s’affiche  permet  de  modifier  toutes  les  propriétés  d’un  élément :  source  de  données,  libellé,  format 
d’affichage, valeur par défaut, liste de valeur associée, etc. 

Nous utiliserons cette page ultérieurement notamment pour associer une liste de valeurs à un champ. Cliquez sur le 
bouton Annuler. 
Pour visualiser le résultat des modifications, vous pouvez cliquer sur le bouton Exécuter de la page d’édition d’une 
page. 

Le formulaire de saisie doit maintenant avoir l’allure suivante : 

Certains attributs peuvent être modifiés directement pendant la navigation dans l’application (sous réserve d’être 
connecté  avec  un  compte  développeur).  Pour  cela,  il  faut  d’abord afficher les liens d’édition en cliquant sur le lien 
Afficher les liens de modification situé en bas à droite : 

 
 
Ensuite, vous pouvez cliquer sur les icônes  pour éditer les propriétés de l’élément associé.

- 16 - © ENI Editions - All rigths reserved


 
 
Pensez à rafraîchir la page pour voir le résultat de la modification.

Pour masquer les icônes d’édition, vous pouvez cliquer sur le lien Masquer les liens de modification situé en bas à 
droite. 

Pour  revenir  dans  l’éditeur  de  la  page,  vous  pouvez  cliquer  sur  le  lien  Modifier  une  page  N,  N  correspondant  au 
numéro de la page courante. 
Nous allons maintenant modifier l’ordre des éléments dans le formulaire. 

■ Cliquez  sur  l’icône  de  la  zone  Eléments.  La  page  qui  s’affiche  permet  de  modifier  la  mise  en  page  par 
glisser­déplacer : 

Dans  la  partie  gauche,  la  structure  actuelle  de  la  page  est  affichée  ;  la  position  des  différentes  zones  peut  être 
modifiée  par  glisser­déplacer.  La  partie  droite  propose  plusieurs  types  de  zones.  Pour  ajouter  une  nouvelle  zone 
dans la page, il suffit de glisser­déplacer l’icône correspondant au type de zone souhaité. Pour ajouter une nouvelle 
ligne dans la page, vous pouvez glisser­déplacer le bouton Ajouter une ligne. 

À titre d’exemple, nous allons déplacer la zone collection (P4_ID_COLLECTION) pour la positionner sous le sous­titre 
(zone P4_SOUS_TITRE). Pour cela, il faut d’abord insérer une ligne vide puis déplacer la zone. 

© ENI Editions - All rigths reserved - 17 -


 

Lorsqu’un élément est sélectionné, son libellé et son type peuvent être modifiés en haut de la page. 

■ Lorsque  les  modifications  sont  terminées,  cliquez  sur  le  bouton  Suivant  >  puis  sur  le  bouton  Appliquer  les 
modifications. 

Vous pouvez ensuite exécuter la page pour visualiser les modifications. 

b. Créer et utiliser des listes de valeurs 

Pour  faciliter  la  saisie  des  informations  "collection"  et  "niveau",  nous  allons  proposer  des  listes  de  valeurs  à 
l’utilisateur. 

Dans  l’éditeur  de  page,  les  listes  de  valeurs  utilisées  par  la  page  sont  affichées  dans  la  zone  Liste  de  valeurs 
(LOV) située dans la colonne de droite (Composants partagés) : 

 
 

■ Pour créer une nouvelle liste de valeurs, cliquez sur l’icône de création  .

- 18 - © ENI Editions - All rigths reserved


 

■ Sur la première page, laissez l’option Entièrement nouveau sélectionnée puis cliquez sur le bouton Suivant >. 

■ Pour  les  différentes  valeurs  de  niveau,  nous  allons  utiliser  une  liste  statique.  Saisissez  le  nom  de  la  liste  de 
valeurs, sélectionnez l’option Statique puis cliquez sur le bouton Suivant >. 

© ENI Editions - All rigths reserved - 19 -


 

Sur  cette  page,  nous  allons  saisir  les  différentes  valeurs  de  liste.  APEX  permet  d’avoir  une  valeur  retournée 
différente  de  la  valeur  affichée  (ce  qui  permet  par  exemple  de  stocker  un  code  dans  la  base  et  non  la  valeur 
affichée). Pour notre exemple, les valeurs retournées sont les mêmes que les valeurs affichées. Lorsque la saisie 
est  terminée,  cliquez  sur  le  bouton  Créer  une  liste  de  valeurs  (LOV) ;  la  page  de  gestion  des  listes  de  valeurs 
s’affiche : 

Une liste de valeur n’appartient pas à une page de l’application ; c’est un composant partagé qui peut être utilisé 
dans plusieurs pages de l’application. 

- 20 - © ENI Editions - All rigths reserved


■ Cliquez sur le bouton Créer > pour créer une deuxième liste de valeurs. 

■ Sur la première page, laissez l’option Entièrement nouveau sélectionnée puis cliquez sur le bouton Suivant >. 

■ Pour les différentes valeurs de collection, nous allons utiliser une liste dynamique, basée sur une requête SQL. 
Saisissez le nom de la liste de valeurs, sélectionnez l’option Dynamique puis cliquez sur le bouton Suivant >. 

Sur cette page, nous allons saisir la requête associée à la liste de valeurs. La clause SELECT de cette requête doit 
comporter  deux  expressions  :  la  première  expression  donne  la  valeur  affichée  dans  la  liste  et  la  deuxième 
expression la valeur retournée. Pour notre exemple, nous allons retourner le contenu de la table COLLECTION, avec 
la  colonne  NOM  comme  valeur  affichée  et  la  colonne  ID  comme  valeur  retournée ;  la  liste  est  triée  par  ordre 
alphabétique sur le nom. Lorsque la saisie est terminée, cliquez sur le bouton Créer une liste de valeurs (LOV) ; la 
page de gestion des listes de valeurs s’affiche de nouveau. 

Nous  allons  maintenant  utiliser  ces  listes  de  valeurs  dans  notre  formulaire  de  saisie  des  livres.  Éditez  la  page 
correspondante, puis cliquez sur le lien de l’élément P4_ID_COLLECTION pour éditer ces propriétés. 

■ Dans l’éditeur des propriétés de l’élément, cliquez sur l’onglet Nom. 

© ENI Editions - All rigths reserved - 21 -


 

■ Sélectionnez la valeur Liste SELECT dans la liste Afficher en tant que. 

■ Cliquez sur l’onglet Liste de valeurs (LOV). 

■ Sélectionnez la liste de valeurs LISTE_COLLECTIONS et la valeur Oui dans la liste Afficher les valeurs Null. Dans 
la zone Valeur d’affichage Null, saisissez la valeur ­­aucune­­. 

■ Cliquez sur le bouton Appliquer les modifications. 

Nous allons faire la même chose pour le champ "niveau" (P4_NIVEAU), mais en optant pour un affichage en tant que 
groupe de boutons d’option : 

- 22 - © ENI Editions - All rigths reserved


 

■ Sélectionnez  la  liste  de  valeurs  LISTE_NIVEAUX.  Dans  la  zone  Nombre  de  colonnes,  saisissez  la  valeur  "4". 
Cliquez sur le bouton Appliquer les modifications. 

■ Exécutez la page pour visualiser le résultat : 

c. Ajouter des contrôles sur les données saisies 

APEX permet d’ajouter très facilement des contrôles sur les données saisies. 
Dans l’éditeur de page, les contrôles sur les données saisies sont affichés dans la zone Validations située dans la 
colonne du milieu (Traitement de page) : 

© ENI Editions - All rigths reserved - 23 -


 
 

■ Pour créer une nouvelle validation, cliquez sur l’icône de création  .

■ APEX permet de définir des validations de niveau d’élément ou de niveau de page. À titre d’exemple, nous allons 
créer  une  validation  de  niveau  d’élément  sur  le  nombre  de  pages.  Sélectionnez  l’option  Validation  de  niveau 
d’élément et cliquez sur le bouton Suivant >. 

- 24 - © ENI Editions - All rigths reserved


 

■ Sélectionnez l’élément correspondant au nombre de pages et cliquez sur le bouton Suivant >. 

■ Sélectionnez SQL comme méthode de validation et cliquez sur le bouton Suivant >. 

© ENI Editions - All rigths reserved - 25 -


 

■ Sélectionnez Expression SQL comme type de validation et cliquez sur le bouton Suivant >. 

■ Indiquez le nom de la validation, sélectionnez le mode d’affichage du message d’erreur et cliquez sur le bouton 
Suivant >. 

- 26 - © ENI Editions - All rigths reserved


 

■ Saisissez  ensuite  l’expression  SQL  permettant  de  valider  l’élément  et  le  message  d’erreur  associé.  Dans 
l’expression SQL, vous pouvez faire référence aux éléments de la page en faisant précéder le nom de l’élément 
par le caractère ":". Cliquez sur le bouton Suivant >. 

■ La  dernière  page  permet  de  préciser  dans  quels  cas  la  validation  doit  être  contrôlée.  Dans  la  liste  déroulante 
Type  de  condition, sélectionnez la valeur  La  demande  est  contenue  dans  Expression  1, puis saisissez "SAVE, 
CREATE" dans la zone Expression 1. 

■ Cliquez sur le bouton Créer pour créer la validation. 

© ENI Editions - All rigths reserved - 27 -


■ Exécutez la page et saisissez une valeur erronée pour visualiser le résultat : 

- 28 - © ENI Editions - All rigths reserved

Vous aimerez peut-être aussi