SQL Cours
SQL Cours
SQL Cours
Langage SQL
1.5.1 Identicateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5.2 Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.5.3 Colonnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.6 Types de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
version 2.1 1.6.1 Types numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.6.2 Types chaîne de caractères . . . . . . . . . . . . . . . . . . . . . . . 5
1.6.3 Types temporels . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Richard Grin 1.6.4 Types binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.6.5 Valeur NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.7 Création d'une table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1er mars 1999 1.8 Contrainte d'intégrité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.8.1 Types de contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.8.2 Exemples de contraintes . . . . . . . . . . . . . . . . . . . . . . . . 8
1.9 Sélection simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.10 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2 Langage de manipulation des données 12
2.1 Insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Modication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 Transactions : Commit/Rollback . . . . . . . . . . . . . . . . . . . . . . . . 14
3 Interrogations 16
3.1 Syntaxe générale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2 Clause SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
TABLE DES MATIÈRES iii iv TABLE DES MATIÈRES
3.3 Clause FROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.4.3 DROP INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.4 Clause WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.5 Privilèges d'accès à la base . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.4.1 Clause WHERE simple . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.5.1 GRANT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.4.2 Opérateurs logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.5.2 REVOKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.5 Jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.5.3 Changement de mot de passe . . . . . . . . . . . . . . . . . . . . . 43
3.5.1 Jointure d'une table à elle-même . . . . . . . . . . . . . . . . . . . 21 4.6 Procédure stockée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.5.2 Jointure externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.7 Trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.6 Sous-interrogation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.8 Dictionnaire de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.6.1 Sous-interrogation à une ligne et une colonne . . . . . . . . . . . . . 22
3.6.2 Sous-interrogation ramenant plusieurs lignes . . . . . . . . . . . . . 23 5 Gestion des accès concurrents 46
3.6.3 Sous-interrogation synchronisée . . . . . . . . . . . . . . . . . . . . 24 5.1 Niveaux d'isolation des transactions . . . . . . . . . . . . . . . . . . . . . 46
3.6.4 Sous-interrogation ramenant plusieurs colonnes . . . . . . . . . . . 25 5.2 Traitement par défaut des accès concurrents par Oracle . . . . . . . . . . . 46
3.6.5 Clause EXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.3 Autres possibilités de blocages . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.7 Fonctions de groupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.4 Verrouillage d'une table en mode exclusif (Exclusive) . . . . . . . . . . . . 48
3.8 Clause GROUP BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.9 Clause HAVING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 5.5 Verrouillage d'une table en mode Share Row Exclusive . . . . . . . . . . . 48
3.10 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 5.6 Verrouillage d'une table en mode partagé (Share) . . . . . . . . . . . . . . 48
3.10.1 Fonctions arithmétiques . . . . . . . . . . . . . . . . . . . . . . . . 30 5.7 Verrouillage de lignes pour les modier (mode Row Exclusive) . . . . . . . 49
3.10.2 Fonctions chaînes de caractères . . . . . . . . . . . . . . . . . . . . 30 5.8 Verrouillage de lignes en mode Row Share . . . . . . . . . . . . . . . . . . 49
3.10.3 Fonctions de travail avec les dates . . . . . . . . . . . . . . . . . . . 33 5.9 Lecture consistante pendant une transaction . . . . . . . . . . . . . . . . . 50
3.10.4 Nom de l'utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.10 Tableau récapitulatif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.11 Clause ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.12 Opérateurs booléens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 6 Java et JDBC 51
3.12.1 Opérateur UNION . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 6.1 Drivers et gestionnaire de drivers . . . . . . . . . . . . . . . . . . . . . . . 51
3.12.2 Opérateur INTERSECT . . . . . . . . . . . . . . . . . . . . . . . . 35 6.1.1 Types de drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.12.3 Opérateur MINUS . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 6.1.2 Types de drivers et applet untrusted . . . . . . . . . . . . . . . . . 52
6.2 Modèles de connexion à une base de données . . . . . . . . . . . . . . . . . 53
4 Langage de dénition des données 36 6.3 Utilisation pratique de JDBC . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.1 Schéma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 6.4 Étapes du travail avec une base de données avec JDBC . . . . . . . . . . . 55
4.2 Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 6.5 Classes et interfaces de JDBC . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.2.1 CREATE TABLE AS . . . . . . . . . . . . . . . . . . . . . . . . . 36 6.6 Connexion à une base de données . . . . . . . . . . . . . . . . . . . . . . . 56
4.2.2 ALTER TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 6.7 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.2.3 Ajout d'une colonne - ADD . . . . . . . . . . . . . . . . . . . . . . 37 6.8 Instruction SQL simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.2.4 Modication d'une colonne - MODIFY . . . . . . . . . . . . . . . . 37 6.8.1 Consultation des données (SELECT) . . . . . . . . . . . . . . . . . 57
4.2.5 DROP TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.3 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.8.2 Modication des données (INSERT, UPDATE, DELETE) . . . . . 60
4.3.1 CREATE VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.8.3 Ordre SQL quelconque . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.3.2 DROP VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.9 Instruction SQL paramétrée . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.3.3 Utilisation des vues . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 6.10 Procédure stockée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.3.4 Utilité des vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 6.11 Syntaxe spéciale SQL ( SQL Escape Syntax ) . . . . . . . . . . . . . . . . 65
4.4 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 6.12 Les Meta données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.4.1 CREATE INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 6.12.1 ResultSetMetaData . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.4.2 Utilisation des index . . . . . . . . . . . . . . . . . . . . . . . . . . 41 6.12.2 DatabaseMetaData . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
TABLE DES MATIÈRES v vi PRÉSENTATION DU POLYCOPIÉ
7 Langage C et Pro*C d'Oracle 67
7.1 Variables hôtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.2 Zone SQLCA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
7.3 Curseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
7.4 Pré-compilation, compilation et exécution de programmes écrits avec PRO*C 69
7.5 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Présentation du polycopié
Ce polycopié présente le langage SQL. Il ne suppose que quelques connaissances de base
exposées dans le polycopié d'introduction aux bases de données.
Les exemples s'appuient sur la version du langage SQL implantée dans le SGBD Oracle,
version 7.
Les remarques et les corrections d'erreurs peuvent être envoyées par courrier électro-
nique à l'adresse grin@unice.fr, en précisant le sujet Poly SQL.
1 2 CHAPITRE 1. INTRODUCTION
Entry Level (ensemble minimum à respecter pour se dire à la norme SQL-2)
SQL-3 est en cours d'homologation.
Types chaîne de caractères de SQL-2 Une constante de type date est une chaîne de caractères entre apostrophes. Le format
dépend des options que l'administrateur a choisies au moment de la création de la base.
Les constantes chaînes de caractères sont entourées par des apostrophes ('). Si la chaîne S'il a choisi de franciser la base, le format d'une date est jour/mois/année, par exemple,
contient une apostrophe, celle-ci doit être doublée. Exemple : 'aujourd''hui'. '25/11/92' (le format américain par défaut donnerait '25-NOV-92'). L'utilisateur peut
Il existe deux types pour les colonnes qui contiennent des chaînes de caractères : saisir des dates telles que '3/8/93' mais les dates enregistrées dans la base ont toujours
deux chires pour chacun des nombres, par exemple, '03/08/93'.
le type CHAR pour les colonnes qui contiennent des chaînes de longueur constantes Dans Oracle une donnée de type DATE inclut un temps en heures, minutes et secondes.
ne contenant pas plus de 255 caractères (255 pour Oracle, cette longueur maximum
varie suivant les SGBD).
La déclaration de type chaîne de caractères de longueur constante a le format suivant : 1.6.4 Types binaires
CHAR(longueur ) Ce type permet d'enregistrer des données telles que les images et les sons, de très grande
où longueur est la longueur maximale (en nombre de caractères) qu'il sera possible taille et avec divers formats.
de stocker dans le champ. longueur doit être obligatoirement spéciée. L'insertion SQL-2 n'a pas normalisé ce type de données. Les diérents SGBD fournissent un type
d'une chaîne dont la longueur est supérieure à longueur sera refusée. Une chaîne plus pour ces données mais les noms varient : LONG RAW pour Oracle, mais IMAGE pour Sybase,
courte que longueur sera complétée par des espaces (important pour les comparaisons BYTE pour Informix, etc.
de chaînes). Nous n'utiliserons pas ce type de données dans ce cours.
le type VARCHAR pour les colonnes qui contiennent des chaînes de longueurs variables.
Tous les SGBD ont une longueur maximum pour ces chaînes (plusieurs milliers de 1.6.5 Valeur NULL
caractères).
On déclare ces colonnes par : Une colonne qui n'est pas renseignée, et donc vide, est dite contenir la valeur NULL.
VARCHAR(longueur ) Cette valeur n'est pas zéro, c'est une absence de valeur.
longueur indique la longueur maximale des chaînes contenues dans la colonne
1.7 Création d'une table
Types chaîne de caractères d'Oracle
L'ordre CREATE TABLE permet de créer une table en dénissant le nom et le type
Les types Oracle sont les types SQL-2 mais le type VARCHAR s'appelle VARCHAR2 dans (voir 1.6) de chacune des colonnes de la table. Nous ne verrons ici que trois des types de
Oracle (la taille maximum est de 2000 caractères). données utilisés dans SQL : numérique, chaîne de caractères et date. Nous nous limiterons
1.8. CONTRAINTE D'INTÉGRITÉ 7 8 CHAPITRE 1. INTRODUCTION
dans cette section à une syntaxe simpliée de cet ordre (voir 4.2.1 et 1.8 pour des complé- qui composent cette clé ne doit avoir une valeur NULL.
ments) :
CREATE TABLE table (pour une contrainte sur une table :)
(colonne1 type1, UNIQUE (colonne1, colonne2,...)
colonne2 type2, (pour une contrainte sur une colonne :)
......... UNIQUE
.........) interdit qu'une colonne (ou la concaténation de plusieurs colonnes) contienne deux valeurs
table est le nom que l'on donne à la table ; colonne1, colonne2,.. sont les noms des identiques.
colonnes ; type1, type2,.. sont les types des données qui seront contenues dans les colonnes. (pour une contrainte sur une table :)
On peut ajouter après la description d'une colonne l'option NOT NULL qui interdira FOREIGN KEY (colonne1, colonne2,...)
que cette colonne contienne la valeur NULL. On peut aussi ajouter des contraintes d'inté- REFERENCES tableref [(col1, col2,...)]
grité portant sur une ou plusieurs colonnes de la table (voir 1.8). [ON DELETE CASCADE]
(pour une contrainte sur une colonne :)
Exemple 1.3 REFERENCES tableref [(col1 )]
CREATE TABLE article [ON DELETE CASCADE]
( ref CHAR (10) NOT NULL,
indique que la concaténation de colonne1, colonne2,... (ou la colonne que l'on dénit pour
prix NUMBER (9,2),
une contrainte sur une colonne) est une clé étrangère qui fait référence à la concaténation
datemaj DATE)
des colonnes col1, col2,... de la table tableref (contrainte d'intégrité référentielle). Si aucune
colonne de tableref n'est indiquée, c'est la clé primaire de tableref qui est prise par défaut.
1.8 Contrainte d'intégrité Cette contrainte ne permettra pas d'insérer une ligne de la table si la table tableref
ne contient aucune ligne dont la concaténation des valeurs de col1, col2,... est égale à la
Dans la dénition d'une table, on peut indiquer des contraintes d'intégrité portant sur concaténation des valeurs de colonne1, colonne2,...
une ou plusieurs colonnes. Les contraintes possibles sont : col1, col2,... doivent avoir la contrainte PRIMARY KEY ou UNIQUE. Ceci implique
UNIQUE, PRIMARY KEY, FOREIGN KEY...REFERENCES, CHECK qu'une valeur de colonne1, colonne2,... va référencer une et une seule ligne de tableref.
Chaque contrainte doit être nommée (ce qui permettra de la désigner par un ordre L'option ON DELETE CASCADE indique que la suppression d'une ligne de ta-
ALTER TABLE, et ce qui est requis par les nouvelles normes SQL) en la faisant précéder bleref va entrainer automatiquement la suppression des lignes qui la référencent dans la
de : table. Si cette option n'est pas indiquée, il est impossible de supprimer des lignes de tableref
CONSTRAINT nom-contrainte contrainte qui seraient référencées par des lignes de la table.
Il existe des contraintes : CHECK(condition )
sur une colonne : la contrainte porte sur une seule colonne. Elle suit la dénition de donne une condition que la ou les colonnes devront vérier (exemples dans la section
la colonne dans un ordre CREATE TABLE (pas possible dans un ordre ALTER suivante). On peut ainsi indiquer des contraintes d'intégrité de domaines dont on a des
TABLE). exemples dans la section 1.8.2.
sur une table : la contrainte porte sur une ou plusieurs colonnes. Elles se place au même Des contraintes d'intégrité peuvent être ajoutées ou supprimées par la commande AL-
niveau que les dénition des colonnes dans un ordre CREATE TABLE ou ALTER TER TABLE (exemple à la n de la section 1.8.2). Mais pour modier une contrainte, il
TABLE. faut la supprimer et ajouter ensuite la contrainte modiée.
Il est parfois intéressant d'enlever temporairement des contraintes. Oracle le permet
par la commande ALTER TABLE ... DISABLE/ENABLE mais n'utilise pas la commande
1.8.1 Types de contraintes de la norme SQL-2 (SET CONSTRAINTS ... DEFERRED/IMMEDIATE).
(pour une contrainte sur une table :)
PRIMARY KEY (colonne1, colonne2,...)
(pour une contrainte sur une colonne :)
1.8.2 Exemples de contraintes
PRIMARY KEY Quelques contraintes sur des colonnes :
indique la clé primaire de la table (contrainte d'intégrité d'entité). Aucune des colonnes CREATE TABLE EMP (
1.9. SÉLECTION SIMPLE 9 10 CHAPITRE 1. INTRODUCTION
MATR NUMBER(5) CONSTRAINT KEMP PRIMARY KEY, SELECT exp1, exp2,...
NOME CHAR(9) CONSTRAINT NOM_UNIQUE UNIQUE FROM table
CONSTRAINT MAJ CHECK (NOME = UPPER(NOME)), WHERE prédicat
......... table est le nom de la table sur laquelle porte la sélection. exp1, exp2,... est la liste des
DEPT NUMBER(2) CONSTRAINT R_DEPT REFERENCES DEPT(DEPT) expressions (colonnes, constantes,... ; voir 1.10) que l'on veut obtenir. Cette liste peut être
CONSTRAINT NDEPT CHECK (DEPT IN (10, 20, 30, 35, 40))) *, auquel cas toutes les colonnes de la table sont sélectionnées.
Des contraintes de colonne peuvent être mises au niveau de la table :
CREATE TABLE EMP (
Exemples 1.4
MATR NUMBER(5),
(a) SELECT * FROM DEPT
NOME CHAR(9) CONSTRAINT NOM_UNIQUE UNIQUE (b) SELECT NOME, POSTE FROM EMP
CONSTRAINT MAJ CHECK (NOME = UPPER(NOME)), (c) SELECT NOME , SAL + NVL(COMM,0) FROM EMP
.........
CONSTRAINT NDEPT DEPT NUMBER(2) CHECK (DEPT IN (10, 20, 30, 35, 40)), La clause WHERE permet de spécier quelles sont les lignes à sélectionner.
CONSTRAINT KEMP PRIMARY KEY (MATR), Le prédicat peut prendre des formes assez complexes. La forme la plus simple est exp1
CONSTRAINT R_DEPT FOREIGN KEY (DEPT) REFERENCES DEPT(DEPT)) op exp2, où exp1 et exp2 sont des expressions (voir 1.10) et op est un des opérateurs =,
Certaines contraintes portent sur plusieurs colonnes et ne peuvent être indiquées que != (diérent), >, >=, <, <=.
comme contraintes de table :
CREATE TABLE PARTICIPATION (
Exemple 1.5
SELECT MATR, NOME, SAL * 1.15
MATR NUMBER(5) CONSTRAINT R_EMP REFERENCES EMP,
FROM EMP
CODEP VARCHAR2(10) CONSTRAINT R_PROJET REFERENCES PROJET,
WHERE SAL + NVL(COMM,0) >= 12500
....,
CONSTRAINT PKPART PRIMARY KEY(MATR, CODEP))
Avec ALTER TABLE on peut ajouter, enlever ou modier des contraintes de colonnes
ou de tables : 1.10 Expressions
ALTER TABLE EMP
Les expressions acceptées par SQL portent sur des colonnes, des constantes, des fonc-
DROP CONSTRAINT NOM_UNIQUE
tions.
ADD (CONSTRAINT SAL_MIN CHECK(SAL + NVL(COMM,0) > 5000))
Ces trois types d'éléments peuvent être reliés par des opérateurs arithmétiques (+ - * /),
ALTER TABLE EMP
maniant des chaînes de caractères (|| pour concaténer des chaînes), des dates (- donne le
MODIFY NOME CONSTRAINT NOM_UNIQUE UNIQUE
nombre de jours entre deux dates).
Les priorités des opérateurs arithmétiques sont celles de l'arithmétique classique (* et
On peut aussi provisoirement supprimer et ensuite rétablir une contrainte par les clauses /, puis + et -). Il est possible d'ajouter des parenthèses dans les expressions pour obtenir
DISABLE et ENABLE de ALTER TABLE : l'ordre de calcul que l'on désire.
ALTER TABLE EMP
Les expressions peuvent gurer :
DISABLE CONSTRAINT NOM_UNIQUE UNIQUE en tant que colonne résultat d'un SELECT
dans une clause WHERE
1.9 Sélection simple dans une clause ORDER BY (étudiée en 3.11)
dans les ordres de manipulations de données (INSERT, UPDATE, DELETE étudiés
L'ordre pour retrouver des informations stockées dans la base est SELECT. au chapitre 2)
Nous étudions dans ce chapitre une partie simpliée de la syntaxe, susant néanmoins Le tableau qui suit donne le nom des principales fonctions (voir 3.10 pour plus de
à la plupart des interrogations courantes. Une étude plus complète sera vue au chapitre 3. détails).
1.10. EXPRESSIONS 11 12 CHAPITRE 2. LANGAGE DE MANIPULATION DES DONNÉES
DE GROUPE ARITHMETIQUES DE CHAINES DE DATES
SUM NVL NVL NVL
COUNT TO_CHAR SUBSTR TO_CHAR
VARIANCE SQRT LENGTH ADD_MONTHS
MAX ABS INSTR MONTHS_BETWEEN
MIN
Remarque 1.2
POWER TO_NUMBER NEXT_DAY
Chapitre 2
Toute expression dont au moins un des termes a la valeur NULL donne comme
résultat la valeur NULL.
La fonction NVL (Null VaLue ) permet de remplacer une valeur NULL par une valeur
Langage de manipulation des données
par défaut :
NVL (expr1, expr2 )
prend la valeur expr1, sauf si expr1 a la valeur NULL, auquel cas NVL prend la valeur Le langage de manipulation de données est le langage permettant de modier les infor-
expr2. mations contenues dans la base.
Il existe trois commandes SQL permettant d'eectuer les trois types de modication
Exemple 1.6 NVL(COMM, 0) des données :
INSERT ajout de lignes
UPDATE mise à jour de lignes
DELETE suppression de lignes
Ces trois commandes travaillent sur la base telle qu'elle était au début de l'exécution
de la commande. Les modications eectuées par les autres utilisateurs entre le début et
la n de l'exécution ne sont pas prises en compte (même pour les transactions validées).
2.1 Insertion
INSERT INTO table (col1,..., coln )
VALUES (val1,...,valn )
ou
INSERT INTO table (col1,..., coln )
SELECT ...
table est le nom de la table sur laquelle porte l'insertion. col1,..., coln est la liste des noms
des colonnes pour lesquelles on donne une valeur. Cette liste est optionnelle. Si elle est
omise, ORACLE prendra par défaut l'ensemble des colonnes de la table dans l'ordre où
elles ont été données lors de la création de la table. Si une liste de colonnes est spéciée,
les colonnes ne gurant pas dans la liste auront la valeur NULL.
Exemples 2.1
(a) INSERT INTO dept VALUES (10, 'FINANCES', 'PARIS')
(b) INSERT INTO dept (lieu, nomd, dept)
VALUES ('GRENOBLE', 'RECHERCHE', 20)
La deuxième forme avec la clause SELECT permet d'insérer dans une table des lignes
2.2. MODIFICATION 13 14 CHAPITRE 2. LANGAGE DE MANIPULATION DES DONNÉES
provenant d'une table de la base. Le SELECT a la même syntaxe qu'un SELECT normal. On remarquera que la moyenne des salaires sera calculée pour les valeurs qu'avaient
les salaires au début de l'exécution de la commande UPDATE et que les modications
Exemple 2.2 eectuées sur la base pendant l'exécution de cette commande ne seront pas prises en
Enregistrer la participation de MARTIN au groupe de projet numéro 10 : compte.
INSERT INTO PARTICIPATION (MATR, CODEP) (d) Enlever (plus exactement, mettre à la valeur NULL) la commission de MARTIN :
SELECT MATR, 10 UPDATE EMP
FROM EMP SET COMM = NULL
WHERE NOME = 'MARTIN'; WHERE NOME = 'MARTIN'
Une sous-interrogation peut ramener plusieurs lignes à condition que l'opérateur de Il a fallu renommer la table EMP de l'interrogation principale pour pouvoir la réfé-
comparaison admette à sa droite un ensemble de valeurs. rencer dans la sous-interrogation.
3.6. SOUS-INTERROGATION 25 26 CHAPITRE 3. INTERROGATIONS
3.6.4 Sous-interrogation ramenant plusieurs colonnes Souvent on peut utiliser IN à la place de la clause EXISTS. Essayez sur l'exemple
précédent.
Il est possible de comparer le résultat d'un SELECT ramenant plusieurs colonnes à une
liste de colonnes. La liste de colonnes gurera entre parenthèses à gauche de l'opérateur de Remarque 3.6
comparaison. Il faut se méer lorsque l'on utilise EXISTS en présence de valeurs NULL. Si on veut
Avec une seule ligne sélectionnée : par exemple les employés qui ont la plus grande commission par la requête suivante,
WHERE (exp, exp,...) op (SELECT ...) select nome from emp e1
Avec plusieurs lignes sélectionnées : where not exists
WHERE (exp, exp,...) op ANY (SELECT ...) (select matr from emp
WHERE (exp, exp,...) op ALL (SELECT ...) where comm > e1.comm)
WHERE (exp, exp,...) IN (SELECT ...) on aura en plus dans la liste tous les employés qui ont une commission NULL.
WHERE (exp, exp,...) NOT IN (SELECT ...)
WHERE (exp, exp,...)
où op est un des opérateurs = ou != Division avec la clause EXISTS
Les expressions gurant dans la liste entre parenthèses seront comparées à celles qui NOT EXISTS permet de spécier des prédicats où le mot tous intervient dans un
sont ramenées par le SELECT. sens comparable à celui de l'exemple suivant. Elle permet d'obtenir la division de deux
relations.
Exemple 3.13 On rappelle que la division de R par S sur l'attribut B (notée R B S, ou R S s'il
Employés ayant même poste et même salaire que MERCIER : n'y a pas d'ambiguïté sur l'attribut B) est la relation D dénie par :
SELECT NOME, POSTE, SAL FROM EMP
D = {a 2 R[A] / 8 b 2 S, (a,b) 2 R} = {a 2 R[A] / 6 9 b 2 S, (a,b) 62 R}
WHERE (POSTE, SAL) =
Faisons une traduction mot à mot de cette dernière dénition en langage SQL :
(SELECT POSTE, SAL FROM EMP select A from R R1
WHERE NOME = 'MERCIER') where not exists
(select C from S
On peut utiliser ce type de sous-interrogation pour retrouver les lignes qui correspondent where not exists
à des optima sur certains critères pour des regroupements de lignes (voir un exemple (select A, B from R
dans 3.8). where A = R1.A and B = S.C))
En fait, on peut remplacer les colonnes des select placés derrière des not exists par
ce que l'on veut puisque seule l'existence ou non d'une ligne compte. On peut écrire par
3.6.5 Clause EXISTS exemple :
select A from R R1
La clause EXISTS est suivie d'une sous-interrogation entre parenthèses, et prend la where not exists
valeur vrai s'il existe au moins une ligne satisfaisant les conditions de la sous-interrogation. (select null from S
where not exists
Exemple 3.14 (select null from R
SELECT NOMD FROM DEPT where A = R1.A and B = S.C))
WHERE EXISTS (SELECT NULL FROM EMP On arrive souvent à optimiser ce type de select en utilisant les spécicités du cas. Voyons
WHERE DEPT = DEPT.DEPT AND SAL > 10000); un exemple concret : la réponse à la question Quels sont les départements qui participent
Cette interrogation liste le nom des départements qui ont au moins un employé ayant à tous les projets? est fourni par R Dept S où R = (PARTICIPATION JMatr EMP)
plus de 10.000 comme salaire ; pour chaque ligne de DEPT la sous-interrogation syn- [Dept, CodeP] (JMatr indique une jointure sur l'attribut Matr) et S = PROJET [CodeP]
chronisée est exécutée et si au moins une ligne est trouvée dans la table EMP, EXISTS La traduction donne (en remplaçant presque mot à mot R par PARTICIPATION, EMP
prend la valeur vrai et la ligne de DEPT satisfait les critères de l'interrogation. et par la condition de jointure PARTICIPATION.Matr = EMP.Matr, S par PROJET, A
3.7. FONCTIONS DE GROUPES 27 28 CHAPITRE 3. INTERROGATIONS
par EMP.Dept, B par PARTICIPATION.CodeP et C par PROJET.CodeP) : Les valeurs NULL sont ignorées par les fonctions de groupe. Ainsi, SUM(col) est la
SELECT DEPT FROM PARTICIPATION, EMP E1 somme des valeurs qui ne sont pas égales à NULL de la colonne 'col'. De même, AVG est
WHERE PARTICIPATION.MATR = EMP.MATR la somme des valeurs non NULL divisée par le nombre de valeurs non NULL.
AND NOT EXISTS Il faut remarquer qu'à un niveau de profondeur (relativement aux sous-interrogations),
(SELECT CODEP FROM PROJET d'un SELECT, les fonctions de groupe et les colonnes doivent être toutes du même niveau
WHERE NOT EXISTS de regroupement. Par exemple, si on veut le nom et le salaire des employés qui gagnent le
(SELECT DEPT, CODEP FROM PARTICIPATION, EMP plus dans l'entreprise, la requête suivante provoquera une erreur :
WHERE PARTICIPATION.MATR = EMP.MATR SELECT NOME, SAL
AND DEPT = E1.DEPT AND CODEP = PROJET.CODEP)) FROM EMP
Sur ce cas particulier on voit qu'il est inutile de travailler sur la jointure de PARTICI- WHERE SAL = MAX(SAL)
PATION et de EMP pour le SELECT externe. On peut travailler sur la table DEPT. Il Il faut une sous-interrogation car MAX(SAL) n'est pas au même niveau de regroupement
en est de même sur tous les cas où la table R est une jointure. D'après cette remarque, que le simple SAL :
le SELECT précédent devient : SELECT NOME, SAL
SELECT DEPT FROM DEPT FROM EMP
WHERE NOT EXISTS WHERE SAL = (SELECT MAX(SAL) FROM EMP)
(SELECT CODEP FROM PROJET
WHERE NOT EXISTS
(SELECT DEPT, CODEP FROM PARTICIPATION, EMP 3.8 Clause GROUP BY
WHERE PARTICIPATION.MATR = EMP.MATR
AND DEPT = DEPT.DEPT AND CODEP = PROJET.CODEP)) Il est possible de subdiviser la table en groupes, chaque groupe étant l'ensemble des
lignes ayant une valeur commune.
GROUP BY exp1, exp2,...
3.7 Fonctions de groupes groupe en une seule ligne toutes les lignes pour lesquelles exp1, exp2,... ont la même valeur.
Cette clause se place juste après la clause WHERE, ou après la clause FROM si la clause
Les fonctions de groupes peuvent apparaître dans le Select ou le Having (voir 3.9) ; ce WHERE n'existe pas.
sont les fonctions suivantes : Des lignes peuvent être éliminées avant que le groupe ne soit formé grâce à la clause
AVG moyenne WHERE.
SUM somme
MIN plus petite des valeurs Exemples 3.16
MAX plus grande des valeurs (a) SELECT DEPT, COUNT(*)
VARIANCE variance FROM EMP
STDDEV écart type (déviation standard) GROUP BY DEPT
COUNT(*) nombre de lignes (b) SELECT DEPT, COUNT(*)
COUNT(col ) nombre de valeurs non nulles de la colonne FROM EMP
COUNT(DISTINCT col ) nombre de valeurs non nulles diérentes WHERE POSTE = 'SECRETAIRE'
GROUP BY DEPT
Exemples 3.15 (c) SELECT NOME, DEPT
(a) SELECT COUNT(*) FROM EMP
FROM EMP WHERE (DEPT, SAL) =
(b) SELECT SUM(COMM) (SELECT DEPT, MAX(SAL)
FROM EMP FROM EMP
WHERE DEPT = 10 GROUP BY DEPT)
3.9. CLAUSE HAVING 29 30 CHAPITRE 3. INTERROGATIONS
RESTRICTION : (SELECT MAX(COUNT(*))
Dans la liste des colonnes résultat d'un SELECT de groupe ne peuvent gurer que des FROM EMP
caractéristiques de groupe, c'est-à-dire : WHERE POSTE = 'SECRETAIRE'
soit des fonctions de groupe, GROUP BY DEPT)
soit des expressions gurant dans le GROUP BY.
Par exemple l'ordre suivant est invalide : On remarquera que la dernière sous-interrogation est indispensable car MAX(COUNT(*))
n'est pas au même niveau de regroupement que les autres expressions du premier SELECT.
SELECT NOMD, SUM(SAL)
FROM EMP, DEPT
WHERE EMP.DEPT = DEPT.DEPT
3.10 Fonctions
GROUP BY DEPT.DEPT
Nous allons décrire ci-dessous les principales fonctions disponibles dans Oracle. Il faut
Il aurait fallu écrire : remarquer que ces fonctions ne sont pas standardisées et ne sont pas toutes disponibles
dans les autres SGBD.
SELECT NOMD, SUM(SAL)
FROM EMP, DEPT
WHERE EMP.DEPT = DEPT.DEPT
3.10.1 Fonctions arithmétiques
GROUP BY NOMD ABS(n ) valeur absolue de n
MOD(n1, n2 ) n1 modulo n2
3.9 Clause HAVING POWER(n, e ) n à la puissance e
ROUND(n [, p ]) arrondit n à la précision p (0 par défaut)
SIGN(n ) -1 si n <0, 0 si n =0, 1 si n >0
HAVING prédicat
sert à préciser quels groupes doivent être sélectionnés. SQRT(n ) racine carrée de n
Elle se place après la clause GROUP BY. TO_CHAR(n, format ) convertit n en chaîne de caractères (voir 3.10.2)
Le prédicat suit la même syntaxe que celui de la clause WHERE. Cependant, il ne peut TRUNC(n [, p ]) tronque n à la précision p (0 par défaut)
porter que sur des caractéristiques de groupe : fonction de groupe ou expression gurant GREATEST(n1, n2,...) maximum de n1, n2,...
dans la clause GROUP BY. LEAST(n1, n2,...) minimum de n1, n2,...
TO_NUMBER(chaîne ) convertit la chaîne de caractères en numérique
Exemple 3.17
SELECT DEPT, COUNT(*) Exemple 3.18
FROM EMP Calcul du salaire journalier :
WHERE POSTE = 'SECRETAIRE' SELECT NOME, ROUND(SAL/22, 2) FROM EMP
GROUP BY DEPT
HAVING COUNT(*) > 1
3.10.2 Fonctions chaînes de caractères
On peut évidemment combiner toutes les clauses, des jointures et des sous-interrogations.
La requête suivante donne les noms des départements (et leur nombre de secrétaires) qui DECODE(crit, val1, res1 [,val2, res2,...], defaut )
ont le plus de secrétaires : permet de choisir une valeur parmi une liste d'expressions, en fonction de la valeur prise
par une expression servant de critère de sélection : elle prend la valeur res1 si l'expression
SELECT NOMD Departement, COUNT(*) "Nombre de secretaires" crit a la valeur val1, prend la valeur res2 si crit a la valeur val2,... ; si l'expression crit n'est
FROM EMP, DEPT égale à aucune des expressions val1, val2... , DECODE prend la valeur defaut par défaut.
WHERE EMP.DEPT = DEPT.DEPT AND POSTE = 'SECRETAIRE' Les expressions résultat (res1, res2, defaut ) peuvent être de types diérents : caractère et
GROUP BY NOMD numérique, ou caractère et date (le résultat est du type de la première expression rencontrée
HAVING COUNT(*) = dans le DECODE).
3.10. FONCTIONS 31 32 CHAPITRE 3. INTERROGATIONS
Les expression val et res peuvent être soit des constantes, soit des colonnes ou même de caractères. La fonction TRANSLATE remplace chaque caractère de la chaîne chaîne
des expressions résultats de fonctions. présent dans l'ensemble de caractères car_source par le caractère correspondant (de même
position) de l'ensemble car_cible.
Exemple 3.19 Exemple : remplacer les A et les M par des * dans les noms des employés :
Liste des employés avec leur catégorie (président = 1, directeur = 2, autre = 3) :
SELECT TRANSLATE (NOME, 'AM', '**') FROM EMP
SELECT NOME, DECODE(POSTE, 'PRESIDENT', 1, 'DIRECTEUR', 2, 3)
REPLACE(chaîne, ch1, ch2 ) remplace ch1 par ch2 dans chaîne.
LENGTH(chaîne ) La fonction TO_CHAR permet de convertir un nombre ou une date en chaîne de
prend comme valeur la longueur de la chaîne. caractère en fonction d'un format :
SUBSTR(chaîne, position [,longueur ]) Pour les nombres :
extrait de la chaîne chaîne une sous-chaîne de longueur longueur commençant en position TO_CHAR (nombre, format )
position de la chaîne.
Le paramètre longueur est facultatif : par défaut, la sous-chaîne va jusqu'à l'extrémité nombre est une expression de type numérique, format est une chaîne de caractère pouvant
de la chaîne. contenir les caractères suivants :
9 représente un chire (non représente si non signicatif)
INSTR(chaîne, sous-chaîne [,pos [,n ]]) 0 représente un chire (présent même si non signicatif)
prend comme valeur la position de la sous-chaîne dans la chaîne (les positions sont numé- . point décimal apparent
rotées à partir de 1). 0 signie que la sous-chaîne n'a pas été trouvée dans la chaîne. , une virgule apparaîtra à cet endroit
La recherche commence à la position pos de la chaîne (paramètre facultatif qui vaut $ un $ précédera le premier chire signicatif
1 par défaut). Une valeur négative de pos signie une position par rapport à la n de la B le nombre sera représente par des blancs s'il vaut zéro
chaîne. MI le signe négatif sera à droite
Le dernier paramètre n permet de rechercher la n ième occurrence de la sous-chaîne PR un nombre négatif sera entre < >
dans la chaîne. Ce paramètre facultatif vaut 1 par défaut.
Exemple 3.20 Exemple 3.21
Position du deuxième 'A' dans les postes : Achage des salaires avec au moins trois chires (dont deux décimales) :
SELECT INSTR (POSTE, 'A', 1, 2) FROM EMP
SELECT TO_CHAR(SAL, '9990.00') FROM EMP
UPPER(chaîne ) convertit les minuscules en majuscules
LOWER(chaîne ) convertit les majuscules en minuscules Pour les dates :
LPAD(chaîne, long [,car ]) TO_CHAR (date, format )
complète (ou tronque) chaîne à la longueur long. La chaîne est complétée à gauche par le format indique le format sous lequel sera achée date. C'est une combinaison de codes ;
caractère (ou la chaîne de caractères) car. en voici quelques uns :
Le paramètre car est optionnel. Par défaut, chaîne est complétée par des espaces. YYYY année
RPAD(chaîne, long [,car ]) a une fonction analogue, chaîne étant complétée à droite. YY deux derniers chires de l'année
Exemple : SELECT LPAD (NOME, 10, '.') FROM EMP WW numéro de la semaine dans l'année
LTRIM(chaîne, car ) MM numéro du mois
supprime les caractères à l'extrémité gauche de la chaîne chaîne tant qu'ils appartiennent DDD numéro du jour dans l'année
à l'ensemble de caractères car. DD numéro du jour dans le mois
RTRIM(chaîne, car ) D numéro du jour dans la semaine
a une fonction analogue, les caractères étant supprimés à l'extrémité droite de la chaîne. HH ou HH12 heure (sur 12 heures)
Exemple : supprimer les A et les M en tête des noms : HH24 heure (sur 24 heures)
SELECT LTRIM(NOME,'AM') FROM EMP MI minutes
TRANSLATE(chaîne, car_source, car_cible ) Tout caractère spécial inséré dans le format sera reproduit dans la chaîne de caractère
car_source et car_cible sont des chaînes de caractères considérées comme des ensembles résultat. On peut également insérer dans le format une chaîne de caractères quelconque, à
3.11. CLAUSE ORDER BY 33 34 CHAPITRE 3. INTERROGATIONS
condition de la placer entre guillemets. L'option facultative DESC donne un tri par ordre décroissant. Par défaut, l'ordre est
croissant.
Exemple 3.22 Le tri se fait d'abord selon la première expression, puis les lignes ayant la même valeur
SELECT TO_CHAR(DATEMB, 'DD/MM/YY HH24')
pour la première expression sont triées selon la deuxième, etc. Les valeurs nulles sont
WHERE TO_CHAR(DATEMB) LIKE '%/05/91'
toujours en tête quel que soit l'ordre du tri (ascendant ou descendant).
TO_NUMBER (chaîne ) Pour préciser lors d'un tri sur quelle expression va porter le tri, il est possible de
convertit une chaîne de caractères en nombre (quand la chaîne de caractères est composée donner le rang relatif de la colonne dans la liste des colonnes, plutôt que son nom. Il est
de caractères numériques. aussi possible de donner un nom d'en-tête de colonne du SELECT (voir 3.2).
ASCII(chaîne )
donne le code ASCII du premier caractère de chaîne. Exemple 3.23
CHR(n ) donne le caractère de code ASCII n. À la place de : SELECT DEPT, NOMD FROM DEPT ORDER BY NOMD
TO_DATE(chaîne, format ) on peut taper : SELECT DEPT, NOMD FROM DEPT ORDER BY 2
permet de convertir une chaîne de caractères en donnée de type date. Le format est iden-
tique à celui de la fonction TO_CHAR. Cette nouvelle syntaxe doit être utilisée pour les interrogations exprimées à l'aide d'un
opérateur booléen UNION, INTERSECT ou MINUS.
Elle permet aussi de simplier l'écriture d'un tri sur une colonne qui contient une
3.10.3 Fonctions de travail avec les dates expression complexe.
ROUND(date, précision )
arrondit la date à la précision spéciée. La précision est indiquée en utilisant un des masques Exemples 3.24
de mise en forme de la date. (a) Liste des employés et de leur poste, triée par département et dans chaque département
Exemple : premier jour de l'année où les employés ont été embauchés : par ordre de salaire décroissant :
SELECT ROUND (DATEMB, 'YY') FROM EMP SELECT NOME, POSTE
TRUNC(date, précision ) FROM EMP
tronque la date à la précision spéciée (similaire à ROUND). ORDER BY DEPT, SAL DESC
SYSDATE (b) SELECT DEPT, SUM(SAL) "Total salaires"
a pour valeur la date et l'heure courante du système d'exploitation hôte. FROM EMP
Exemple : nombre de jour depuis l'embauche : GROUP BY DEPT
SELECT ROUND(SYSDATE - DATEMB) FROM EMP ORDER BY 2
(c) SELECT DEPT, SUM(SAL) "Total salaires"
3.10.4 Nom de l'utilisateur FROM EMP
GROUP BY DEPT
USER ORDER BY SUM(SAL)
a pour valeur le nom sous lequel l'utilisateur est entré dans Oracle.
SELECT SAL FROM EMP
(d) SELECT DEPT, SUM(SAL) "Total salaires"
FROM EMP
WHERE NOME = USER
GROUP BY DEPT
ORDER BY "Total salaires"
3.11 Clause ORDER BY
Les lignes constituant le résultat d'un SELECT sont obtenues dans un ordre indéter- 3.12 Opérateurs booléens
miné. La clause ORDER BY précise l'ordre dans lequel la liste des lignes sélectionnées sera
donnée. Pour cette section on suposera que deux tables EMP1 et EMP2 contiennent les infor-
ORDER BY exp1 [DESC], exp2 [DESC], ... mations sur deux liales de l'entreprise.
3.12. OPÉRATEURS BOOLÉENS 35 36 CHAPITRE 4. LANGAGE DE DÉFINITION DES DONNÉES
3.12.1 Opérateur UNION
L'opérateur UNION permet de fusionner deux sélections de tables pour obtenir un
ensemble de lignes égal à la réunion des lignes des deux sélections. Les lignes communes
n'apparaîtront qu'une fois.
Exemple 3.25
Liste des ingénieurs des deux liales :
Chapitre 4
Langage de dénition des données
SELECT * FROM EMP1 WHERE POSTE='INGENIEUR'
UNION
SELECT * FROM EMP WHERE POSTE='INGENIEUR'
En fait, certains SGBD (Oracle version 8 mais pas la version 7, par exemple) orent
la possibilité de placer sur la machine du serveur Web un programme qui relaie les ordres
SQL vers des serveurs du SGBD, qui peuvent donc se trouver sur une autre machine.
Une autre solution souple pour accèder à une base de données à travers le Web est
d'utiliser des servlets (programmes Java qui travaillent directement avec le serveur Web)
Code Java
Serveur
qui ne sont pas des applets mais des applications Java et qui n'ont pas les contraintes de middleware
sécurité des applets. Ces servlets peuvent générer des pages Web (comme les programmes JDBC
CGI) qui contiennent des données de la base récupérées grâce à JDBC. Les servlets sont JDBC
voiture tiers collision. Le mot tiers désigne ici une entité bien dénie.
Par exemple, dans le modèle 2-tiers, 2 entité interviennent (application Java ou applette,
et SGBD) : une application Java ou une applet utilise JDBC pour parler directement avec Fig. 6.1 Modèle 2-tiers Fig. 6.2 Modèle 3-tiers
le SGBD qui gère la base de données.
Cependant ce type de serveur est bien souvent assez coûteux et il n'existe à ma connais-
Modèle 3-tiers Dans ce modèle, un serveur middleware est l'interlocuteur direct du sance que des solutions propriétaires qui obligent les applications à utiliser les protocoles
code Java client. C'est ce serveur qui échange des données avec le SGBD. du serveur, au détriment de la portabilité.
Nous avons alors 3 entités qui interviennent : un client (écrit en Java), un serveur
middleware installé quelque part sur le réseau, et le SGBD qui communique avec le client Modèle logique n-tiers Pour savoir si on est dans un modèle 2-tiers ou 3-tiers, il
en passant par le serveur middleware. faut examiner le découpage logique. Quand on utilise un simple relai en middleware pour
Ce serveur n'est pas nécessairement écrit en Java. Si c'est le cas, il utilisera le plus atteindre les données, on ne peut parler de modèle 3-tiers. En Oracle version 8, on a vu
souvent JDBC pour l'interface avec le SGBD. qu'il est possible de placer un relai du SGBD sur une machine qui est serveur Web pour
Cette solution a de nombreux avantages : permettre à une applet d'accéder directement aux données placées sur une autre machine.
On est ici dans un modèle 2-tiers plutôt que 3-tiers. Le tiers logique accès à la base est
Le serveur peut ajouter un niveau de sécurité ; simplement éclatés en 2 couches physiques : relai du SGBD et SGBD.
Il permet de centraliser des demandes venant de diérents types de programmes Dans un modèle n-tiers typique, les clients sont des clients légers : ils ne s'occupent
(navigateurs HTML, programmes écrits en diérents langages,...) vers diérents types essentiellement que de l'interface entre l'utilisateur et l'application. À l'autre bout se trouve
de stockages de données ; les serveurs de données.
Les échanges entre les applications clientes et le serveur peuvent avoir plusieurs sup- Le middleware est une couche de logiciels qui se trouvent sur le réseau entre les clients
ports (sockets, RMI Java, CORBA, HTML,...) ; et les serveurs de données. Il va assurer des services commun à toutes les applications,
Il permet plus de souplesse pour l'emplacement du serveur Web et du SGBD pour des comme
accès par une applette unsecure : ils peuvent se trouver sur des machines diérentes. le nommage, pour désigner une ressource sur le réseau par un nom logique et pas par
Il sut que le serveur Web et le serveur middleware se trouvent sur la même un emplacement physique,
machine. la sécurité pour l'accès aux données (ltrer par exemple les appels de méthodes
6.3. UTILISATION PRATIQUE DE JDBC 55 56 CHAPITRE 6. JAVA ET JDBC
distants), 3. Lancer l'exécution de ces commandes : interroger (executeQuery()), modier la base
la gestion des transactions, comme dans les SGBD, par exemple pour annuler éven- (executeUpdate()), ou lancer tout autre ordre SQL (execute())
tuellement les eets d'actions eectuées sur plusieurs types de données enregistrées 4. Fermer la connexion (close()).
dans des SGBD diérents, Ces étapes sont détaillées dans les sections suivantes.
la répartition de la charge des traitements sur plusieurs machines.
On peut parler d'architecture n-tiers car ces tâches sont eectuées par des entités bien
distinctes du middleware, et souvent réparties sur divers machines du réseau. 6.5 Classes et interfaces de JDBC
L'avantage d'un modèle logique n-tiers (n >2) est qu'il facilite l'utilisation de clients Interfaces Description
légers et que les gestions complexes citées ci-dessus sont encapsulées dans la couche midd- Driver renvoie une Connection utilisée par le DriverManager
leware . Ainsi, par exemple, un changement dans les règles de sécurité n'entraine pas une Connection connexion à une base
modication dans les autres couches. Les inconvénients sont avant tout une mise en place Statement lié à un ordre SQL
complexe et une mise au point dicile des programmes car les outils de débogage ne sont PreparedStatement lié à un ordre SQL paramétré
souvent pas adaptés à la programmation distribuée et il est dicile de trouver la source CallableStatement lié à une procédure stockée sur le serveur
des erreurs. ResultSet lignes récupérées par un ordre SELECT
ResultSetMetaData description des lignes récupérées par un SELECT
6.3 Utilisation pratique de JDBC DatabaseMetaData
Classes
informations sur la base de données
Description
Les exemples pratiques donnés dans ce cours utilisent une connexion avec une base de DriverManager gère les drivers, lance les connexions aux bases
données Oracle. Ils utilisent un driver de type 4 fourni (gratuitement) par Oracle. Date date SQL
Pour travailler avec JDBC et un certain driver, on doit : Time heures, minutes, secondes SQL
1. Ajouter le chemin des classes qui implémentent JDBC dans la variable CLASSPATH. TimeStamp comme Time avec une grande précision
Pour notre cas : Types constantes pour les types SQL
DriverPropertyInfo informations utilisées pour la connexion
ORACLE_HOME=/net4/oracle (pas utilisé pour la programmation ordinaire)
CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/classes111.zip
Exceptions Description
2. Le plus souvent on importera le package java.sql pour éviter de préxer ses éléments SQLException erreurs SQL
dans le programme : SQLWarning avertissements SQL
import java.sql.*; DataTruncation avertit quand une valeur est tronquée
3. Charger en mémoire la classe du driver. Pour celui que nous allons utiliser :
Class.forName("oracle.jdbc.driver.OracleDriver"); 6.6 Connexion à une base de données
Une connexion à un SGBD est représentée par une instance de la classe implémentant
6.4 Étapes du travail avec une base de données avec l'interface Connection. Dans la suite de ce cours on dira, en raccourci, par une instance
de la classe Connection et on utilisera le même type de raccourci pour les autres classes
JDBC qui implémentent les autres interfaces de JDBC.
Un des drivers précédemment enregistrés doit permettre d'accéder à la base. Les étapes On obtient une telle instance de Connection en retour de la méthode static getConnection()
du travail avec la base sont : de la classe DriverManager. On doit passer à cette méthode l'URL de la base de données.
En fait, le gestionnaire de driver essaye tous les drivers qui se sont enregistrés (au moment
1. Ouvrir une connexion (Connection) de leur chargement en mémoire par Class.forName()) jusqu'à ce qu'il trouve un driver
2. Créer les objets Java qui vont contenir les commandes SQL : Statement, PreparedStatement qui peut se connecter à la base.
ou CallableStatement Une URL pour une base de données est de la forme :
6.7. TRANSACTIONS 57 58 CHAPITRE 6. JAVA ET JDBC
jdbc:sous-protocole :base de donnée méthode next().
Par exemple, si on utilise le pont JDBC-ODBC, on pourrait avoir l'URL jdbc:odbc:base1. Exemple 6.1
En fait la syntaxe de l'URL dépend du driver utilisé. Il faut se reporter à la documen- Statement stmt1 = conn.createStatement();
tation du driver. // rset contient les lignes renvoyees par le select
Pour notre exemple avec Oracle, on aura, si erato est la machine qui héberge la base, ResultSet rset = stmt1.executeQuery("select NOME from EMP");
1521 est le port sur lequel le SGBD écoute les requêtes et MINFO est le nom de la base // On récupère chaque ligne une à une.
Oracle : // getString(1) récupère la 1ère colonne (voir sect. suivante)
static final String url = "jdbc:oracle:thin:@erato:1521:MINFO"; while (rset.next())
conn = DriverManager.getConnection(url, "toto", "mdptoto"); System.out.println (rset.getString(1));
stmt1.close();
6.11 Syntaxe spéciale SQL ( SQL Escape Syntax ) String nomColonne = rsmd.getColumnName(i);
System.out.println("La colonne " + i + " de nom "
+ nomColonne + " est de type " + typeColonne);
Ce type de syntaxe {mot-clé paramètre...} est utilisée par JDBC pour dénir une }
syntaxe commune à tous les SGBD quand ils ont des syntaxes diérentes. Une date est
ainsi représentée par {d 'yyyy-mm-dd'}, par exemple, {d '1998-02-18'}.
De même de nombreuses fonctions peuvent être supportées par les diérents drivers. 6.12.2 DatabaseMetaData
Reportez-vous à leur documentation pour savoir lesquelles (ou utilisez les méthodes de Voici un extrait de programme, qui ajoute dans une liste (classe List de l'AWT) les
DataBaseMetaData). noms des tables et vues disponibles dans une base de données :
private DatabaseMetaData metaData;
Exemples 6.7 private java.awt.List listTables = new java.awt.List(10);
(a) {fn concat("debut", "fin")}
.... {
(b) {fn user()} metaData = conn.getMetaData();
String[] types = { "TABLE", "VIEW" };
Remarque 6.4 // % : joker SQL pour désigner tous les noms
Ce type de syntaxe est aussi associé à la jointure externe qui a une syntaxe diérente ResultSet rs = metaData.getTables(null, null, "%", types);
dans les diérents SGBD. Oracle n'est d'ailleurs pas à la norme SQL-2 pour la jointure String nomTables;
externe. De plus, le driver fourni par Oracle ne supporte pas ce type de syntaxe. On while (rs.next()) {
doit donc utiliser la syntaxe particulière à Oracle (+) et on perd donc en portabilité. // Le nom des tables est la 3ème colonne du ResultSet
nomTable = rs.getString(3);
...
JDBC permet de récupérer des informations sur le type de données que l'on vient }
de récupérer par un SELECT (interface ResultSetMetaData), mais aussi sur la base de
données elle-même (interface DatabaseMetaData).
Les données que l'on peut récupérer dépendent du SGBD avec lequel on travaille,
surtout pour DatabaseMetaData. Dans la version actuelle d'Access, on ne peut ainsi pas
obtenir la liste de toutes les tables d'une base de données.
67 68 CHAPITRE 7. LANGAGE C ET PRO*C D'ORACLE
Par exemple, VARCHAR uid[20] sera remplacé par le précompilateur par la structure C
struct {
unsigned short len;
unsigned char arr[20];
Chapitre 7 } uid
Il ne faut pas oublier de donner la bonne valeur à len lorsque l'on récupère une valeur
à partir du langage C et qu'on l'utilise ensuite dans Oracle. En sens inverse, il faut ajouter
Langage C et Pro*C d'Oracle le caractère \0 en n de valeur dans le tableau arr lorsque l'on veut utiliser en langage
C une valeur obtenue par Oracle.
À chaque variable hôte associée à une colonne d'une table de la base on peut lier une
variable indicatrice de type short. Cette variable permettra de repérer et de donner une
Pour obtenir un programme exécutable à partir des programmes sources qui contiennent valeur 'NULL' ou tronquée (voir gure 7.3).
des instructions en Langage C et des requêtes SQL, il faut utiliser des outils annexes fournis
le plus souvent par la société qui commercialise le SGBD.
Avec Oracle, le programmeur a deux solutions pour insérer des ordres SQL dans un 7.2 Zone SQLCA
programme écrit en Langage C : Pour récupérer les codes et messages d'erreur et d'avertissement de SQL, on doit in-
l'utilisation dans ses programmes en langage C de fonctions C contenues par une sérer dans le programme l'instruction EXEC SQL INCLUDE SQLCA; qui inclut la zone de
bibliothèque écrite par Oracle. Le programmeur construit les ordres SQL dans le communication SQLCA. Cette zone contient (entre autres)
programme et les passe en paramètres de ces fonctions. Le programme doit être lié à le code retour de la derniere commande SQL exécutée (contenu dans la variable
la bibliothèque pour obtenir un programme exécutable. SQLCODE). Il est nul si la commande s'est bien passée, négatif si une erreur s'est
à un plus haut niveau qui simplie la tâche du programmeur, celui-ci insert dans ses produite et positive si la commande a provoqué un message d'avertissement.
programmes des pseudo-instructions qui ne sont pas du langage C. Un programme le nombre de lignes traitées par la dernière commande SQL (contenu dans SQ-
fourni par Oracle, appelé précompilateur, remplace alors ces pseudo-instructions par LERRD[2]).
des instructions en langage C ou par des appels aux fonctions C citées dans la première L'instruction EXEC SQL WHENEVER utilise cette zone pour traiter les erreurs.
solution. Le programme peut alors être compilé et lié aux bibliothèques fournies par
Oracle.
Le module Pro*C d'Oracle fournit les outils et les bibliothèques nécessaires. 7.3 Curseur
Des exemples de programmes sont donnés à la section 7.5. Les sections 7.1 et 7.2
donnent quelques précisons pour expliquer ces programmes. La section 7.4 montre comment Lorsqu'un ordre SELECT ramène plus d'une seule ligne, il est nécessaire d'utiliser un
construire les programmes exécutables et indique l'environnement nécessaire. curseur pour récupérer ces lignes dans le programme en langage C.
Un curseur est une zone temporaire dans laquelle sont stockées les lignes ramenées
par le SELECT. On ne peut lire cette zone que séquentiellement. La ligne courante est
7.1 Variables hôtes désignée par le mot clé CURRENT, ce qui permet eventuellement de la modier par un
ordre UPDATE ou de la supprimer par un ordre DELETE.
Les échanges de données entre les instructions en langage C et les ordres SQL se font Oracle a ajouté la possibilité de récupérer directement dans un tableau du langage C
grâce à des variables hôtes (du langage C) qui sont déclarées dans une zone spéciale les lignes renvoyées par un SELECT (un exemple est donné dans la gure 7.6).
du programme encadrée par les deux instructions EXEC SQL BEGIN DECLARE SECTION; et Les étapes de l'utilisation d'un curseur sont les suivantes :
EXEC SQL END DECLARE SECTION;. Ces variables sont préxees par ":" dans les ordres 1. Déclaration et dénition du curseur par l'ordre DECLARE. Par exemple,
SQL (mais pas dans les instructions en langage C). EXEC SQL DECLARE C1 CURSOR FOR
VARCHAR est un pseudo-type C qui sert à conserver des valeurs SQL de type VARCHAR2. SELECT MATR, NOME, SAL FROM EMP;
7.4. PRÉ-COMPILATION, COMPILATION ET EXÉCUTION DE PROGRAMMES ÉCRITS AVEC P 70 CHAPITRE 7. LANGAGE C ET PRO*C D'ORACLE
2. Ouverture par l'ordre OPEN, ce qui exécute l'ordre SELECT associé au curseur .
Par exemple,
EXEC SQL OPEN C1;
3. Récupèration des lignes dans les variables C par l'ordre FETCH. Par exemple,
EXEC SQL FETCH C1 INTO :matricule, :nom, :salaire;
4. Fermeture du curseur quand on n'en a plus besoin par l'ordre CLOSE (EXEC # include <stdio.h>
SQL COMMIT WORK RELEASE ferme automatiquement tous les curseurs). Par
exemple, /* Declaration des variables hotes */
EXEC SQL CLOSE C1; EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20];
7.5 Exemples
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
printf("\nConnexion a Oracle sous le nom %s\n", uid.arr);
EXEC SQL WHENEVER SQLERROR GOTO erreur;
Des exemples commentés sont donnés dans les gures 7.1 à 7.6.
La gure 7.7 donne les étapes pour obtenir un programme exécutable.
Fig. 7.1 Insertion de nouvelles lignes dans la table EMP (début)
7.5. EXEMPLES 71 72 CHAPITRE 7. LANGAGE C ET PRO*C D'ORACLE
while (1) {
printf("Matricule de l'employe (0 pour sortir) : ");
sret = scanf("%d", &matricule);
# include <stdio.h>
if (sret == EOF || sret == 0 || matricule == 0)
EXEC SQL BEGIN DECLARE SECTION;
break;
VARCHAR uid[20], pwd[20], nom[15];
printf("Nom de l'employe : ");
float salaire, commission;
scanf("%s", &nom.arr);
/* Variables indicatrices */
nom.len = strlen(nom.arr);
short salairei, commissioni;
printf("Poste de l'employe : ");
EXEC SQL END DECLARE SECTION;
scanf("%s", poste.arr);
EXEC SQL INCLUDE SQLCA;
poste.len = strlen(poste.arr);
printf("Salaire de l'employe : ");
main() {
scanf("%f", &salaire);
int sret;
printf("Numero du departement de l'employe : ");
/* Entree dans Oracle */
scanf("%d", &nodept);
.........
EXEC SQL INSERT INTO EMP
/* On recupere la ligne */
(matr, nome, poste, sal, dept)
printf("Nom de l'employe : ");
VALUES (:matricule, :nom, :poste, :salaire, :nodept);
scanf("%s", &nom.arr);
EXEC SQL COMMIT WORK;
nom.len = strlen(nom.arr);
printf("Employe %s ajoute\n", nom.arr);
EXEC SQL WHENEVER NOT FOUND pastrouve;
}
EXEC SQL SELECT SAL, COMM INTO :salaire, :commission:commissioni
FROM EMP
/* Quitter Oracle */
WHERE NOME = :nom;
EXEC SQL COMMIT WORK RELEASE;
exit(0);
/* Affichage de la ligne */
if (commissioni == -1)
mauvaisnom:
/* Valeur NULL */
printf("Mot de passe incorrect");
printf("Employe %s, salaire %6.2f\n", nom.arr, salaire);
EXEC SQL ROLLBACK WORK RELEASE;
else
exit(1);
printf("Employe %s, salaire %6.2f\n commission %6.2f",
nom.arr, salaire, commission);
erreur:
printf("\n%.70s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);} Fig. 7.3 Mise à jour d'une ligne dans la table EMP (début)
# include <stdio.h>
void afficher_lignes(int);
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20], pwd[20], nom[10][15];
int matricule[10];
float salaire[10];
short salairei[10];
/* Entree des nouvelles valeurs */
EXEC SQL END DECLARE SECTION;
printf("Nouveau salaire de l'employe : ");
EXEC SQL INCLUDE SQLCA;
sret = scanf("%f", &salaire);
if (sret == EOF || sret == 0)
main() {
salairei = -1; /* valeur NULL */
int sret;
printf("Nouvelle commission de l'employe : ");
long nb_lignes;
sret = scanf("%f", &commission);
/* Entree dans Oracle */
if (sret == EOF || sret == 0)
............
commissioni = -1; /* valeur NULL */
EXEC SQL DECLARE C1 CURSOR FOR
else
SELECT MATR, NOME, SAL FROM EMP;
commissioni = 1;
EXEC SQL OPEN C1;
EXEC SQL UPDATE EMP
EXEC SQL WHENEVER NOT FOUND GOTO finboucle;
SET SAL = :salaire:salairei,
nb_lignes = 0;
COMM = :commission:commissioni
while (1) {
WHERE NOME = :nom;
EXEC SQL FETCH C1 INTO :matricule, :nom, :salaire;
printf("Employe %s mis a jour", nom.arr);
/* sqlca.sqlerrd[2] est le nombre de lignes ramenees
depuis l'ouverture du curseur */
/* Quitter Oracle */
afficher_lignes(sqlca.sqlerrd[2] - nb_lignes);
EXEC SQL COMMIT WORK RELEASE;
nb_lignes = sqlca.sqlerrd[2];
exit(0);
}
finboucle:
pastrouve:
if (sqlca.sqlerrd[2] > nb_lignes)
printf("Pas d'employe %s dans la base", nom.arr);
/* Dernieres lignes a afficher */
EXEC SQL ROLLBACK WORK RELEASE;
afficher_lignes(sqlca.sqlerrd[2] - nb_lignes);
exit(1);
}
/* Quitter Oracle */
EXEC SQL WHENEVER SQLERROR CONTINUE;
Fig. 7.4 Mise à jour d'une ligne dans la table EMP (suite) EXEC SQL COMMIT WORK RELEASE;
exit(0);
}
Fig. 7.5 Utilisation d'un "curseur" pour ramener plusieurs lignes de la table EMP (par
paquets de 10) (début)
7.5. EXEMPLES 75
void afficher_lignes(n)
int n;
{
Index
int i;
printf("\nMatricule Nom Salaire\n");
printf( "--------- ---------- --------\n");
2-tiers, 53 DESC, 34
3-tiers, 53 dictionnaire de données, 44
for (i=0; i<n; i++)
printf("%-10d%-11s%9.2f\n",
3-tiers logique, 54 DISTINCT, 27
division, 26
matricule[i], nom[i].arr, salaire[i]); ABS, 30 donner des droits d'accès, 42
} accès concurrents, 46 driver JDBC, 51
ajouter une colonne, 37 DROP INDEX, 41
Fig. 7.6 Utilisation d'un "curseur" pour ramener plusieurs lignes de la table EMP (par
ALTER TABLE, 9, 37 DROP VIEW, 38
paquets de 10) (suite) AND, 19
annuler une transaction, 14 enlever des droits d'accès, 43
applet, 52 EXCEPT, 35
ASCII, 33 EXISTS, 25
AVG, 27 EXIT, 2
BETWEEN, 19 fonctions arithmétiques, 30
bloquer des données, 50 fonctions chaînes de caractères, 30
fonctions de groupes, 27
~/oracle> make -f proc.mk ex3 changer son mot de passe, 43 FOREIGN KEY, 8
proc ex3.pc CHAR, 5 FROM, 17
CHR, 33
Pro*C/C++: Release 2.2.2.0.0 - Production on Thu Feb 20 11:43:07 1997 colonne, 3 GRANT, 42
COMMIT, 14, 48 GREATEST, 30
Copyright (c) Oracle Corporation 1979, 1994. All rights reserved. CONSTRAINT, 7 GROUP BY, 28
contrainte d'intégrité, 7, 40, 45 HAVING, 29
System default option values taken from: /net4/oracle/precomp/admin/pcscfg.h COUNT, 27
créer un index, 40 identicateur, 2
gcc -DSLXMX_ENABLE -DSLTS_ENABLE -D_REENTRANT -I. -I/precomp/public -c ex3.c créer une table, 6, 36 IN, 19
gcc -o ex3 ex3.o -LRACLE_HOME/lib -lclntsh -lsql -lncr -lsqlnet -lclient\ créer une vue, 38 index, 40
-lcommon -lgeneric -lepc -lc3v6 -lcore3 -lnlsrtl3 -lnlsrtl3\ CREATE INDEX, 40 insérer des lignes, 12
`cat /net4/oracle/rdbms/lib/sysliblist` -lm -lthread CREATE TABLE, 6 INSERT, 12
CREATE TABLE AS, 36 INSTR, 31
CREATE VIEW, 38 interblocage, 48
Fig. 7.7 Exemple de traitement pour obtenir un programme exécutable curseur, 68 interroger la base, 16
DATE, 6 INTERSECT, 35
DECODE, 30 IS NULL, 19
DELETE, 14 Java, 51
76
INDEX 77 78 INDEX
JDBC, 51 procédure stockée, 43, 62 UNION, 35
jointure, 20 PUBLIC, 43 UNIQUE, 8
jointure externe, 21 UPDATE, 13
joker dans une chaîne, 19 REFERENCES, 8 UPPER, 31
REPLACE, 32 utilisation d'une vue, 39
LCD, 1, 47 ROLLBACK, 14, 48 utilité des vues, 39
LDD, 1, 47 ROUND, 30, 33
LEAST, 30 RPAD, 31 valider une transaction, 14
lecture consistante, 47, 50 RTRIM, 31 VARCHAR, 5
LENGTH, 31 schéma, 36
VARCHAR2, 5
LMD, 1 variable hôte, 67
LOCK TABLE, 47 SELECT FOR UPDATE, 49 variable indicatrice, 68
LOWER, 31 SET TRANSACTION READ ONLY, VARIANCE, 27
LPAD, 31 50 vue, 38
LTRIM, 31 SGBDR, 1
SIGN, 30 WHERE, 18
MAX, 27 sous-interrogation, 22 WITH CHECK OPTION, 39
MIN, 27 SQLCA, 68 WITH GRANT OPTION, 42
MINUS, 35 SQLFORMS, 2
mise à jour avec une vue, 39 SQRT, 30 zone SQLCA, 68
MOD, 30 STDDEV, 27
modèle de connexion, 53 SUBSTR, 31
modier des lignes, 13 SUM, 27
modier une colonne, 37 supprimer des lignes, 14
mot de passe, 43 supprimer un index, 41
supprimer une vue, 38
norme SQL, 1 SYSDATE, 33
NOT, 20 table, 3
NULL, 6 TO_CHAR, 30, 32
NUMBER, 4 TO_DATE, 33
NVL, 11 TO_NUMBER, 30, 33
ON DELETE CASCADE, 8 transaction, 14, 46
opérateur booléen, 34 TRANSLATE, 31
opérateur logique, 19 trigger, 44
OR, 19 TRUNC, 30, 33
ORDER BY, 33 type chaîne, 5
type numérique, 4, 6
pilote JDBC, 51 type numérique d'Oracle, 4
POWER, 30 type numérique SQL-2, 4
pré-compilation, 69 type temporels, 6
précompilateur, 67 types de contraintes, 7
PRIMARY KEY, 7 types temporels Oracle, 6
privilèges d'accès, 42 types temporels SQL-2, 6