Cours BD Avancees
Cours BD Avancees
Cours BD Avancees
Introduction Générale.................................................................................................................................2
I. Introduction.........................................................................................................................................2
V. Modèles de SGBD..............................................................................................................................5
I. Objectifs du chapitre...........................................................................................................................6
2. Processus Oracle.............................................................................................................................7
I. Introduction :.....................................................................................................................................16
2. Expressions numériques :..............................................................................................................17
IV. Jointures :......................................................................................................................................18
1. Sous-requêtes simples :.................................................................................................................19
2. Sous-requêtes synchronisées :.......................................................................................................19
VII. Regroupement :.............................................................................................................................21
VIII. DISTINCT :..................................................................................................................................22
X. Fonctions individuelles :...................................................................................................................22
1. Expression CASE :........................................................................................................................26
2. Expression DECODE :..................................................................................................................26
1. Définition :....................................................................................................................................29
V. Synonyme.........................................................................................................................................32
I. Introduction.......................................................................................................................................33
1. Notion de bloc...............................................................................................................................33
2. Structures de contrôle....................................................................................................................33
3. Les boucles....................................................................................................................................34
1. Les curseurs...................................................................................................................................36
3. Curseur implicite...........................................................................................................................38
1. Procédures et fonctions.................................................................................................................41
2. Les paramètres..............................................................................................................................41
3. Les paquetages..............................................................................................................................42
2. Entête du trigger............................................................................................................................44
5. Clause When.................................................................................................................................45
7. Corps du trigger.............................................................................................................................46
Bibliographie..............................................................................................................................................48
1. Indépendance physique : Plus besoin de travailler directement sur les fichiers physiques (tels
qu’ils sont enregistrés sur disque).Un SGBD nous permet de décrire les données et les liens entre
elles d’une façon logique sans se soucier du comment cela va se faire physiquement dans les
fichiers. On parle alors d’image logique de la base de données, (ou aussi description logique ou
conceptuelle ou encore de schéma logique).Ce schéma est décrit dans un modèle de données par
exemple le modèle de tables, appelé le modèle relationnel. La manipulation des données doit être
facilitée en travaillant directement sur le schéma logique. On peut insérer, supprimer, modifier des
données directement sur l’image logique. Le SGBD va s’occuper de faire le travail sur les fichiers
physiques.
Formule logique (E.g. Nom character 20, non-NULL; age integer between 0 and 120; debit <= credit).
But: protéger les données
V. Modèles de SGBD
SGBD Hiérarchique: Les données sont représentées dans la base sous forme de structure arborescente.
Manipulation des données (balayage ascendant/descendant).
SGBD réseau: Les données sont représentées dans la base sous forme d’un graphe quelconque. Les
programmes ne sont pas indépendants de la structure logique de la base, doivent indiquer le chemin
d’accès aux données et utilisent un langage complexe pour travailler avec leurs données.
SGBD relationnel: fondé sur la théorie mathématique des relations; représentation très simple des
données (tables); langage non procédural (déclaratif), puissant et simple d’emploi SQL est un standard
parmi ces langages dominent le marché: Exemples : Oracle, DB2, SQLServer, Access, DBase, Paradox,
… etc.
I. Objectifs du chapitre
À la fin de ce chapitre, vous pourrez:
2. Processus Oracle
System Monitor (SMON) : effectue une récupération après panne lorsque l'instance est démarrée après
une défaillance.
Process Monitor (PMON) : effectue un nettoyage de processus lorsqu'un processus utilisateur échoue.
L’exemple illustre une configuration Oracle dans laquelle l'utilisateur et les processus serveur associés
utilisent des ordinateurs distincts (connectés entre eux via un réseau).
1 Une instance a été démarrée sur l'ordinateur exécutant Oracle (souvent appelé hôte ou serveur de base
de données).
2 L'ordinateur exécutant l'application (ordinateur local ou poste client) utilise un processus utilisateur.
L'application client tente d'établir une connexion avec l'instance en utilisant le pilote Oracle Net Services.
3 L'instance détecte la demande de connexion émanant de l'application et se connecte à un processus
serveur pour le compte du processus utilisateur.
Il est possible de démarrer les bases de données avec les commandes suivantes:
Normal
Transactionnel
Immediate
Abort
Lorsque le DBA a créé un utilisateur, il lui donne des privilèges. Exemple : Le DBA donne à l’utilisateur
la possibilité de se connecter à la base de données. Ce privilège est donné grâce à CREATE SESSION
Exemple :
Un rôle est un ensemble de privilèges. Lorsque le rôle est créé, le DBA utilise la requête GRANT pour
assigner ce rôle aux utilisateurs.
Exemple :
Le privilège accordé avec la clause WITH GRANT OPTION donne la possibilité au nouvel utilisateur
d’accorder les privilèges sur cet objet aux autres utilisateurs Si vous enlevez ensuite le privilège à cet
utilisateur, tous les utilisateurs à qui il aura donné ce privilège se le verront enlevé aussi de manière
automatique
Exemples :
I. Introduction :
SQL (Structured Query Language) ou langage de requêtes structuré est un langage destiné à interroger et
manipuler les SGBDR. Il a été introduit par IBM en 1979. Le langage SQL est devenu Standard ANSI en
86 et ISO en 87. Plusieurs révisions: SQL1 en 1989, SQL2 en 1992 en , SQL3 en 1999 et SQL2003.
Le langage SQL comporte:
LDD : Langage de Définition de Données (définir les tables, les vues, ..)
LMD : Langage de Manipulation de Données (MAJ, Requêtes, ..)
SELECT *
FROM T_Customer;
FROM T_Customer;
Opérations : addition (+), soustraction (-), multiplication (*), division (/) et modulo (%)
Exemple:
FROM T_Raws_Materials;
Exemple :
FROM T_Customer
ORDER BY city;
IV. Jointures :
Une jointure permet d'exprimer des requêtes portant sur des données réparties sur plusieurs tables
where Inscrit.NumeroP =
NomC='Colloque1';
Exemple:
Select NomP, PrenomP On peut faire intervenir plus que deux tables
I.NomC = C.NomC;
.
Jointure sur la même table
V. Les sous-requêtes :
SQL permet d'utiliser des requêtes pour élaborer des conditions plus complexes et "dynamiques", c'est à
dire qu'un critère de recherche employé dans la clause WHERE soit lui-même le résultat d'un SELECT. Il
exist deux types de sous requête : Sous- requêtes simples et Sous- requêtes synchronisées.
1. Sous-requêtes simples :
Dans ce cas la sous-requête est d'abord évaluée, puis le résultat est utilisé pour exécuter la requête
principale.
Exemple : sélectionner la liste des employés ayant même poste que JONES
2. Sous-requêtes synchronisées :
Dans ce cas la sous-requête est évaluée pour chaque n-uplet de la requête principale
Exemple : sélectionner des employés ne travaillant pas dans le même département que leur manager.
Exercice : Liste des employés travaillant dans un département qui contient au moins un ANALYSTE ?
Les opérateurs ensemblistes : Dans les exemples précédent, le SELECT de la sous-requête ramenait un
seul n-uplet, car à droite du signe "=" se trouvait une seule valeur. Cependant une sous-requête peut
ramener plusieurs n-uplets (une liste de valeur).Les opérateurs permettant de comparer une valeur à un
ensemble de valeurs sont les opérateurs obtenus en ajoutant ANY et ALL à la suite d'un opérateur de
comparaison
ANY : la comparaison sera vraie si elle est vraie pour au moins un élément de l'ensemble.
ALL : la comparaison sera vraie si elle est vraie pour tous les éléments de l'ensemble.
Exercice : sélectionner les employés gagnant plus que tous les employés du département 30
Remarque L'opérateur IN est équivalent à l'opérateur = ANY. L'opérateur NOT IN est équivalent à
l'opérateur != ALL
Les sous-requêtes ramenant plusieurs colonnes : II est possible de comparer le résultat d'un SELECT
ramenant plusieurs colonnes à une liste de colonnes. La liste de colonnes figurera entre parenthèse à
gauche de l'opérateur de comparaison.
Syntaxe:
Exercice : sélectionner la liste des employés ayant même job et même salaire que FORD
avg (col) : moyenne des valeurs (les valeurs NULL sont ignorées)
count (col) : nombre de n-uplet satisfaisant à la condition WHERE. Les valeurs NULL sont ignorées.
Exemples :
VII. Regroupement :
1. Calcul sur plusieurs groupes :
II est possible de subdiviser la table en groupes, chaque groupe étant l'ensemble des lignes ayant une
valeur commune.
VIII. DISTINCT :
Le mot-clé distinct permet de supprimer les lignes identiques du résultat
Le prédicat figurant dans la clause HAVING ne peut porter que sur des caractéristiques des fonctions de
groupe figurant dans la clause GROUP BY.
Exemples :
Fonction : Substituer les valeurs nulles d’une colonne par une valeur choisie
Exemple:
Syntaxe : NVL2(expr1,expr2,expr3)
Fonction : Afficher expr2 si expr1 est non nulle, sinon afficher expr3
Exemple:
Exemple:
Exemple :
2. Expression DECODE :
Syntaxe :
Exemple :
Exemples:
Insertion d’un tuple INSERT INTO nom_table INSERT INTO Client values (1,’ ali’,
( liste_attribut) VALUES ‘13-09-80’,500,2);
(liste_valeurs)
Mise à jour d’un tuple UPDATE nom_table SET UPDATE Client SET Nom=’med’
attribut=valeur [WHERE condition]; where NumCli = 1 ;
Syntaxe :
La spécification des noms de colonnes de la vue est facultative. Par défaut, les colonnes de la vue ont
pour nom les noms des colonnes résultat de SELECT.
Requêtes et vues : Pour récupérer les données de vues, on procédera comme si l'on était en face d'une
table classique. Select * from EMPLOYES2 …
En réalité, cette table est virtuelle et est reconstruite à chaque appel de la vue EMPLOYES par exécution
du SELECT constituant la définition de la vue.
Noter que la séquence est stockée et générée indépendamment de la table, et une séquence peut être
utilisée pour plusieurs tables.
Exemples :
Syntaxe :
Exemple :
Syntaxe :
Exemple :
et les Triggers
I. Introduction
PL/SQL signifie procedural language with SQL. C'est un langage de programmation propriétaire (Oracle)
inspiré d’ADA. Ce langage a fortement inspiré la norme SQL3 car il est bien-sûr bien adapté à la
manipulation d'une base de donnée relationnelle : il utilise les même types que SQL, permet d'intégrer
facilement des requêtes dans le code, de définir des curseurs pour parcourir séquentiellement le résultat
d'une requête ...
Côté Serveur : Définir des objets "programmes" persistants comme les modules stockés
(packages, procédures et fonctions) ou les triggers
Côté Client : en SQLPlus, permet d'écrire des blocs anonymes. C'est aussi le langage de l'outils de
développement d'interface graphique Developer
Comme en ADA, on définit la notion de bloc, qui contient une partie déclarative puis un corps qui
contient éventuellement un traitement d'exception :
[declare
...]
begin
...
[exception
...]
end ;
2. Structures de contrôle
3. Les boucles
for i in [reverse] deb .. fin loop
instr
end loop;
while condition loop
instr
end loop;
loop
instr
exit when condition;
instr
end loop;
Les variables peuvent être : D’un type de base SQL (CHAR, DATE, ...) ou PL/SQL (BOOLEAN, sous-
type d'un type de base,...) Ou d'un type composé. La syntaxe d'une déclaration de variable est :
Quelques exemples :
num NUMBER(4) ;
num2 NUMBER NOT NULL := 3.5 ;
en_stock BOOLEAN := false ;
limite CONSTANT REAL := 5000.00 ; -- une constante, donc forcément initialisée
La contrainte NOT NULL doit être suivie d'une clause d'initialisation.Les déclarations multiples ne sont
pas permises (hélas !). On ne peut donc pas écrire : v1 , v2 NUMBER ;
Un type composé est : un type "record". Quand tous les attributs sont d'un type SQL, une variable de type
record peut représenter une ligne d'une table relationnelle. un type collection : TABLE, VARRAY
utilisés en relationnel objet. Un type objet : modèle relationnel objet. Voici un exemple de déclaration
d'un type record :
Une variable de ce type possède des champs p.nom, p.prenom, et on la déclare de la façon suivante :
p PERSONNE_REC ;
v1 Employee.emp_name%type ;
-- v1 du même type que la colonne emp_name
-- de la table Employee
v2 v1%type ;
-- v2 du même type que v1
num NUMBER(5) ;
numbis num%type ;
-- numbis du même type que num
emp_rec Employee%rowtype ;
-- emp_rec est de type record
-- ses attributs suivent le schéma de Employee
Les instructions INSERT, DELETE, UPDATE s'écrivent telles quelles dans un programme. Elles peuvent
utiliser les variables du programme : il faut donc donner des noms différents aux variables du programme
et aux colonnes des tables manipulées par le programme. Pour une requête dont le résultat est constitué
d'une unique ligne, on peut utiliser la syntaxe SELECT ... INTO....
Pour une requête qui ramène un nombre quelconque de lignes, il faut utiliser un curseur.
create or replace
procedure ajouterEmp(leNom employee.emp_name%type,
lePrenom employee.emp_firstname%type) is
nouveauNum NUMBER ;
begin
select nvl(max(emp_no),0)+1 into nouveauNum
from employee ;
Syntaxiquement, c'est une requête SQL qui peut utiliser des variables du programme, la clause into
permet de préciser les noms des variables qui vont recevoir le résultat de la requête. (cf exemple
précédent). La requête ne doit donc renvoyer qu'une seule ligne.
select *
into emp_rec -- emp_rec de type Employee%rowtype
from Employee
where emp_no = 346;
1. Les curseurs
Un curseur est une structure de donnée séquentielle avec une position courante. On utilise un curseur pour
parcourir le résultat d'une requête SQL dans un programme PL/SQL. On déclare un curseur en associant
un nom à une requête.
Si c’est un curseur, la ligne courante est de type c%rowtype, c'est à dire du type de la ligne de la requête
associée à c.
Instructions :
OPEN : initialise le curseur
FETCH : extrait la ligne courante et passe à la suivante (pas d'exception si plus de ligne)
CLOSE : invalide le curseur
Si on veut parcourir toutes les lignes : boucle FOR
declare
cursor c_proj is
select proj_name, proj_budget
from project
order by proj_budget ;
proj_rec c_proj%rowtype ;
begin
open c_proj ;
loop -- parcours des lignes du curseur
fetch c_proj into proj_rec ;
exit when c_proj%notfound ;
... on utilise la ligne courante rangée dans proj_rec ...
end loop ;
close c_proj ;
end ;
declare
cursor c_proj is
select proj_name, proj_budget
from project
order by proj_budget ;
begin
for proj_rec in c_proj loop -- parcours des lignes du curseur
... on utilise la ligne courante rangée dans proj_rec ...
end loop ;
end ;
open emp_cursor(56) ;
fetch emp_cursor into emp_cursor_rec ;
...
close emp_cursor ;
ou bien
pour les instructions du DML qui modifient la base (INSERT, DELETE, UPDATE)
pour les requêtes de la forme SELECT INTO.
Avec un curseur implicite, on peut obtenir des informations sur la requête réalisée, grâce aux attributs. En
effet SQL%attribut applique l'attribut sur la dernière requête SQL exécutée
Attention, lorsqu'une requête de la forme select ... into ... a déclenché une exception
(NO_DATA_FOUND ou TOO_MANY_ROWS) il ne faut pas se fier aux valeurs retournées par les
attributs.
En PL/SQL, la gestion des erreurs se fait grâce aux exceptions. Le mécanisme de déclenchement /
traitement d'exception est identique à celui du langage ADA, je ne m'étendrai donc pas sur le sujet.
Il existe un certain nombre d'exceptions prédéfinies mais le programmeur peut bien-sûr définir ses
propres exceptions.
BEGIN
...corps du bloc...
EXCEPTION
when exception1 [or exception2 ...] then
instructions ;
when exception3 [or exception4 ...] then
instructions ;
...
[when others then instructions ;]
END;
DECLARE
pe_ratio NUMBER(3,1);
BEGIN
SELECT price / earnings INTO pe_ratio
FROM stocks
WHERE symbol = 'XYZ';
-- might cause division-by-zero error
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', pe_ratio);
EXCEPTION -- exception handlers begin
WHEN ZERO_DIVIDE THEN
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', NULL);
END;
TOO_MANY_ROWS : instruction select ... into qui ramène plus d'une ligne.
nomException EXCEPTION ;
Les exceptions prédéfinies sont associées à des codes d'erreur Oracle. Lorsqu'une exception n'est pas
traitée dans le programme PL/SQL, le client qui a appelé ce programme reçoit le code d'erreur associé.
Malheureusement, tous les codes d'erreur Oracle ne sont pas associés à un nom d'exception. Pour traiter
une erreur non liée à une exception, on peut utiliser la clause When others mais ce n'est pas très précis ;
on ne sait pas exactement quelle erreur on traite. Une autre solution consiste à lier un nom d'exception à
un code d'erreur. Ceci est réalisé par la directive PRAGMA EXCEPTION_INIT(nomException,
codeErreur). Lier une exception à un code d'erreur peut aussi être utilisé pour définir des nouveaux codes
d'erreur à partir de nouvelles exceptions (i.e. non prédéfinies).
On suppose qu'il existe une table COMPAGNIE et une table PILOTE avec une contrainte de clef
étrangère entre les deux (un pilote appartient à une compagnie). Lorsqu'on veut supprimer une compagnie
qui a encore des pilotes, on reçoit l'erreur : ORA-02292 enregistrement fils existant.
Dans ce programme, si aucune ligne de COMPAGNIE n'est effacée, ceci n'entraîne pas d'erreur. La
version suivante permet de déclencher une exception si la compagnie passée en paramètre n'existe pas :
Pour terminer, il est aussi possible de déclencher une erreur, sans la lier à une exception. Pour cela, on
utilise l'instruction raise_application_error(codeErreur,messageErreur); où le code d'erreur est un entier
négatif compris entre -20999 et-20000 (codes réservés aux erreurs non prédéfinies) le message erreur est
celui communiqué au client (par exemple, affiché sous SQLPlus).
Un module stocké est un programme rangé dans la base de données. On peut ainsi définir en PL/SQL des
procédures, fonctions ou même des paquetages. Ces programmes peuvent être appelés par les
programmes clients, et sont exécutés par le serveur. Cette notion de module stocké fait partie de la norme
SQL3. Le langage utilisé dans la norme est très proche de PL/SQL.
1. Procédures et fonctions
2. Les paramètres
Et voici une procédure qui prend en entrée un numéro de département et donne en sortie le nom de ce
département (paramètre OUT au lieu de résultat de fonction)
3. Les paquetages
Un paquetage permet de regrouper ensemble des procédures, exceptions, constantes...Un paquetage est
composé d'une spécification et d'un corps. La spécification du paquetage contient des éléments que l'on
rend accessibles à tous les utilisateurs du paquetage. Le corps du paquetage contient l'implémentation et
ce que l'on veut cacher.
Au niveau des droits, on donne le droit d'exécuter un paquetage : on a alors accès à toute la spécification,
pas au corps. Il faut mettre le minimum de choses dans la spécification (penser à l'encapsulation)
La surcharge est autorisée, on peut avoir plusieurs procédures ou fonctions de même nom, avec des
signatures différentes.
Chaque session qui utilise le paquetage possède une instance du paquetage (il n'y a donc pas partage des
variables)
Spécification
Elle contient : des signatures de procédures et fonctions, des constantes et des variables des définitions
d'exceptions des définitions de curseurs
Il contient: Les corps des procédures et fonctions de la spécifications (obligatoire) D'autres procédures et
fonctions (cachées) Des déclarations que l'on veut rendre privées Un bloc d'initialisation du paquetage si
nécessaire. Voici un exemple (stupide) de paquetage :
-- spécification
create or replace package mon_paq as
procedure p ;
procedure p(i NUMBER) ;
function p(i NUMBER) return NUMBER ;
cpt NUMBER ;
function get_cpt return NUMBER ;
mon_exception EXCEPTION ;
PRAGMA EXCEPTION_INIT(mon_exception, -20101);
end ;
-- corps
create or replace package body mon_paq as
procedure p is
begin
dbms_output.put_line('toto');
end ;
procedure p(i NUMBER) is
begin
dbms_output.put_line(i);
end ;
function p(i NUMBER) return NUMBER is
begin
if (i > 10) then raise mon_exception ; end if ;
return i ;
end ;
function get_cpt return NUMBER is
begin return cpt ; end ;
end ;
begin
mon_paq.cpt := 20 ;
end ;
-- autre utilisateur :
select usertp.mon_paq.get_cpt from dual ;
GET_CPT
----------------------------
null
Un trigger (déclencheur) est un programme qui se déclenche automatiquement suite à un événement. C'est
donc un programme qui fait partie du schéma (comme les modules stockés) mais que l'on n'appelle pas
explicitement, à la différence d'une procédure stockée. Ils existent dans la plupart des SGBD et sont la
traduction d'une vision active de la base de données.
Les triggers que nous étudierons dans ce cours sont déclenchés par des instructions DML qui modifient
l'instance d'une table: INSERT, DELETE ou UPDATE. (il existe sous Oracle d'autres types de triggers)
Ces triggers existent dans la norme SQL3, sous une syntaxe très proche de celle d'Oracle (bien que
légèrement différente, comme d'habitude ...). Le mécanisme général ainsi que les différentes variantes de
triggers sont similaires en SQL3 et sous Oracle.
Les triggers peuvent servir à vérifier des contraintes que l'on ne peut pas définir de façon déclarative,
gérer de la redondance d'information, après une dénormalisation du schéma et collecter des informations
sur les mises à jour de la base.
2. Entête du trigger
On définit :
Si le trigger doit déterminer si l'instruction DML est autorisée, utiliser BEFORE. Si le trigger doit
"fabriquer" la valeur d'une colonne pour pouvoir ensuite la mettre dans la table : utiliser BEFORE. Si on a
besoin que l'instruction DML soit terminée pour exécuter le corps du trigger : utiliser AFTER
Un trigger instruction se déclenche une fois, suite à une instruction DML. Un trigger ligne (FOR EACH
ROW) se déclenche pour chaque ligne modifiée par l'instruction DML.
Par exemple, si une instruction update sur une table T modifie 5 lignes, un trigger instruction lié à cet
événement se déclenchera une seule fois (avant ou après la modification en fonction de after/before) et un
trigger ligne se déclenchera 5 fois, une fois par ligne modifiée (avant ou après la modification en fonction
de after/before).
Dans un trigger ligne, on peut faire référence à la ligne courante, celle pour laquelle le trigger s'exécute.
Pour cette ligne, on a accès à la valeur avant l'instruction DML (nommée :old) et à la valeur après
l'instruction (nommée :new).
:old :new
5. Clause When
On peut définir une condition pour un trigger ligne : le trigger se déclenchera pour chaque ligne vérifiant
la condition. Le trigger suivant insère une ligne dans une table de log, lorsque le salaire d'un employé
diminue.
Pour une instruction du DML sur une table de la base, il peut y avoir quatre familles de triggers possibles
selon l'instant (before, after) et le type (instruction ou ligne). Ces triggers se déclenchent dans l'ordre
suivant :
Dans une même famille, on ne contrôle pas l'ordre d'exécution des triggers : par exemple, s'il y a plusieurs
triggers instructions after pour l'instruction update sur une table T, on ne sait pas dans quel ordre ils vont
s'exécuter.
7. Corps du trigger
Le corps du trigger est écrit en PL/SQL. Par rapport à une procédure stockée, on peut utiliser des
prédicats qui permettent de savoir quel événement a déclenché le trigger : prédicat INSERTING (resp.
UPDATING, DELETING) qui vaut vrai ssi le trigger a été déclenché par un INSERT (resp UPDATE,
DELETE). Nous avons vu précédemment que dans le corps d'un trigger ligne, on peut faire référence aux
valeurs de la ligne courante (avant et après modif) par :old et :new.
Il ne faut pas, dans un trigger ligne, interroger une table qui est en cours de modification (pb mutating
table). En effet, l'état de la table est instable puisque l'instruction SQL est en cours d'exécution.
On peut aussi imaginer de calculer la clef en fonction des valeurs déjà présentes (sans utiliser de
séquence). C'est ce que propose le trigger suivant.