Documente Academic
Documente Profesional
Documente Cultură
AVANCEES
LICENCE PROFESSIONNELLE
699 25 83 95 / 676 67 65 23
aymarcm@yahoo.fr
1
SOMMAIRE
SOMMAIRE ................................................................................................................................................................2
CHAPITRE 0 : RAPPELS ..........................................................................................................................................3
I. QUELQUES NOTIONS.......................................................................................................................................3
II. EXPOSES ..........................................................................................................................................................3
CHAPITRE I : INTRODUCTION SUR LE SGBD ORACLE ........................................................................................4
I. RAPPELS SUR LES SGBD .................................................................................................................................4
II. BASE DE DONNEES ORACLE ET STANDARDS SQL .......................................................................................6
III. ARCHITECTURE D’UN SERVEUR ORACLE .................................................................................................11
IV. LE DICTIONNAIRE DE DONNEES ................................................................................................................16
V. PROCEDURE DE CREATION D’UNE LA BASE DE DONNNEES ...................................................................19
CHAPITRE II : LES OBJETS DE LA BASES DE DONNEES ORACLE .....................................................................20
I. TABLESPACE ..................................................................................................................................................20
II. UTILISATEURS ..............................................................................................................................................24
III. TABLES .........................................................................................................................................................25
IV. CONTRAINTES D’INTEGRITE......................................................................................................................34
V. VUES ..............................................................................................................................................................38
VI. INDEX ...........................................................................................................................................................40
VII. DECLENCHEURS (TRIGGERS)....................................................................................................................42
VIII. SEQUENCES ...............................................................................................................................................43
IX. PRIVILEGES ..................................................................................................................................................44
CHAPITRE III : LE LANGAGE ORACLE PL SQL. ..................................................................................................49
I. INTRODUCTION .............................................................................................................................................49
II. LES INSTRUCTIONS DE BASES.....................................................................................................................53
III. LES TABLEAUX.............................................................................................................................................57
IV. STRUCTURES ...............................................................................................................................................59
V. TABLES ET STRUCTURES ............................................................................................................................59
VI. TRANSACTIONS ...........................................................................................................................................60
VII. EXCEPTIONS ...............................................................................................................................................60
VIII. SOUS-PROGRAMMES .................................................................................................................................63
IX. 1.6 CURSEURS .............................................................................................................................................64
X. CURSEURS PARAMETRES .............................................................................................................................65
XI. TRIGGERS.....................................................................................................................................................67
XII. PACKAGES...................................................................................................................................................72
2
CHAPITRE 0 : RAPPELS
I. QUELQUES NOTIONS
1. Différence en un SGBD et une BD
2. Exemple de SGBD
3. LDD (CREATE, ALTER, DROP)
4. LMD (INSERT, UPDATE, DELETE)
5. Formes normales
6. Modèle Conceptuel de Données
7. Modèle Logique de Données
8. Modèle Physique de Données
9. Exemple d’Application dans le cas d’une gestion de vol
II. EXPOSES
1. Benchmarks pour les SGBDs
2. Systèmes d’information décisionnels et les Bases de données décisionnelles
3. Les SGBDs Géographiques
4. Bases de Données Hétérogènes
5. les SGBD Orientés Objet
6. Les SGBD Parallèles
7. Répartition, Réplication, Nomadisme, Hétérogénéité dans les SGBDs
8. Les bases de données et XML
3
CHAPITRE I : INTRODUCTION SUR LE SGBD ORACLE
I. RAPPELS SUR LES SGBD
I.1. Qu'est-ce qu'une base de données?
Une base de données (son abréviation est BD, en anglais DB, database) est une entité
dans laquelle il est possible de stocker des données de façon structurée et avec le moins de
redondance possible. Ces données doivent pouvoir être utilisées par des programmes, par des
utilisateurs différents. Ainsi, la notion de base de données est généralement couplée à celle
de réseau, afin de pouvoir mettre en commun ces informations, d'où le nom de base. On parle
généralement de système d'information pour désigner toute la structure regroupant les
moyens mis en place pour pouvoir partager des données.
Afin de pouvoir contrôler les données ainsi que les utilisateurs, le besoin d'un système
de gestion s'est vite fait ressentir. La gestion de la base de données se fait grâce à un système
appelé SGBD (système de gestion de bases de données) ou en anglais DBMS (Database
management system). Le SGBD est un ensemble de services (applications logicielles)
permettant de gérer les bases de données, c'est-à-dire:
• permettre l'accès aux données de façon simple
• autoriser un accès aux informations à de multiples utilisateurs
• manipuler les données présentes dans la base de données (insertion, suppression,
modification).
4
Modèle Famille SGBD Langage utilisé Constructeur SGBD Avantages Inconvenients
Réseau Codasyl DML • Univers de • Evolution difficile du schéma
Patrimoniaux Hiérarchique IMS DL1 modélisation riche • Manque d’indépendance entre
• Accès rapide programme et données
Relationnel par E. F CODD • SQL1 en 86 • Oracle depuis 1977 • Modèle simple et • Ne supporte pas les données
en 1970 avec ACM • SQL2 en 92 • Ingres depuis 1980 facile complexes 1NF
(Association of Computer • SQL2 un langage • Peu de sémantique
Machinery) puissant
Relationnel • Théorie relationnelle
et logique bien assise
• Standards existants
• Support de gestion et
de décision
Objet-Relationnel SQL3 • Informix • Garde les atouts du • Modèle complexe
• Oracle Modèle R • Langage complexe
• Sybase • Modèle dérivé du GL • Types de données non
• IBM/DB2 • Modèle extensible standardisés
Objet-Relationnel
• CA-OpenIngres • Standards existents
• SQL Server
• Versant
5
II. BASE DE DONNEES ORACLE ET STANDARDS SQL
Le concept du modèle relationnel est apparu pour la première fois grâce aux travaux
du Dr E. F Codd qui faisait des recherches devant permettre le partage des données en 1970.
Il publia alors une revue intitulée : "A Relational Model of Data for Large Shared Data Banks"
dans un magazine de ACM (Association of Computer Machinery). Très vite ce modèle a été
adopté pour les RGBD relationnels. C’est ainsi que très tôt IBM conçu un premier langage
(SEQUEL) pour implémenter ce concept. Peu après ce langage fut remplacé par SQL
(Structured Query Language) qui lui a été accepté largement comme langage standard des
SGBDR. En 1979, une société ambitieuse au nom de Relational Software, Inc. Proposa au
public le marché le premier SGBD commercial ; cette société s’appellera plus tard Oracle.
Au jour d’aujourd’hui le langage SQL a traversé quatre mouvements de normalisation
respectivement en 1986, 1992, 1999 et 2003. La constructeur Oracle a largement contribué
dans les travaux de normalisation de ce langage dans les rangs des comités ANSI et ISO. De
même, il s’est déployé à arrimer ses produits à la norme. La version 9i d’Oracle a un bon
niveau de conformité avec le standard SQL2 (1992) et niveau moyen de conformité avec la
norme SQL3 (1999) ce d’autant plus qu’à cette date la norme faisait son premier âge.
6
II.5. Nomenclature des objets de la base de données:
Il existe deux conventions de nomenclature des identificateurs : les identificateurs
sans doubles côtes et les identificateurs entourés des doubles côtes. Lorsqu’on crée un
objet par un identificateur avec des doubles côtes, celui-ci doit toujours être référencé avec
leurs côtes en respectant la casse. Par contre lorsqu’on définit des identifiants sans les côtes,
on est libre de les référencer avec ou sans celles-ci moyennant le respect de quelques règles.
Il faut du moins noter que quelques objets de la base de données ne peuvent être désignés
par des identifiants entourés de doubles côtes. Il s’agit notamment des liens des bases de
données logins des utilisateurs et de leurs mots de passe. Voici les principales règles des
identifiants :
• En fonction des plateformes Oracle recommande d’utiles les caractères ASCII standard
en raison de leur bonne compatibilité.
• Un identifiant peut comporter n’importe quel caractère alphanumérique y compris les
caractères suivants : #, $, _. Certains objets tels que les liens de base de données
admettent également les symboles suivants : @, et..
• Ne jamais commencer un identifiant par la chaîne (sys).
• Les identifiants sans côtes doivent forcement commencer par un caractère
alphabétique sans espace; cette contrainte n’est pas valable pour les identifiants avec
doubles côtes.
• Longueur : 1o à 30o (exceptés les noms des bases de données et les noms des liens de
bases de données qui ont respectivement un maximum de 8o et de 128o
• Les identifiants entourés des doubles côtes peuvent être des mots réservés Oracle
contrairement aux identifiants sans côtes (ceci n’est pas recommandé !).
• Les identifiants entourés de doubles côtes sont sensitifs à la casse contrairement aux
identifiants sans doubles côtes.
• A l’intérieur d’un espace de nom deux objets ne peuvent avoir le même nom ou
identifiant.
Un espace de nom est un annuaire propre à chaque schéma de la base de données qui
permet la résolution des noms des différents objets stockés dans ce schéma.
7
Objets liés à un schéma Objets indépendants d’un schéma
Partagent un même espace de nom (Possède chacun son espace de nom) :
- Tables, Vues, - Rôles,
- Séquences, - Synonymes Publics,
- Synonymes Privés, - Liens Publics Base de Données,
- Procédures Indépendantes, - Espace de Table,
- Fonctions Stockées Indépendantes, - Segments d’Annulation,
- Packages, - Profils,
- Vues Matérialisées, - Fichiers de Paramètres (PFILEs),
- Types Utilisateurs. - Fichiers de Paramètres côté serveur
Possède chacun son espace de nom (SPFILEs)
- Index, Contraintes, Dimensions,
- Clusters, Déclencheurs,
- Liens Privés de Bases de Données.
ENSEMBLISTES
9
II.10. Les Fonctions
Les fonctions employées sur Oracle sont soit des fonctions SQL soit des fonctions
PL/SQL, soit encore des fonctions définies par l’utilisateur. Les fonctions SQL sont des
fonctions définies par Oracle et mises à la disposition des utilisateurs qui n’a pour seul effort
que les appeler. Par contre, les fonctions utilisateurs sont des fonctions que le développeur
implémente par exemple avec du PLSQL ou du Java qui sont des langages pour lesquels il
existe des moteurs d’exécution construits pour Oracle.
Nous nous intéresserons particulièrement aux fonctions SQL. A la base des fonctions
SQL, on distinguera plusieurs familles de fonctions SQL : les fonctions « single Row » (un
enregistrement à la fois), les fonctions d’agrégat, les fonctions analytiques. Nous verrons un
certain nombre de ces fonctions au fur et à mesure que le programme évolue.
QUELQUES FONCTIONS
Chaines
Travaillent beaucoup plus sur les
Dates Numériques
caractères ascii standard et sont
pour la plupart sensibles à la casse
System Control ALTER SYSTEM Ajustement des paramètres de l’instance (le serveur).
Statement
Embedded SQL DDL, DML ou TCS incorporée dans un langage
Statements procédural.
Un processus utilisateur est créé lorsqu’un outil client désirant communiquer avec le
serveur Oracle est lancé (Un outil d'administration : SQL*Plus, OEM ; une application Oracle
Forms, etc.). Un processus utilisateur est un mécanisme qui va exécuter le code d'une
application ou d'un outil Oracle.
Pour faire fonctionner un outil application tel que SQL*Plus ou des applicatifs Oracle
Forms, Oracle crée un processus utilisateur (Client). L'UPI (User Program Interface) est un
mécanisme standardisé utilisé par un processus utilisateur pour communiquer avec un
processus serveur. C'est l'UPI qui génère l'appel au serveur Oracle.
Un processus serveur est créé lorsque un utilisateur se « logue » sur le serveur en
spécifiant un nom d'utilisateur, un mot de passe et un nom de base de données. Le
processus Serveur est créé sur le serveur Oracle. Le processus serveur va permettre
l'interaction entre le processus utilisateur et le serveur Oracle en récupérant les requêtes et
en les exécutant sur les serveurs Oracle. Le processus serveur inclus l'OPI (Oracle Program
Interface) qui est utilisé pour communiquer avec la base de données Oracle.
Une connexion se définit comme le lien entre un processus utilisateur et un processus
serveur.
Si l'utilisateur se connecte localement sur le serveur, le chemin de communication est
établi via un mécanisme de communication inter processus.
Si l'utilisateur se connecte via une machine cliente, un logiciel réseau est utilisé.
Une Session quant à elle est une connexion spécifique entre un utilisateur et un serveur
Oracle est appelé. La session démarre lorsque la demande de connexion de l'utilisateur est
validée par le serveur Oracle et se termine lorsqu'il se déconnecte ou lorsqu'une fin de
connexion prématurée se produit.
12
III.2. Architecture des processus Serveur
L’on rencontre trois types de processus dans un environnement Oracle :
• les processus utilisateur (User Processes),
• les processus d’arrière plan (BackGround Processes)
• les processus serveur (Server Processes).
Le type de processus qui nous intéresse c’est bien les processus serveur. Selon la
configuration que le DBA fait de ces processus, on aboutit à une certaine architecture. Ainsi,
on pourra configurer ces processus serveur pour obtenir deux types d’architecture de
serveurs: les serveurs dédiés et les serveurs partagés.
III.2.1. Serveur dédié (Dedicated Server)
Cette configuration prévoit que le nombre de processus client ne peut excéder le
nombre de processus serveur en SGA. En d’autres termes, si tous les processus serveur
démarrés sont déjà occupés par des processus client, alors s’il advient qu’un nouveau
processus client demande une session, Oracle démarre aussi un nouveau processus serveur
dédié. On constate ainsi qu’à mesure que les processus client augmentent, les processus
serveur augmentent également. On pourrait arriver une saturation de la mémoire par un
nombre excessif de processus serveur : conséquence, il y a baisse de performance. le schéma
suivant nous présente un schéma fonctionnel entre les processus serveur et les processus
client.
13
III.2.2. Serveur Partagé (Shared Server) :
Dans cette configuration plusieurs processus client peuvent partager un même serveur
au cours de leur session. Il s’avère qu’avec un certain nombre de serveur, Oracle arrive à
gérer un grand nombre de processus client. Le petit nombre de processus serveur réduit alors
la charge de la mémoire tout en imposant un plus grand rendement aux processus serveurs,
car ils sont appelés à travailler à plein temps. Cette solution est adéquate pour les systèmes
à forte sollicitation ou les serveurs de messagerie tels que yahoo. Contemplons le schéma
précédant
démarrage de l’instance.
SHARED_SERVERS Définit le nombre de dispatchers à lancer au démarrage de
l’instance.
14
Composants d’un serveur Oracle
III.4.1. Instance Oracle
L’instance est le module de traitement des données d’un serveur Oracle. Il est lui-
même constitué de deux classes d’objet : les structures de la mémoire et les processus
d’arrière plan. La structure de mémoire d’une instance s’appelle SGA (System Global Area).
La SGA se comporte en plusieurs composants dont les principales sont présentées ci-dessus.
Paramètre
Nom Rôle
d’Initialisation
Database Buffer
DB_CACHE_SIZE cache de traitement des transactions
Cache
Obligatoires
Les processus d’arrière-plan qu’un serveur Oracles sont divers et jouent chacun un
rôle précis lorsqu’il a été initialisé. Cependant parmi ces processus, il y en a qui sont
indispensables. On les appelle les processus d’arrière-plan obligatoires (mandatory
background processes). Le tableau ci-dessous nous en donne la liste exhaustive de ces
processus.
15
Processus Appellation Rôle
DBWn DataBase Transfère les données traitées en mémoire pour les stocker
Writer définitivement sur les fichiers de données.
LGWR Log Copies les entrées redo dans les fichiers redo online :
obligatoires
Processus
LCKn RAC Lock Manager, Instance gestionnaire des verrous en environnement multi instances
Optionnels
16
Le dictionnaire de données est automatiquement mis à jour par Oracle lorsque des
commandes de langage de définition des données (DDL) ou des commandes de manipulation
des données (DML), débouchant par exemple sur l'extension d'une table, sont exécutées.
Le dictionnaire de données stocke les informations sur :
• La structure de stockage de la base de données : Par exemple, les informations sur
les tablespaces, les blocs de données, les extensions et les segments d'une base de
données.
• La structure physique de la base de données, notamment les informations sur les
fichiers de contrôle, les fichiers redo log et les fichiers de données.
• Les noms et les définitions des objets, tels que les tables, les vues, les index, les
clusters, les séquences, les triggers (ou déclencheurs), les fonctions, les procédures et
les packages mais aussi les informations sur les espaces alloués et l’espace actuellement
utilisé par les objets.
• Les contraintes d’intégrité définies pour les tables d'une base de données.
• Les noms des utilisateurs de la base de données et les privilèges et les rôles attribués
à chaque utilisateur. Les privilèges définissent les opérations qu’un utilisateur peut
effectuer dans la base de données. Un rôle est constitué d’un ensemble de privilèges.
• L’audit sur une base de données : par exemple, le dictionnaire de données fournit les
informations sur les utilisateurs qui ont accédé à des objets ou les ont mis à jour. L’audit
correspond à l’enregistrement d’opérations spécifiques en fonction d'un utilisateur, d'un
objet ou d'un privilège.
Le dictionnaire de données possède deux composants :
• les tables de base
• les vues du dictionnaire de données.
18
IV.5. Informations contenues dans le dictionnaire de données
Vues Descriptions
Dictionary Vues générales
dict_columns
dba_tables Informations sur les objets, tels que les tables, les
dba_objects contraintes, les gros objets et les colonnes
dba_lobs
dba_tab_columns
dba_constraints
dba_users Informations sur les privilèges et les rôles des
dba_sys_privs utilisateurs
dba_roles
dba_extents Allocation d’espace pour les objets de la base de
dba_free_space Données
dba_segments
dba_rollback_segs Structures générales de la base de données
dba_data_files
dba_tablespaces
Dba_audit_trail Informations d’audit
Dba_audit_objects
Dba_audit_obj_opts
La vue DICTIONARY ou DICT ou CATALOG ou encore CAT (qui sont des synonymes) du
dictionnaire de données fournit une vue d’ensemble de toutes les données du dictionnaire de
données. Utiliser la vue DICTIONARY afin de vous éviter d'avoir à se souvenir de toutes les
vues et des informations fournies par chacune de ces vues.
Exemple :
L’objectif est de récupérer les noms des segments de rollback de la base de données
en interrogeant la vue DICTIONARY.
SELECT *
FROM dictionary
WHERE table_name LIKE UPPER (‘%ROLLBACK%’);
TABLE_NAME COMMENTS
---------------------------- --------------------------
DBA_ROLLBACK_SEGS Description of rollback segments
Cette requête affiche le nom des vues qui contiennent des informations sur les
segments de rollback. Pour afficher les noms des segments de rollback :
SELECT segment_name FROM dba_rollback_segs;
SEGMENT_NAME
------------------------------
SYSTEM
RB_TEMP
RB1
RB2
RB3
19
CHAPITRE II : LES OBJETS DE LA BASES DE DONNEES
ORACLE
I. TABLESPACE
Un tablespace est un espace logique qui contient les objets stockés dans la base de
données comme les tables ou les indexes. En d’autres termes, le tablespace est une unité
logique de stockage composée de fichiers de données. Un tablespace est composé d'au moins
un datafile, c'est à dire un fichier de données qui est physiquement présent sur le serveur à
l'endroit stipulé lors de sa création. C’est à partir de cet objet que l’on va gérer le stockage
principalement ; ranger les objets par type (application, service, index, tables, etc…) et ainsi
permettre une administration plus fluide et plus souple, une meilleure optimisation, et
performances. Le stockage est organisé en segments et extent. Autrement dit, chaque
datafile est constitué de segments d'au moins un extent (ou page) lui-même constitué d'au
moins 3 blocs : l'élément le plus petit d'une base de données.
Une base de données Oracle possède au minimum 4 tablespaces.
• SYSTEM (dictionnaire de données - Tablespace SYSTEM)
• SYSAUX (system auxiliaire composants oracle - Tablespace SYSAUX)
• UNDOTBS (segments d’annulations - Tablespace UNDO)
• TEMP (segments temporaires - Tablespace TEMPORAIRE)
Puis des tablespace spécifiquement créés pour des données applicatives et
utilisateurs.
Il est déconseillé de stocker des données applicatives / utilisateurs dans SYSTEM et
SYSAUX.
Voir les tablespace dans Oracle
SELECT tablespace_name, status, contents, extent_management
FROM dba_tablespaces;
I.1. Creation d’un tablespace permanent avec l'ordre sql CREATE TABLESPACE.
On appelle Tablespace permanents, les Tablespace autres que TBS UNDO et TBS
TEMPORARY
Syntaxe de création d’un tablespace
CREATE [ BIGFILE | SMALLFILE ] TABLESPACE Name
DATAFILE file_specification SIZE integer [ K | M | G | T | P | E ] [REUSE]
AUTOEXTEND
{ OFF
| ON [ NEXT integer [ K | M | G | T | P | E ]]
[ MAXSIZE { UNLIMITED | integer [ K | M | G | T | P | E ] } ]
| DEFAULT [ { COMPRESS | NOCOMPRESS } ]
STORAGE
({ INITIAL integer [ K | M | G | T | P | E ]
| NEXT integer [ K | M | G | T | P | E ]
| MINEXTENTS integer
| MAXEXTENTS { integer | UNLIMITED }
| PCTINCREASE integer
| FREELISTS integer
| FREELIST GROUPS integer
| OPTIMAL [ integer [ K | M | G | T | P | E ]
| NULL
]
| BUFFER_POOL { KEEP | RECYCLE | DEFAULT }
})
EXTENT MANAGEMENT
{ LOCAL
[ AUTOALLOCATE
| UNIFORM
20
[ SIZE integer [ K | M | G | T | P | E ] ]
]
| DICTIONARY
}
SEGMENT SPACE MANAGEMENT { AUTO | MANUAL }
| [ MINIMUM EXTENT integer [ K | M | G | T | P | E ]
| BLOCKSIZE integer [ K ]
| { LOGGING | NOLOGGING }
| FORCE LOGGING
| FLASHBACK { ON | OFF }
| { ONLINE | OFFLINE };
Exemples :
CREATE SMALLFILE TABLESPACE "DATA"
DATAFILE 'C:\ORACLE\PRODUCT\10.2.0\ORADATA\DBTEST\DATA.DBF' SIZE 2G
AUTOEXTEND ON NEXT 100M MAXSIZE 5000M
LOGGING
ONLINE
PERMANENT
BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 10M
SEGMENT SPACE MANAGEMENT AUTO;
sinon
22
ATTENTION, la clause AND DATAFILES n'est pas nécessaire pour Oracle-managed files, car
ils sont retirés du système, même si vous ne spécifiez pas AND DATAFILES.
Donc si vous êtes en Oracle-managed files et que vous ne désirez pas supprimer les fichiers
physiques, utilisez KEEP DATAFILES.
I.4. Oracle Tablespace temporaire (TEMPORARY TABLESPACE)
Oracle effectue de nombreux tris (utilisateurs et noyau) suite aux requêtes du type ORDER
BY, GROUP BY, UNION, DISTINCT, etc.
Ils sont principalement effectués dans une zone de tri en mémoire (PGA) sauf si celle-ci est
insuffisante alors il utilisera le TEMPORARY TABLESPACE.
Attention si votre base de données n’en possède pas, les tris seront effectués dans le
tablespace SYSTEM. Le tablespace temporaire peut être géré en mode local ou dictionnaire.
Le mode conseillé est le mode LOCAL. Plusieurs tablespace temporaires peuvent être en
ligne et actifs simultanément dans une base de données et faire partie d'un groupe de
tablespaces temporaires. Amélioration des temps de réponses pour les requêtes en
parallèles.
Création d’un Tablespace temporaire avec CREATE TABLESPACE.
SQL> CREATE TEMPORARY TABLESPACE temp
TEMPFILE 'c:\oracle\oradata\dbtest\temp01.dbf' SIZE 1000M
EXTENT MANAGEMENT LOCAL
AUTOEXTEND ON NEXT 100M MAXSIZE 5000M ;
Remarque :
Un utilisateur Oracle peut être identifié par le Système d'exploitation ou par Oracle.
Les droits utilisateurs sont gérés avec des privilèges systèmes (ex : droit de créer une table).
Les droits utilisateurs sont gérés avec des privilèges objets (ex : droit de mettre à jour une
table). Privilèges systèmes et Privilèges objets peuvent être regroupés dans un RÔLE. Un
RÔLE est un regroupement de privilèges systèmes et de privilèges objets. On définit à la
création du USER le ou les Tablespace (ou aucun) dans lesquels il sera autorisé à créer des
objets. On définit à la création du USER des Quota d'utilisation dans les Tablespace.
24
Création d'un compte utilisateur (User) identifié par le système d'exploitation.
SQL> CREATE USER "SRV_ORA\DANIEL"
IDENTIFIED EXTERNALLY
DEFAULT TABLESPACE data
TEMPORARY TABLESPACE temp
PROFILE DEFAULT
ACCOUNT UNLOCK;
A ce moment précis, aucune connexion possible encore.
SQL> connect /
ERROR:
ORA-01045: l'utilisateur SRV_ORA\DANIEL n'a pas le privilege CREATE
SESSION ;
connexion refusée
Nous allons donc donner le rôle CONNECT à l'utilisateur Daniel (CREATE SESSION fait partie
de ce RÔLE).
SQL> GRANT CONNECT TO "SRV_ORA\DANIEL";
Grant succeeded.:m
SQL> connect /
Connected.
SQL> show user
USER is "SRV_ORA\DANIEL"
III. TABLES
III.1. Présentation
Une table est un objet de la base de données qui sert à stocker les données des
utilisateurs. C’est un ensemble de lignes et de colonnes. L'intersection d'une ligne et d'une
colonne est appelée un champ. Une table peut contenir au maximum 1000 colonnes et doit
être nommée selon les conventions de nommage d'Oracle. En plus de ces règles, il y a
quelques comportements qu’un bon développeur Oracle devrait adopter :
25
• Les noms de tables et des colonnes doivent être explicites et représentatifs des
informations contenues respectivement dans les tables et les colonnes.
• Il est fortement conseillé de nommer de manière identique une colonne qui fait
référence à une autre colonne d'une autre table.
Oracle propose plusieurs types de tables dont on peut user pour stocker nos
informations. Le choix du type de table est basé sur les vertus et les limites éventuelles de
types de tables présentés.
Les différents types disponibles sont les suivants :
• Les tables normales : c’est l'élément le plus communément utilisé pour stocker les
données utilisateur. Il s'agit du type de table par défaut qui constitue le sujet principal
de ce paragraphe
• Les tables partitionnées : elle permet de créer des applications évolutives. Elles sont
adaptées pour les tables volumineuses avec accès simultanés. Elle contient une ou
plusieurs partitions qui stockent chacune les lignes partitionnées. Une partition
constitue un segment qui peut se trouver dans un tablespace différent.
• Les tables organisées en index : c’est une table normale contenant un index de clé
primaire dans une ou plusieurs de ses colonnes. Ce type de table nous évite l’usage de
deux espaces de stockage distincts pour la table et un index. Ces tables accélèrent
l'accès par clé aux données des tables dans les interrogations impliquant des
recherches de correspondance exacte ou des recherches sur des plages de données.
Les insertions de nouvelles données sont plus coûteuses dans la mesure où, il faut les
insérer au bon endroit quitte à déplacer plusieurs enregistrements.
• Les tables incluses dans un cluster : Un cluster est constitué de plusieurs tables qui
partagent les mêmes blocs de données, regroupés du fait qu'ils partagent des colonnes
et souvent utilisés conjointement. Il est possible de stocker les données de plusieurs
tables dans un même objet ; cet objet s’appelle un cluster de tables.
Il faut noter que le serveur Oracle permet également de manipuler les tables
temporaires. La différence entre une table temporaire et une table permanente est que les
données d’une table temporaire sont stockées en mémoire contrairement aux données d’une
table permanente qui sont stockés dans des fichiers qui sont des supports permanents.
Lorsque les données d’une table temporaire deviennent volumineuses, certaines sont
transférées dans un tablespace temporaire. Une chose qui en fait la différence est qu’une
fois créée, une table temporaire est accessible à tous les utilisateurs moyennant le fait que
l’on ne peut accéder qu’aux données que l’on a introduites. Il en est de même pour la
troncature des tables temporaires.
Remarques :
• En général, les tables doivent être créées avec une clé primaire.
• Si vous avez défini le paramètre MINIMUM EXTENT du tablespace, la taille des
extensions la table est arrondie au multiple suivant le plus proche.
• Si vous omettez la clause [NO] LOGGING, l'attribut de journalisation de la table
correspond par défaut à celui du tablespace dans lequel elle réside.
• Si vous affectez au paramètre MINEXTENTS une valeur supérieure à 1 et que le
tablespace contient plusieurs fichiers de données, les extensions sont réparties dans
les différents fichiers du tablespace.
Exemple :
CREATE TABLE employee (
id NUMBER (7),
last_name VARCHAR2 (25),
dept_id NUMBER (7))
PCTFREE 20 PCTUSED 50
27
STORAGE (INITIAL 200K NEXT 200K PCTINCREASE 0 MAXEXTENTS 50)
TABLESPACE data;
Exemple : CREATE TABLE avec une PRIMARY KEY et CHECK.
CREATE TABLE scott.vehicule
( vehicule_id NUMBER(6)
, vehicule_marque VARCHAR2(30) CONSTRAINT ck_vehic_marq_nn NOT NULL
, vehicule_modele VARCHAR2(30) CONSTRAINT ck_vehic_mod_nn NOT NULL
, date_sortie DATE
, vehicule_prix NUMBER(10,2)
, CONSTRAINT pk_vehicule_id PRIMARY KEY (vehicule_id)
)
TABLESPACE data;
Exemple : CREATE TABLE avec une PRIMARY KEY (INDEX COMPOSITES sur 3 Colonnes).
CREATE TABLE scott.vehicule
( vehicule_id NUMBER(6)
, vehicule_marque VARCHAR2(30) DEFAULT 'RENAULT'
, vehicule_modele VARCHAR2(30)
, date_sortie DATE
, vehicule_prix NUMBER(10,2)
, CONSTRAINT pk_vehicule_id PRIMARY KEY (vehicule_id,
vehicule_marque,
vehicule_modele)
)
TABLESPACE data;
Exemple : CREATE TABLE avec un Index UNIQUE (unicité) et 3 CHECK.
CREATE TABLE scott.vehicule
( vehicule_id NUMBER(6)
, vehicule_marque VARCHAR2(30)
, vehicule_modele VARCHAR2(30)
, date_sortie DATE CONSTRAINT ck_vehic_date_nn NOT NULL
, vehicule_prix NUMBER(10,2) CONSTRAINT ck_vehic_prix_nn NOT NULL
, CONSTRAINT ck_vehic_prix_min CHECK (vehicule_prix > 0)
, CONSTRAINT un_vehicule_id UNIQUE (vehicule_id)
)
TABLESPACE data;
COMMENT ON COLUMN SCOTT.VEHICULE.VEHICULE_PRIX IS 'Prix neuf';
Remarques
Quelques règles à observer lors de la création des tables :
• Placez les tables dans des tablespaces distincts et non dans des tablespaces contenant
des segments de undo, des segments temporaires et des index.
• Placez les tables dans des tablespaces gérés localement pour éviter la fragmentation.
• Pour améliorer les performances du balayage complet de tables, alignez les tailles
d'extension à l'aide du paramètre d'initialisation.
• Utilisez la clause CACHE pour les petites tables de référence pouvant être
fréquemment utilisées.
28
Les autres clauses, telles que TABLESPACE, STORAGE et les paramètres d'utilisation
des blocs peuvent être définis lors de la création d'une table à partir d'une autre table.
Utilisez la clause NOLOGGING pour interdire la génération d'entrées de journalisation (redo
log entries) et accélérer la création de la table. Lorsque vous créez une table en copiant une
table, les contraintes, les déclencheurs et les privilèges de table ne sont pas copiées. Si la
table d'origine contient une colonne NOT NULL, cette colonne existe également dans la
nouvelle table.
III.2.4. Création des tables temporaires
Outre les tables permanentes, vous pouvez créer des tables temporaires qui
contiennent les données privées des sessions qui n'existent que le temps d'une transaction ou
d'une session.
La commande CREATE GLOBAL TEMPORARY TABLE permet de créer une table
temporaire spécifique à une transaction ou à une session. Les données d'une table
temporaire de transaction et celles d'une table temporaire de session existent
respectivement pendant la durée de la transaction et pendant la durée de la session.
Les données d'une session sont privées. Chaque session ne peut voir et modifier que ses
propres données. Aucun verrou DML n'est placé sur les données d'une table temporaire. Les
clauses qui contrôlent la durée de stockage des lignes sont :
• ON COMMIT DELETE ROWS : indique que les lignes sont uniquement visibles dans la
transaction,
• ON COMMIT PRESERVE ROWS : indique que les lignes sont visibles pour toute la
session.
Vous pouvez créer des index, des vues et des déclencheurs dans les tables temporaires
et utiliser également les utilitaires Export et Import pour exporter et importer la définition
d'une table temporaire. Toutefois, aucune donnée n'est exportée, même si vous utilisez
l'option ROWS. La définition d'une table temporaire est visible dans toutes les sessions.
Exemple :
CREATE GLOBAL TEMPORARY TABLE employee_temp
AS SELECT * FROM employee;
III.3.2. Ajouter un champ dans une table Oracle avec ALTER TABLE ADD.
Syntaxe ALTER TABLE ADD.
ALTER TABLE [ schema. ]table ADD { ( column [ datatype ] ) } ;
30
Exemple ALTER TABLE MODIFY.
SQL> ALTER TABLE countries MODIFY (duty_pct NUMBER(3,2));•Passage de NUMBER(2,2) à NUMBER(3,2)
SQL> ALTER TABLE supplier MODIFY supplier_name NOT NULL; •Passage de NULL autorisé à NOT NULL
Syntaxe :
TRUNCATE TABLE [schema.] table
[{DROP | REUSE} STORAGE]
Exemple
ALTER TABLE employee
DROP COLUMN comments
CASCADE CONSTRAINTS CHECKPOINT 1000;
Remarque : La suppression d'une colonne peut prendre un certain temps, car toutes
les données de la colonne sont supprimées de la table.
Vous pouvez obtenir des informations sur les tables à partir du dictionnaire de données.
Pour obtenir le numéro d'objet de données et l'emplacement de l'en-tête de table de toutes
les tables appartenant à l'utilisateur SUMMIT, lancez l'interrogation suivante :
SELECT t.table_name, o.data_object_id, s.header_file, s.header_block
FROM dba_tables t, dba_objects o, dba_segments s
WHERE t.owner=o.owner
AND t.table_name=o.object_name
AND t.owner=s.owner
AND t.table_name=s.segment_name
AND t.owner='SUMMIT';
34
• le mot clé CURRENT_TIME (heure de saisie)
• le mot clé CURRENT_TIMESTAMP (date et heure de saisie)
35
IV.4. Tester l'unicité d'une valeur
La clause UNIQUE permet de vérifier que la valeur saisie pour un champ n'existe pas
déjà dans la table. Cela permet de garantir que toutes les valeurs d'une colonne d'une table
seront différentes.
(Pour une contrainte sur une table :)
UNIQUE (colonne1, colonne2,...)
(Pour une contrainte sur une colonne :)
UNIQUE
Interdit qu'une colonne (ou la concaténation de plusieurs colonnes) contienne deux
valeurs identiques.
Cette contrainte UNIQUE convient à des clés candidates. Cependant une colonne
UNIQUE peut avoir des valeurs NULL et une contrainte UNIQUE ne correspond donc pas
toujours à un identificateur.
Les clés étrangères permettent de définir les colonnes d'une table garantissant la
validité d'une autre table. Ainsi, il existe des éléments (appelés triggers, ou en français
gâchettes ou déclencheurs) permettant de garantir l'ensemble de ces contraintes que l'on
désigne par le terme d'intégrité référentielle, c'est-à-dire notamment de s'assurer qu'un
tuple utilisé à partir d'une autre table existe réellement.
Des contraintes d'intégrité peuvent être alors ajoutées ou supprimées par la commande
ALTER TABLE. On peut aussi modifier l'état de contraintes par MODIFY CONSTRAINT. On ne
peut ajouter que des contraintes de table. Si on veut ajouter (ou modifier) une contrainte de
colonne, il faut modifier la colonne.
Exemple
ALTER TABLE EMP
DROP CONSTRAINT NOM_UNIQUE
ADD CONSTRAINT SAL_MIN CHECK (SAL + NVL (COMM,0) > 1000)
RENAME CONSTRAINT NOM1 TO NOM2
MODIFY CONSTRAINT SAL_MIN DISABLE
V. VUES
L’exécution d’une requête produit toujours une relation. Cela suggère la possibilité
d’ajouter au schéma des tables ’virtuelles’ qui ne sont rien d’autres que le résultat de
38
requêtes stockées. De telles tables sont nommées des vues dans la terminologie
relationnelle. On peut interroger des vues comme des tables stockées.
Une vue n’induit aucun stockage puisqu’elle n’existe pas physiquement, et permet
d’obtenir une représentation différente des tables sur lesquelles elle est basée.
On peut donner plusieurs définitions aux vues dans une base de données et chacune
de ces définitions est révélatrice des nombreuses vertus que nous offrent les vues.
Une vue est une structure logique basée sur une table ou une autre vue. A ce titre, on
peut remarquer qu’une vue ne peut exister que si sa table de base ou sa vue de base existe
bel et bien. On peut aussi dire qu’une vue est une table virtuelle ou une requête stockée.
Cette définition nous montre l’importance des vues sur le plan temps d’exécution des
requêtes. En effet, étant une requête compilée et stockée, on gagne en temps avec les vues
plutôt que d’utiliser une imbrication des sous requêtes qui prendront plus de temps dans la
phase de l’analyse, et ce chaque fois qu’elle sera invoquée.
Intérêts des vues :
• Simplification de l’accès aux données en masquant la complexité des éventuelles
opérations de jointures sous-jacentes.
• Sauvegarde indirecte des requêtes complexes.
• Présentation de mêmes données sous différentes formes adaptées aux différents
usagers.
• Support de l’indépendance logique : si la table de base est modifiée, les vues associées
doivent être refaites, mais les requêtes qui interrogent ces vues n’en sont pas
affectées.
• Renforce la sécurité des données dans la mesure où seules les lignes et colonnes
destinées à un utilisateur lui sont présentées.
Exemple : on peut créer une vue qui ne contient que les cinémas parisiens :
CREATE VIEW ParisCinemas
AS SELECT * FROM Cinema WHERE ville = ’Paris’
On peut aussi en profiter pour restreindre la vision des cinémas parisiens à leur nom
et à leur nombre de salles.
CREATE VIEW SimpleParisCinemas
AS SELECT nom, COUNT(*) AS nbSalles
FROM Cinema c, Salle s
WHERE ville = ’Paris’
AND c.nom = s.nomCinema
GROUP BY c.nom
Enfin un des intérêts des vues est de donner une représentation dénormalisée de la
base, en regroupant des informations par des jointures. Par exemple on peut créer une vue
Casting donnant explicitement les titres des films, leur année et les noms et prénoms des
acteurs.
CREATE VIEW Casting (film, annee, acteur, prenom) AS
39
SELECT titre, annee, nom, prenom
FROM Film f, Role r, Artiste a
WHERE f.idFilm = r.idFilm
AND r.idActeur = a.idArtiste
Remarque : on a donné explicitement des noms d’attributs au lieu d’utiliser les
attributs de la clause SELECT.
Maintenant, on peut utiliser les vues et les tables dans des requêtes SQL. Par exemple
la requête : Quels acteurs ont tourné un film en 1997 s’exprime par :
SELECT acteur, prenom
FROM Casting
WHERE annee = 1997
On peut ensuite donner des droits en lecture sur cette vue pour que cette information
limitée soit disponible à tous.
GRANT SELECT ON Casting TO PUBLIC
VI. INDEX
Un index est un objet utilisé pour optimiser la recherche des éléments dans une table
à l'aide d'un pointeur. L’usage des index est transparent à l'utilisateur final dont les sens ne
peuvent qu’apprécier la rapidité ou la lenteur du système. Il incombe donc aux développeurs
et administrateurs de la base de données de bien choisir quel type d’index est bon pour leur
40
système. Lorsqu‘ils sont créés, leur but est de réduire les lectures physiques (le nombre
d'entrées/sorties) et par ricochet le temps de recherche des enregistrements. Lorsqu’une
recherche est effectuée sur une colonne qui n'a pas été indexée, la requête fait une
recherche séquentielle sur chaque ligne et vérifie si les critères de recherche lui sont
applicables. Par contre si la colonne a été indexée, le serveur localise directement les lignes
qui correspondent, d'où un gain de temps. Il faut cependant être vigilant quant à l'utilisation
des index car ils ne sont pas une garantie pour l'amélioration de la vitesse, car chaque
opération DML effectuée force le serveur à mettre à jour les index.
VIII. SEQUENCES
Une séquence est un objet de la base de données qui génère des numéros uniques qui
pourront être insérés dans une colonne comme clé primaire. Les séquences ne sont pas des
objets propres à un schéma (utilisateur), ils peuvent donc être utilisés par tous les
utilisateurs.
Une séquence incrémente ou décrémente un compteur dans une routine Oracle (ce qui
génère un gain de temps et de codage). Il est possible de stocker les valeurs dans un cache,
ce qui accélèrera l'accès aux valeurs de la séquence.
CREATE SEQUENCE [schema.]séquence
[INCREMENT BY n]
[START WITH n]
[MAXVALUE n | NOMAXVALUE]
[MINVALUE n | NOMINVALUE]
[CYCLE | NOCYCLE]
[CACHE n | NOCACHE]
[ORDER | NOORDER];
Remarques
• Si aucune de ces clauses n’est définie, alors Oracle pose INCREMENT BY 1, START WITH
1.
• Si on pose INCREMENT BY -1, START WITH -1, alors Oracle construit une séquence
décroissante.
• On accède aux séquences avec les instructions par SELECT, INSERT, UPDATE.
Exemple :
DROP SEQUENCE RCCM.SEQ_PLCODEPERSONNEL;
43
IX. PRIVILEGES
Un privilège attribué à un utilisateur lui donne l’accès à un certain nombre d’action
sur la base de données. On distingue les privilèges objets et les privilèges systèmes. Les
privilèges objets sont des droits accordés à un utilisateur afin qu’il puisse effectuer des
opérations DML sur des objets déjà existants. Les privilèges système sont des droits accordés
à un utilisateur pour effectuer des opérations DDL sur des objets inexistants ou déjà existants.
Un rôle est un ensemble de privilèges attribuables à des utilisateurs qui ont en commun
certaines tâches dans le système nécessitant les mêmes privilèges.
Pour qu’un exécuter une instruction sur le serveur Oracle, ce dernier doit détenir des
privilèges suffisants à cet effet. On distingue deux familles de privilèges : les privilèges
système et les privilèges objet.
IX.1. Les privilèges système
Les privilèges système sont les privilèges qui confère à un utilisateur de la base de
données de pourvoir de créer et de maintenir des objets de la base de donnés tels que les
synonymes, les tables, les séquences, etc. On dénombre plus de 100 privilèges système
repartis sur les différents objets de la base de données ou des domaines d’activité.
Objet ou Domaine d’Activité Privilèges
Fonction administrative ALTER SYSTEM
AUDIT SYSTEM
AUDIT ANY
ALTER DATABASE
ANALYSE ANY
SYSDBA
SYSOPER
GRANT ANY
Accès à la BD(Database Access) CREATE SESSION
ALTER SESSION
RESTRICTED SESSION
Tablespaces CREATE TABLESPACE
ALTER TABLESPACE
DROP TABLESPACE
MANAGE TABLESPACE
UNLIMITED TABLESPACE
Utilisateurs (Users) CREATE USER
BECOME USER
ALTER USER
DROP USER
Segments d’Annulation (Undo CREATE ROLLBACK SEGMENT
Segments) ALTER ROLLBACK SEGMENT
DROP ROLLBACK SEGMENT
Tables CREATE TABLE
CREATE ANY TABLE
ALTER ANY TABLE
BACKUP ANY TABLE
LOCK ANY TABLE
COMMENT ANY TABLE
DROP ANY TABLE
INSERT ANY TABLE
SELECT ANY TABLE
UPDATE ANY TABLE
DELETE ANY TABLE
Clusters CREATE CLUSTER
44
CREATE ANY CLUSTER
ALTER ANY CLUSTER
DROP ANY CLUSTER
Index CREATE ANY INDEX
ALTER ANY INDEX
DROP ANY INDEX
Synonymes (Synonyms)
Vues (Views) CREATE SYNOYM
CREATE ANY SYNONYM
DROP ANY SYNONYM
CREATE PUBLIC SYNONYM
DROP PUBLIC SYNOSYM
Séquences CREATE SEQUENCE
CREATE ANY SEQUENCE
ALTER ANY SEQUENCE
DROP ANY SEQUENCE
SELECT ANY SEQUENCE
Liens de BD (Database Links) CREATE DATABASE LINK
CREATE PUBLIC DATABASE LINK
DROP PUBLIC DATABASE LINKK
Rôles CREATE ROLE
DROP ANY ROLE
GRANT ANY ROLE
ALTER ANY ROLE
Transactions FORCE TRANSACTION
FORCE ANY TRANSACTION
PL/SQL CREATE PROCEDURE
CREATE ANY PROCEDURE
ALTER ANY PROCEDURE
DROP ANY PROCEDURE
EXECUTE ANY PROCEDURE
Déclencheurs (Triggers) CREATE TRIGGER
CREATE ANY TRIGGER
ALTER ANY TRIGGER
DROP ANY TRIGGER
Profils (Profiles) CREATE PROFILE
ALTER PROFILE
DROP PROFILE
ALTER RESOURCE COST
Vues matérialisées (Materialized CREATE SNAPSHOT
Views) CREATE ANY SNAPSHOT
Ou (Snapshot) LATER ANY SNAPSHOT
DROP ANY SNAPSHOT
Annuaires (Directories) CREATE ANY DIRECTORY
DROP ANY DIRECTORY
Types (Types) CREATE TYPE
CREATE ANY TYPE
ALTER ANY TYPE
DROP ANY TYPE
EXECUTE ANY TYPE
Bibliothèques (Libraries) CREATE LIBRARY
CREATE ANY LIBRARY
ALTER ANY LIBRARY
45
DROP ANY LIBRARY
EXECUTE ANY LIBTRARY
NB :
Tout privilège comportant le mot ANY est un privilège système
Les privilèges SYSDBA et SYSOPER
Seuls les utilisateurs habilités à faire des tâches administratives doivent se connectés
avec les privilèges SYSDBA et SYSOPER.
Catégorie Exemple
SYSOPER ALTER DATABASE ARCHIVELOG
RECOVER DATABASE
ALTER DATABASE BACKUP CONTROLFILE TO
ALTER DATABASE OPEN | MOUNT
SHUTDOWN
STARTUP
SYSDBA SYSOPER PRIVILEGES WITH ADMIN OPTION
CREATE DATABASE
ALTER DATABASE BEGIN/END BACKUP
RESTRICTED SESSION
RECOVER DATABASE UNTIL
IX.1.1. Attribution d’un privilège système
Pour attribuer un privilège système à un utilisateur le donateur doit lui-même avoir
reçu ce privilège avec l’option WITH ADMIN OPTION ou encore posséder au moins le privilège
GRANT ANY PRIVILEGE.
Syntaxe :
GRANT system_privilege [, system_privilege ]
TO {user | role | PUBLIC} [, {user | role | PUBLIC}]
[WITH ADMIN OPTION]
Sémantique:
system_privilege : spécifie le privilège système à accorder à un utilisateur ou un rôle.
PUBLIC : Attribut le système privilège à tous les utilisateurs
WITH ADMIN OPTION : permet à l’utilisateur d’attribuer à son tour le(s) privilège(s)
reçu(s) à d’autres utilisateurs ou rôles.
NB : cette opération peut également être réalisée avec OEM dans son module sécurité.
IX.1.2. Supprimer des privilèges système
Un privilège système peut être supprimé avec la commande REVOKE. Un utilisateur
peut supprimer un privilège système à un autre utilisateur dès lors qu’il possède un privilège
système avec ADMIN OPTION.
NB : il n’est pas nécessaire que celui qui révoque soit celui qui avait accordé le
privilège système.
Syntaxe:
REVOKE system_privileg [, system_privilege]
FROM {user | role | PUBLIC} [, {user|role|PUBLIC}]
Sémantique:
ALL : Supprime tous les privilèges objet qui ont été accordé à l’utilisateur
ON : Identifie l’objet sur lequel les privilèges objet sont supprimés
FROM : Identifie des utilisateurs ou des rôles qui ont leurs privilèges objets supprimés
CASCADE CONSTRAINTS : Supprime toutes les contraintes d’intégrité référentielle que
la suppression a définit en utilisant les privilèges REFERENCES ou ALL
Des effets en cascade peuvent être observés lors de la suppression d’un privilège
système relié à une opération de DML. Par exemple, si SELECT ANY TABLE est attribué à un
utilisateur et que ce dernier a créé des procédures utilisant la table, toutes les procédures
se trouvant dans le schéma de l’utilisateur doivent être recompilées avant qu’elles ne
puissent être réutilisées.
47
La suppression d’objet privilège aura aussi un effet en cascade quand WITH GRANT
OPTION est donné.
Bon à savoir:
Un utilisateur désireux d’exécuter une procédure n’a pas besoin d’avoir les droits
respectifs sur les objets que la procédures manipule dans son code. Il n’a besoin que
du privilège EXECUTE. Cependant le propriétaire de la procédure lui a besoin de ces
privilèges. Ces privilèges doivent lui être cédés directement et non à travers des rôles.
Une procédure stockée a besoin d’être recompilée
Le retrait du privilège REFERENCES à un utilisateur qui en avait déjà usé pour créer
une CI référentielle pourrait poser des problèmes si l’on ne fait pas usage de l’option
CASCADE CONTRAINT. Cependant, l’usage de cette option entraîne également la
suppression de la CI créée par ce privilège.
Illustration: REVOKE REFERENCES ON emp FROM panky CASCADE CONSTRAINT
IX.3. Informations sur les privilèges
Quatre vues du dictionnaire de données permettent d’obtenir des informations sur les
privilèges :
Vue Contenu
DBA_SYS_PRIVS liste les privilèges système attribués aux utilisateurs et aux rôles.
SESSION_PRIVS liste les privilèges dont les utilisateurs disposent actuellement.
DBA_TAB_PRIVS liste toutes les attributions de privilèges sur tous les objets de la
base de données.
DBA_COL_PRIVS décrit toutes les attributions de privilèges sur les colonnes dans
la base de données.
48
CHAPITRE III : LE LANGAGE ORACLE PL SQL.
I. INTRODUCTION
Le PL de PL/SQL signifie Procedural Language. Le langage Oracle PL/SQL est un
langage procédural et est une extension procédurale du langage SQL. Il permet de grouper
des commandes et de les soumettre au noyau en un bloc unique de traitement. Le langage
SQL est non procédural alors que le PL/SQL est un langage procédural qui s’appuie sur toutes
les structures de programmations traditionnelles (variables, itérations, tests, séquences). Le
PL/SQL sert à programmer des procédures, des fonctions, des triggers, des packages. Le
PL/SQL s’intègre dans les outils SQL*FORMS, SQL*PLUS, PRO*C, ...il sert à programmer des
procédures, des fonctions, des triggers, et donc plus généralement, des packages.
Ecrivez-le dans un éditeur dont vous copierez le contenu dans SQL+. Un script écrit en
PL/SQL se termine obligatoirement par un /, sinon SQL+ ne l'interprète pas. S'il contient des
erreurs de compilation, il est possible d'afficher les messages d'erreur avec la commande
SQL+ : SHOW ERRORS.
Un bloc peut être imbriqué dans le code d’un autre bloc. Un sous-bloc peut aussi se
trouver dans la partie des exceptions.
DECLARE --section optionnelle
déclaration variables, constantes, types, curseurs,...
END; --obligatoire
EXCEPTION --section optionnelle
traitement des erreurs
END; --obligatoire
Dans le code PL/SQL (partie procédural) nous pouvons avoir :
• des structures conditionnelles (IF-THEN-ELSE / IF-THEN-ELSIF / CASE)
• des structures répétitives (WHILE, LOOP, FOR,...)
• des ordres LMD (SELECT, UPDATE, DELETE, INSERT,...)
• des gestions de transactions (COMMIT, SAVEPOINT, ROLLBACK,...)
• des appels de fonctions, procédures, packages,...
50
I.2.1. Conversion implicite
Le PL/SQL opère des conversions de type implicites en fonctions des opérandes en
présence. Il est nécessaire de bien connaître ces règles comme pour tous les langages.
Cependant, le typage implicite des variables (cf. paragraphe sur les variables) permet de
simplifier la déclaration des variables.
51
I.3. Gestion de l’affichage
Il est évidemment possible d’utiliser des fonctions prédéfinies d’entrée/sortie. Ces
fonctions servent essentiellement durant la phase de test des procédures PL/SQL (l’affichage
étant généralement géré du côté client). Par défaut, les fonctions d'affichage sont
désactivées. Il faut d’abord activer le package DBMS_OUTPUT par la commande SET
SERVEROUTPUT ON. Ensuite on peut utiliser la fonction PUT_LINE de ce package.
Pour afficher le contenu d'une variable, les procédures DBMS_OUTPUT.PUT() et
DBMS_OUTPUT.PUT_LINE() prennent en argument une valeur à afficher ou une variable dont
la valeur est à afficher.
affiche.sql
SET SERVEROUTPUT ON
DECLARE
message varchar2(100);
BEGIN
message := 'Essai d''affichage';
DBMS_OUTPUT.put_line ('Test : ' || message);
END;
/
Exécution
SQL> @affiche
Test : Essai d'affichage
PL/SQL procedure successfully completed.
Noter l’emploi de '' pour pouvoir afficher le caractère ', et du double pipe || pour pouvoir
concaténer plusieurs chaînes de caractères. La concaténation est souvent nécessaire car la
fonction put_line n’accepte qu’une seule chaîne de caractères en argument. Lorsque les
données affichées « défilent » trop vite on pourra utiliser deux méthodes :
• Utiliser la commande set pause on (une commande set pause off devra lui
correspondre pour revenir à la normale). Il faut alors frapper la touche RETURN pour
faire défiler les pages d’affichage.
• Utiliser la commande spool nom_fichier. Elle permet de diriger l’affichage, en plus
de la sortie standard qui est l’écran, vers un fichier nommé nom_fichier.lst. La
commande spool off est nécessaire pour arrêter la re-direction (attention aux fichiers
de spool qui grossissent inconsidérément).
52
L’utilisation de l’attribut %ROWTYPE permet à la variable d’hériter des
caractéristiques d’une ligne de table
DECLARE
V_vol vol%ROWTYPE ;
Si une variable est déclarée avec l’option CONSTANT, elle doit être initialisée. Si une
variable est déclarée avec l’option NOT NULL, elle doit être initialisée et la valeur NULL ne
pourra pas lui être affectée durant l’exécution du programme.
I.5. Les structures
Définition d’une structure art_qtecom (article et quantité commandée)
/* création du type enregistrement typ_vol*/
type typ_vol is record
( v_novol vol.no_vol%type ,
v_dest vol.destination%type
) ;
Déclaration d’une variable de type v_vol :
/* affectation du type typ_vol à v_vol*/
v_vol typ_vol;
Accès aux membres de la structure :
v_vol.v_dest := ‘Tahiti’;
Source complet
DECLARE
type typ_vol is record
( v_novol vol.no_vol%type ,
v_dest vol.destination%type
) ;
v_vol typ_vol;
BEGIN
v_vol.v_dest := ‘Tahiti’;
END;
/
53
ELSEIF salaire > 1000 AND emp_id_emp = 1 THEN
nouveau_salaire := ancien_salaire + 500;
ELSE nouveau_salaire := ancien_salaire + 300;
END IF;
Performance
CASE expression
WHEN expression1 THEN résultat1
WHEN expression2 THEN résultat2
…
est plus performant que
CASE
WHEN expression = expression1 THEN résultat1
WHEN expression = expression2 THEN résultat2
L’expression CASE ne supporte pas plus de 255 arguments, chaque clause WHEN…THEN
comptant pour 2.
-- Première syntaxe
SELECT
nom,
CASE sexe
WHEN 'M' THEN 'Monsieur'
WHEN 'F' THEN CASE mariée
WHEN 'O' THEN 'Madame'
WHEN 'N' THEN 'Mademoiselle'
END
ELSE 'Inconnu'
END CASE
FROM employe
/
--Deuxième syntaxe
SELECT
nom,
CASE sexe
WHEN sexe = 'M' THEN 'Monsieur'
WHEN sexe = 'F' AND mariée = 'O' THEN 'Madame'
WHEN sexe = 'F' AND mariée = 'N' THEN 'Mademoiselle'
ELSE 'Inconnu'
END CASE
FROM
employe
/
Il est possible d’avoir des instructions CASE imbriquées.
55
Exemple :
BEGIN
GOTO deuxiemeàffichage
Dbms_output.putline(‘Cette ligne ne sera jamais affichée’) ;
<<deuxiemeàffichage>>
dbms_output.putline(‘Cette ligne sera toujours affichée’) ;
END ;
/
Limites de l’instruction GOTO
L’instruction GOTO comporte plusieurs limites :
• L’étiquette doit être suivie d’au moins un ordre exécutable
• L’étiquette cible doit être dans la même portée que l’instruction GOTO,
chacune des structures suivantes maintien sa propre portée : fonctions,
procédures blocs anonymes, instruction IF, boucles LOOP, gestionnaire
d’exceptions, instruction CASE.
• L’étiquette cible doit être dans la même partie de bloc que le GOTO
Expression NULL
Lorsque vous voulez demander au PL/SQL de ne rien faire, l’instruction NULL devient
très pratique. Le format d’une instruction NULL est le suivant :
NULL;
Le point-virgule indique qu’il s’agit d’une commande et non pas de la valeur NULL.
--
IF :etat.selection = ‘detail’ Then
Exec_etat_detaille;
Else
NULL ; -- ne rien faire
END IF ;
II.4. Itération
On dispose de l’instruction LOOP que l’on peut faire cohabiter avec les traditionnelles
WHILE et FOR. La commande EXIT permet d’interrompre la boucle.
Exemple
OPEN curs1;
LOOP
FETCH curs1 into ancien_salaire;
EXIT WHEN curs1%NOTFOUND;
IF salaire <=1000 THEN
nouveau_salaire := ancien_salaire + 100;
ELSEIF salaire > 1000 AND emp_id_emp = 1 THEN
nouveau_salaire := ancien_salaire + 500;
ELSE nouveau_salaire := ancien_salaire + 300;
END IF;
UPDATE employe SET
salaire = nouveau_salaire
WHERE current of curs1;
END LOOP;
57
III.3. Allocation d'un tableau
La création d'un type tableau met à disposition un constructeur du même nom que le
type crée. Cette fonction réserve de l'espace mémoire pour ce tableau et retourne l'adresse
mémoire de la zone réservée, il s'agit d'une sorte de malloc. Si, par exemple, un type tableau
numtab a été crée, la fonction numtab() retourne une tableau vide.
DECLARE
TYPE numberTab IS VARRAY (10) OF NUMBER;
t numberTab ;
BEGIN
t:= numberTab() ;
/* utilisation du tableau */
END;
/
Une fois cette allocation faite, il devient presque possible d'utiliser le tableau...
III.4. Dimensionnement d'un tableau
Le tableau retourné par le constructeur est vide. Il convient ensuite de réserver de
l'espace pour stocker les éléments qu'il va contenir. On utilise pour cela la méthode EXTEND().
EXTEND s'invoque en utilisant la notation pointée. Par exemple,
DECLARE
TYPE numberTab IS VARRAY (10) OF NUMBER;
t numberTab ;
BEGIN
t:=numberTab() ;
t.EXTEND(4) ;
/* utilisation du tableau */
END;
/
III.5. Utilisation d'un tableau
On accède, en lecture et en écriture, à l’i-ème élément d’une variable tabulaire
nommé T avec l’instruction T (i).
Les éléments sont indicés à partir de 1.
Exécutons, par exemple, une permutation circulaire vers la droite des éléments du
tableau t.
DECLARE
TYPE numberTab IS VARRAY (10) OF NUMBER;
t numberTab ;
i number ;
k number ;
BEGIN
t := numberTab ( ) ;
t.EXTEND ( 1 0 ) ;
FOR i IN 1..10 LOOP
t(i):=i ;
END LOOP;
k:=t(10) ;
FOR i in REVERSE 2..10 LOOP
t(i):=t(i-1) ;
END LOOP ;
t (1):=k ;
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(t(i)) ;
END LOOP ;
END;
/
58
IV. STRUCTURES
Une structure est un type regroupant plusieurs types. Une variable de type structuré
contient plusieurs variables, ces variables s'appellent aussi des champs.
IV.1. Création d'un type structuré
On définit un type structuré de la sorte :
TYPE /* nomType */ IS RECORD
(
/* liste des champs */
) ;
nomType est le nom du type structuré construit avec la syntaxe précédente. La liste
suit la même syntaxe que la liste des colonnes d'une table dans un CREATE TABLE. Par
exemple, construisons le type point (dans IR2),
TYPE point IS RECORD
(
abscisse NUMBER,
ordonnee NUMBER
) ;
Notez bien que les types servant à définir un type structuré peuvent être quelconques
: variables scalaires, tableaux, structures, etc.
Déclaration d'une variable de type structuré point est maintenant un type, il devient
donc possible de créer des variables de type point, la règle est toujours la même pour
déclarer des variables en PL/SQL, par exemple
p point ; permet de déclarer une variable p de type point.
V. TABLES ET STRUCTURES
Si vous ne tenez pas à vous prendre la tête pour choisir le type de chaque variable,
demandez-vous ce que vous allez mettre dedans ! Si vous tenez à y mettre une valeur qui se
trouve dans une colonne d'une table, il est possible de vous référer directement au type de
cette colonne avec le type nomTable.nomColonne%type. Par exemple,
DECLARE
num PRODUIT.numprod%type ;
nom PRODUIT.nomprod%type := 'Poupée Batman' ;
BEGIN
SELECT numprod INTO num
59
FROM PRODUIT
WHERE nomprod = nom;
DBMS_OUTPUT.PUT_LINE ('L''article '||nom||' a pour numéro '||num) ;
END;
/
Pour aller plus loin, il est même possible de déclarer une structure pour représenter
une ligne d'une table, le type porte alors le nom suivant : nomTable%rowtype.
DECLARE
nom PRODUIT.nomprod%type := 'Poupée Batman ' ;
ligne PRODUIT%rowtype ;
BEGIN
SELECT INTO ligne
FROM PRODUIT
WHERE nomprod = nom ;
DBMS_OUTPUT.PUT_LINE('L''article '||ligne.nomprod||' a pour numéro '||ligne.numprod ) ;
END;
/
VI. TRANSACTIONS
Un des mécanismes les plus puissants des SGBD récents réside dans le système des
transactions. Une transaction est un ensemble d'opérations atomiques", c'est-à-dire
indivisible. Nous considérerons qu'un ensemble d'opérations est indivisible si une exécution
partielle de ces instructions poserait des problèmes d'intégrité dans la base de données.
Par exemple, dans le cas d'une base de données de gestion de comptes en banque, un
virement d'un compte à un autre se fait en deux temps : créditer un compte d'une somme s,
et débiter un autre de la même somme s. Si une erreur survient pendant la deuxième
opération, et que la transaction est interrompue, le virement est incomplet et le patron va
vous assassiner.
Il convient donc de disposer d'un mécanisme permettant de se protéger de ce genre
de désagrément. Plutôt que se casser la tête à tester les erreurs à chaque étape et à balancer
des instructions permettant de revenir en arrière", nous allons utiliser les instructions COMMIT
et ROLLBACK.
Voici le squelette d'un exemple :
/*instructions*/
IF /*erreur*/ THEN
ROLLBACK;
ELSE
COMMIT;
END;
Le ROLLBACK annule toutes les modifications faites depuis le début de la transaction
(donc depuis le précédent COMMIT), COMMIT les enregistre définitivement dans la base de
données.
La variable d'environnement AUTOCOMMIT, qui peut être positionnée à ON ou à OFF
permet d'activer la gestion des transactions. Si elle est positionnée à ON, chaque instruction
a des répercussions immédiates dans la base, sinon, les modifications ne sont effectives
qu'une fois qu'un COMMIT a été exécuté.
VII. EXCEPTIONS
Le mécanisme des exceptions est implémenté dans la plupart des langages récent,
notamment orientés objet. Cette façon de programmer a quelques avantages immédiats :
• obliger les programmeurs à traiter les erreurs : combien de fois votre prof de C a hurlé
en vous suppliant de vérifier les valeurs retournées par un malloc, ou un fopen ? La
plupart des compilateurs des langages à exceptions (notamment java) ne compilent que
si pour chaque erreur potentielle, vous avez préparé un bloc de code (éventuellement
vide...) pour la traiter. Le but est de vous assurer que vous n'avez pas oublié d'erreur.
60
• Rattraper les erreurs en cours d'exécution : Si vous programmez un systéme de sécurité
de centrale nucléaire ou un pilote automatique pour l'aviation civile, une erreur de
mémoire qui vous afficherait l'écran bleu de windows, ou le message "Envoyer le rapport
d'erreur ?", ou plus simplement le fameux "Segmentation fault" produirait un effet des
plus mauvais. Certaines erreurs d'exécution sont rattrapables, autrement dit, il est
possible de résoudre le problème sans interrompre le programme.
• Ecrire le traitement des erreurs à part : Pour des raisons fiabilité, de lisibilité, il a été
considéré que mélanger le code "normal" et le traitement des erreurs était un style de
programmation perfectible... Dans les langages à exception, les erreurs sont traitées à
part.
61
Les deux variables globales SQLCODE et SQLERRM contiennent respectivement le code
d'erreur Oracle et un message d'erreur correspondant à la dernière exception levée. Chaque
exception a donc, en plus d'un nom, un code et un message.
DECLARE
GLUBARF EXCEPTION;
BEGIN
RAISE GLUBARF;
62
EXCEPTION
WHEN GLUBARF THEN
DBMS_OUTPUT.PUT_LINE (' glubarf raised.') ;
END;
/
VIII. SOUS-PROGRAMMES
VIII.1. Procédures
VIII.1.1. Syntaxe
On définit une procédure de la sorte
CREATE OR REPLACE PROCEDURE /* nom */ (/* parametres */) IS
/* declaration des variables locales */
BEGIN
/* instructions */
END;
Les paramètres sont une simple liste de couples nom type. Par exemple, la procédure
suivante affiche un compte à rebours.
CREATE OR REPLACE PROCEDURE compteARebours (n NUMBER) IS
BEGIN
IF n >= 0 THEN
DBMS_OUTPUT.PUT_LINE (n);
compteARebours ( n-1 ) ;
END IF;
END;
VIII.1.2. Invocation
En PL/SQL, une procédure s'invoque tout simplement avec son nom. Mais sous SQL+,
on doit utiliser le mot-clé CALL. Par exemple, on invoque le compte à rebours sous SQL+ avec
la commande CALL compteARebours(20).
Passage de paramètres
Oracle permet le passage de paramètres par référence. Il existe trois types de passage
de paramètres :
• IN : passage par valeur
• OUT : aucune valeur passée, sert de valeur de retour
• IN OUT : passage de paramètre par référence
Par défaut, le passage de paramètre se fait de type IN.
CREATE OR REPLACE PROCEDURE incr (val IN OUT NUMBER) IS
BEGIN
val := val + 1 ;
END;
VIII.2. Fonctions
VIII.2.1. Syntaxe
On crée une nouvelle fonction de la fa_con suivante :
CREATE OR REPLACE FUNCTION /*nom*/ (/* parametres */) RETURN /*type*/ IS
/* declaration des variables locales */
BEGIN
/* instructions */
END;
L'instruction RETURN sert à retourner une valeur. Par exemple,
CREATE OR REPLACE FUNCTION module (a NUMBER, b NUMBER) RETURN NUMBER IS
BEGIN
IF a < b THEN
RETURN a;
ELSE
RETURN module (a - b,b) ;
63
END IF ;
END;
VIII.2.2. Invocation
Tout comme les procédures, l'invocation des fonctions ne pose aucun problème en
PL/SQL, par contre, sous SQL+, c'est quelque peu particulier. On passe par une pseudo-table
nommée DUAL de la façon suivante :
64
END LOOP ;
/*...*/
END;
Fermeture
Aprés utilisation, il convient de fermer le curseur.
CLOSE /* nomcurseur */ ;
Complétons notre exemple,
DECLARE
CURSOR emp_cur IS
SELECT * FROM EMP;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
LOOP
FETCH emp_cur INTO ligne;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (ligne.ename) ;
END LOOP;
CLOSE emp_cur;
END;
/
Le programme ci-dessus peut aussi s'écrire
DECLARE
CURSOR emp_cur IS
SELECT * FROM EMP;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
FETCH emp_cur INTO ligne;
WHILE emp_cur%FOUND LOOP
DBMS_OUTPUT.PUT_LINE (ligne.ename );
FETCH emp_cur INTO ligne;
END LOOP;
CLOSE emp_cur;
END;
Boucle FOR
Il existe une boucle FOR se chargeant de l'ouverture, de la lecture des lignes du curseur
et de sa fermeture,
FOR ligne IN emp_cur LOOP
/* Traitement */
END LOOP ;
Par exemple,
DECLARE
CURSOR emp_cur IS
SELECT * FROM EMP;
ligne emp_cur%rowtype ;
BEGIN
FOR ligne IN emp_cur LOOP
DBMS_OUTPUT.PUT_LINE ( ligne.ename ) ;
END LOOP ;
END;
/
X. CURSEURS PARAMETRES
X.1. Introduction
A votre avis, le code suivant est-il valide ?
DECLARE
65
NUMBER n := 14 ;
BEGIN
DECLARE
CURSOR C IS
SELECT * FROM PERSONNE
WHERE numpers >= n;
ROW C%rowType ;
BEGIN
FOR ROW IN C LOOP
DBMS_OUTPUT.PUT_LINE (ROW.numpers);
END LOOP;
END;
END;
/
Réponse : non. La requête d'un curseur ne peut pas contenir de variables dont les
valeurs ne sont pas fixées.
Pourquoi ? Parce que les valeurs des n sont susceptibles de changer entre la Déclaration
du curseur et son ouverture.
Le remède est un curseur paramétré.
X.2. Définition
Un curseur paramétré est un curseur dont la requête contient des variables dont les
valeurs ne seront fixées qu'à l'ouverture.
X.3. Déclaration
On précise la liste des noms et des type des paramètres entre parenthèses après le
nom du curseur :
CURSOR /* nom */ (/* liste des paramètres */) IS
/* requête */
Par exemple, créons une requête qui, pour une personne donnée, nous donne la liste
des noms et prénoms de ses enfants :
CURSOR enfants(numparent NUMBER) IS
SELECT * FROM PERSONNE WHERE pere = numparent OR mere = numparent ;
X.4. Ouverture
On ouvre un curseur paramétré en passant en paramètre les valeurs des variables :
OPEN /* nom */ (/* liste des paramètres */)
Par exemple, OPEN enfants (1) ;
67
SQL> SELECT COUNT(*)FROM CLIENT ;
COUNT(* )
---------
21
SQL> DELETE FROM CLIENT;
SQL> DELETE FROM CLIENT
*
ERREUR à la ligne 1 :
ORA-20555: Va te faire.. .
ORA-06512: à "SCOTT.PASDEDELETEDANSCLIENT" , ligne 2
ORA-04088: erreur lors de l’exécutions du déclencheur
'SCOTT.PASDEDELETEDANSCLIENT'
SQL> SELECT COUNT(*) FROM CLIENT ;
COUNT(*)
-----------------
21
L'instruction RAISE_APPLICATION_ERROR(code, message) lève une exception sans nom
portant un code code et un message d'erreur message. Vous remarquez que comme l'erreur
a été levée avant la suppression, les données sont toujours présentes dans la table CLIENT.
Le trigger a contrôlé une règle, et comme elle n'était pas respectée, il a lancé une erreur.
Combinaisons d'événements
Il est possible, en séparant les types d'événement par le mot-clé OR, de définir un
trigger déclenché par plusieurs événements. Les variables booléennes INSERTING, UPDATING
et DELETING permettent d'identifier l'événement qui a déclenché le trigger.
CREATE OR REPLACE TRIGGER afficheEvenement
BEFORE INSERT OR UPDATE OR DELETE ON CLIENT
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS_OUTPUT.PUT_LINE ('Insertion dans CLIENT');
ELSIF UPDATING THEN
DBMS_OUTPUT.PUT_LINE ('Mise à jour dans CLIENT');
ELSE
DBMS_OUTPUT.PUT_LINE ('Suppression dans CLIENT');
END IF;
END;
XI.4. Accès aux lignes en cours de modification
Dans les FOR EACH ROW triggers, il est possible avant la modification de chaque ligne,
de lire l'ancienne ligne et la nouvelle ligne par l'intermédiaire des deux variables structurées
:old et :new. Par exemple le trigger suivant empêche de diminuer un salaire :
CREATE OR REPLACE TRIGGER pasDeBaisseDeSalaire
BEFORE UPDATE ON EMP
FOR EACH ROW
BEGIN
IF (:old.sal > : new.sal) THEN
RAISE_APPLICATION_ERROR (-20567,'Pas de baisse de salaire!');
END IF;
END;
Tables en mutation
Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la
table en cours de modification.
CREATE OR REPLACE TRIGGER beforeStatement
BEFORE UPDATE ON CLIENT
DECLARE
NB NUMBER;
68
BEGIN
SELECT COUNT(*) INTO NB FROM CLIENT ;
END;
/
Déclencheur créé .
CREATE OR REPLACE TRIGGER afterStatement
AFTER UPDATE ON CLIENT
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT(*) INTO NB FROM CLIENT;
END;
/
Déclencheur créé.
SQL> UPDATE CLIENT SET nomcli=nomcli ;
21 ligne(s) mise(s) à jour.
CREATE OR REPLACE TRIGGER beforeForEachRow
BEFORE UPDATEON CLIENT
FOR EACH ROW
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT(*) INTO NB FROM CLIENT;
END;
/
Déclencheur créé.
SQL> UPDATE CLIENT SET nomcli = nomcli ;
UPDATE CLIENT SET nomcli = nomcli
--
ERREUR à la ligne 1 :
ORA-04091: la table SCOTT.CLIENT est en mutation ; le déclencheur ou la
fonction ne peut la voir
ORA-06512: à "SCOTT.BEFOREFOREACHROW», ligne 4
ORA-04088: erreur lors de l’exécution du déclencheur
'SCOTT.BEFOREFOREACHROW'
SQL> DROP TRIGGER beforeForEachRow ;
Déclencheur supprimé .
69
XI.5. Contourner le problème des tables en mutation
Il existe plusieurs façons de contourner ce problème :
• Utiliser un STATEMENT trigger. Comme on ne sait pas quelles lignes ont été modifiées,
on est obligé de toutes les traiter. Cette approche présente donc un inconvénient
majeur : elle nous amène à effectuer de nombreux traitements inutiles.
• En ayant des données redondantes. Il suffit que les données servant à la vérification se
trouvent dans une autre table que celle en mutation. Cette méthode a pour
inconvénient la mémoire occupée et la quantité de code à écrire pour maintenir la
cohérence des données. Dans la plupart des cas, cette solution est malgré tout la
meilleure.
Colonnes supplémentaires
Par exemple, si l'on souhaite empêcher un client d'avoir plus de 10 comptes en banque,
une solution est de placer dans la table client une colonne contenant le nombre de comptes.
ALTER TABLE CLIENT ADD nbComptes number ;
UPDATE CLIENT SET nbComptes = 0 ;
Une fois cette table crée, il convient de s'assurer que les données de la colonne
nbComptes contient toujours les bonnes valeurs. On le fait avec plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT
BEGIN
UPDATE CLIENT SET nbComptes =
(
SELECT COUNT(*)
FROM COMPTECLIENT CC
WHERE CC.numCli = numCli
) ;
END;
/
CREATE OR REPLACE TRIGGER verifieNbComptes
BEFORE INSERT ON COMPTECLIENT
FOR EACH ROW
DECLARE
nbComptes NUMBER;
BEGIN
SELECT nbComptes INTO nbComptes
FROM CLIENT
WHERE numCli =:new.numcli;
IF (nbComptes >= 10) THEN
RAISE_APPLICATION_ERROR (-20556,'Ce client a déjà trop de comptes') ;
END IF ;
END;
/
On peut affiner en remplaçant metAJourNbComptes par plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER initialiseNbComptes
BEFORE INSERT ON CLIENT
FOR EACH ROW
BEGIN
: new.nbComptes := 0 ;
END;
/
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes 1
70
WHERE numcli = :old.numcli ;
END IF ;
IF INSERTING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes + 1
WHERE numcli = :new.numcli ;
END IF;
END;
/
Tables supplémentaires
Si l'on souhaite par exemple empêcher les circuits dans la table PERSONNE, il est
nécessaire de faire un parcours de graphe. Ce qui nécessite des SELECT dans la table en cours
de mutation. La seule solution est dans ce cas d'avoir une table miroir qui contient les
colonnes clés primaire et étrangères de cette table, et de s'en servir pour détecter les
circuits.
CREATE TABLE MIRRORPERSONNE
(
numpers NUMBERPRIMARY KEY,
pere NUMBER,
mere NUMBER
) ;
Nous allons ensuite procéder de même, en répercutant chaque opération de PERSONNE
sur MIRRORPERSONNE.
CREATE OR REPLACE TRIGGER miseAJourMirrorPersonne
BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
DELETE FROM MIRRORPERSONNE
WHERE numpers = :old.numpers ;
END IF;
IF INSERTING OR UPDATING THEN
INSERT INTO MIRRORPERSONNE VALUES
( :new.numpers , :new.pere , :new.mere ) ;
END IF ;
END;
/
Une fois cela fait, il suffit de rechercher si une personne insérée est une descendante
d'elle même dans MIRRORPERSONNE.
CREATE OR REPLACE FUNCTION trouveCircuit (current NUMBER, toFind NUMBER)
RETURN BOOLEAN IS
numPere NUMBER;
numMere NUMBER;
BEGIN
IF (current IS NULL) THEN
RETURN FALSE;
END IF;
SELECT pere, mere INTO numPere, numMere
FROM MIRRORPERSONNE
WHERE numPers = current;
RETURN (numPere = toFind OR numMere = toFind OR
trouveCircuit ( numPere , toFind ) OR
trouveCircuit ( numMere , toFind ) ) ;
END;
/
CREATE OR REPLACE TRIGGER verifieCircuit
AFTER UPDATE OR INSERT ON PERSONNE
FOR EACH ROW
71
BEGIN
IF ( trouveCircuit ( : new.numPers , : new.numPers ) ) THEN
RAISE_APPLICATION_ERROR (-20557, 'Circuit dans l''arbre généalogique.');
END IF ;
END;
/
XII. PACKAGES
XII.1. Principe
Un package est un ensemble de sous-programmes et de variables formé par
• Une spécification : Déclaration de variables et de sous-programmes
• Un corps : implémentation des sous-programmes
Tout ce qui se trouve dans la spécification doit se trouver dans le corps, mais la
réciproque est fausse. Un package satisfait les points suivants :
• encapsulation : certains traitements sont masqués, seule la spécification du package est
visible. Cela a pour avantage de simplifier la tâche de celui qui va utiliser le package.
• modularité : il est possible de développer séparément les diverses parties de
l'application. le développement devient ainsi un assemblage de package.
Ces deux aspects fournissent une souplesse certaine au niveau du développement : il
est possible de modifier le corps d'un package sans changer sa spécification, donc sans
modifier le fonctionnement de l'application.
XII.2. Spécification
La syntaxe permettant de créer l'entête est la suivante :
CREATE OR REPLACE PACKAGE nompackage IS
/*
déclarations
*/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE compteur IS
procedure reset ;
function nextValue return number ;
END compteur ;
/
XII.3. Corps
La syntaxe permettant de créer le corps est la suivante :
CREATE OR REPLACE PACKAGE BODY nompackage IS
/*
implementation
*/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE BODY compteur IS
cpt NUMBER := 0 ;
PROCEDURE reset IS
BEGIN
cpt := 0 ;
END;
FUNCTION nextValue RETURN NUMBER IS
BEGIN
cpt := cpt + 1 ;
RETURN cpt - 1 ;
72
END;
END compteur ;
/
On peut utiliser un package depuis n'importe quel script PL/SQL :
DECLARE
nb NUMBER;
BEGIN
FOR nb IN 4..20 LOOP
DBMS_OUTPUT.PUT_LINE (COMPTEUR.nextValue()) ;
END LOOP;
COMPTEUR.RESET();
FOR nb IN REVERSE 0..10 LOOP
DBMS_OUTPUT.PUT_LINE (COMPTEUR.nextValue()) ;
END LOOP ;
END;
/
73