Vous êtes sur la page 1sur 502

SQL

Nouvelle dition

Allen G. Taylor



SQL pour les Nuls (nouvelle dition)

Titre de ldition originale : SQL For Dummies, 8th Edition

Pour les Nuls est une marque dpose de Wiley Publishing, Inc.
For Dummies est une marque dpose de Wiley Publishing, Inc.

Collection dirige par Jean-Pierre Cano
Traduction : Jean-Paul Duplan et Stphane Bontemps
Mise en page : maged

Edition franaise publie en accord avec Wiley Publishing, Inc.
ditions First, un dpartement ddi8, 2017
ditions First, un dpartement ddi8
12 avenue dItalie
75013 Paris
Tl. : 01 44 16 09 00
Fax : 01 44 16 09 01
E-mail : firstinfo@efirst.com
Web : www.editionsfirst.fr
ISBN : 978-2-412-02377-8
ISBN numrique : 9782412026458
Dpt lgal : 1er trimestre 2017

Cette uvre est protge par le droit dauteur et strictement rserve lusage priv du
client. Toute reproduction ou diffusion au profit de tiers, titre gratuit ou onreux, de
tout ou partie de cette uvre est strictement interdite et constitue une contrefaon
prvue par les articles L 335-2 et suivants du Code de la proprit intellectuelle.
Lditeur se rserve le droit de poursuivre toute atteinte ses droits de proprit
intellectuelle devant les juridictions civiles ou pnales.

Ce livre numrique a t converti initialement au format EPUB par Isako


www.isako.com partir de l'dition papier du mme ouvrage.
Introduction

B
ienvenue dans le monde des bases de donnes et de son langage SQL
(langage structur de requtes). Il existe de nombreux systmes de
gestion de bases de donnes (SGBD) pour de nombreuses plates-formes
matrielles. Ces produits peuvent parfois tre trs diffrents, mais tous ceux
qui sont dignes de ce nom partagent quelque chose en commun : ils
permettent laccs et la manipulation des donnes via SQL. Connatre SQL,
cest pouvoir crer des bases de donnes relationnelles et en extraire
nimporte quelle information.
Au sujet de ce livre
Les systmes de gestion de base de donnes sont au cur de nombreuses
organisations. Les gens pensent souvent que la cration et ladministration
de ces systmes sont des tches trs complexes, rserves des
technogourous spcialiss en bases de donnes qui disposent de
connaissances que le simple mortel ne pourrait esprer acqurir. Ce livre
balaie ce mythe. Voici ce que vous y trouverez :
Dcouvrir les notions lmentaires des bases de donnes.

Comprendre comment un SGBD est structur.

Dcouvrir les fonctionnalits majeures de SQL.

Crer une base de donnes.

Protger une base de donnes.

Travailler sur les donnes dune base de donnes.

Dterminer comment extraire linformation que vous


souhaitez dune base de donnes.

Lobjectif de ce livre est de vous apprendre crer des bases de donnes


relationnelles et en extraire des informations utiles laide de SQL. SQL
est un langage standard international utilis dans le monde entier pour crer
et administrer des bases de donnes. Cette dition traite de la dernire
version du standard, SQL:2011.
Ce livre ne vous apprendra pas comment produire un modle de donnes. Je
suppose que vous-mme ou quelquun dautre lauront dj fait. Cependant,
cet ouvrage vous montrera comment implmenter ce modle laide de
SQL. Si vous pensez que votre modle de donnes nest pas bon, vous
devez absolument le repenser avant de construire la base de donnes
correspondante. Plus tt vous dtecterez et corrigerez ce type de problme
de conception, moins il vous en cotera.
Qui devrait lire ce livre ?
Connatre SQL vous rendra service chaque fois que vous devrez stocker ou
rcuprer des donnes dans un SGBD. Vous navez pas besoin dtre
programmeur pour utiliser SQL, pas plus que vous navez connatre des
langages tels que le COBOL, le C ou le Basic. La syntaxe de SQL est
entirement en anglais (et non en franais, dsol).
Si vous tes programmeur, vous pourrez incorporer SQL dans vos
programmes pour manipuler plus facilement des donnes. Ce livre vous
montrera comment procder afin dintgrer dans vos applications les riches
et puissants outils quoffre ce langage.
Icnes utilises dans ce livre
Ce conseil vous permet de gagner du temps et de lever des doutes.

Souvenez-vous de linformation signale par cette icne car vous pourrez


en avoir besoin ultrieurement.

Tenez compte du conseil qui Figure ct de cette icne. Il peut vous


garantir contre des problmes majeurs. Ignorez-le vos risques et prils.

Cette icne vous signale la prsence de dtails techniques quil est


intressant mais pas indispensable de connatre.
Pour commencer
Les bases de donnes sont les meilleurs outils qui aient t invents pour
conserver la trace des donnes qui vous importent. Comprendre comment
elles fonctionnent et matriser le langage SQL feront de vous un homme ou
une femme en vogue. Vos collgues viendront vous voir ds lors quils ou
elles auront besoin dinformations essentielles. Vos chefs vous solliciteront
pour des conseils. Les plus jeunes vous demanderont des autographes. Mais
plus que tout, vous pourrez comprendre comment fonctionne votre
entreprise (ou votre association) dans ses moindres dtails.
I
Dbuter en SQL

DANS CETTE PARTIE :

Les fondements des bases de donnes relationnelles.

Les concepts de base de SQL.

Les outils essentiels des bases de donnes.


Chapitre 1
Les bases de donnes
relationnelles
DANS CE CHAPITRE :
Organiser linformation.

Dfinir la notion de bases de donnes.

Dfinir ce quest un SGBD.

Comparer diffrents modles de bases de donnes.

Dfinir le concept de base de donnes relationnelle.

Traiter des problmes de conception dune base de donnes.

S
QL (Structured Query Language, ou langage structur de requtes
prononcez esse-q-elle et non squale) est un langage standard
spcifiquement conu pour permettre aux gens de crer des bases de
donnes, dy ajouter de nouvelles donnes, dassurer la maintenance de ces
donnes et den rcuprer des portions prcises. Dvelopp dans les
annes 1970 par IBM, SQL a volu au fil des ans jusqu devenir un
standard industriel. En tant que tel, il est maintenu par lorganisation
internationale des standards (ISO).
Il existe plusieurs types de bases de donnes dont chacun correspond un
concept de modlisation particulier.
SQL a t initialement dvelopp pour travailler sur des donnes contenues
dans des bases bties selon le modle relationnel. Rcemment, le standard
SQL a volu pour incorporer des lments du modle objet, produisant
ainsi des structures hybrides appeles bases de donnes objet-relationnel
(ou relationnel-objet, selon les auteurs). Dans ce chapitre, je traite du
stockage de donnes, je consacre une section expliquer comment le
modle relationnel se distingue des autres modles les plus connus, et je
prsente les fonctionnalits les plus importantes des bases de donnes
relationnelles.
Avant de parler de SQL, je voudrais prciser un point : je dois expliquer ce
que jentends par base de donnes. La signification de ce terme a volu
avec les ordinateurs et la manire dont les gens enregistrent et maintiennent
linformation.

Conserver la trace des choses


Aujourdhui les gens utilisent les ordinateurs pour accomplir des tches qui
ncessitaient autrefois dautres outils. Les ordinateurs ont remplac les
machines crire pour rdiger et modifier des documents. Ils ont surpass
les calculateurs lectromcaniques dans le calcul mathmatique. Ils ont
aussi remplac des millions de feuilles de papier et de fichiers dans le
stockage dinformations sensibles. Les ordinateurs travaillent mieux et plus
rapidement que tous ces vieux outils. Cependant, tout cela a un cot. Les
utilisateurs nont plus un accs physique direct leurs donnes.
Quand les ordinateurs tombent en panne (cest rare, mais cela peut arriver),
il est classique de les remettre en question en se demandant sils amliorent
rellement quelque chose. Cest quautrefois quand un dossier crashait
par terre, il suffisait de ramasser les papiers et de les ranger dans le
dossier. Et hormis les tremblements de terre et autres dsastres majeurs,
rien ne semblait vraiment pouvoir faire tomber en panne une armoire
dossiers. De mme, on na jamais vu une armoire envoyer un message
derreur. Mais quand un disque dur plante , cest une autre histoire. Vous
ne pouvez pas ramasser les bits et les octets. Des pannes mcaniques,
lectriques ou des dfaillances humaines font parfois disparatre de manire
dfinitive des donnes.
Il convient donc de prendre quelques mesures pour vous protger contre la
perte accidentelle de donnes. Voici quatre critres auxquels doit rpondre
le systme de stockage de linformation que vous choisirez :
Il doit tre rapide et facile de stocker des donnes, car
vous le ferez souvent.

Le support de stockage doit tre fiable. Vous ne voulez pas


vous apercevoir un beau matin que vos donnes ont
disparu comme par magie.

Il doit tre simple et rapide de rcuprer des donnes,


quelle que soit la quantit dinformations dont vous
disposez.

Vous devez pouvoir rapidement et facilement rcuprer


linformation que vous recherchez parmi des tonnes de
donnes.

Les bases de donnes dignes de ce nom satisfont ces critres. Et si vous


souhaitez stocker plus dune dizaine de donnes, vous dsirerez
probablement en utiliser une.

Quest-ce quune base de donnes ?


Le terme base de donnes est tomb dans le langage commun et a perdu son
sens initial. Pour certaines personnes, une base de donnes est un ensemble
dobjets htroclites (agenda, liste de courses, parchemins magiques).
Dautres personnes lui accordent une signification plus prcise.
Dans ce livre, je dfinirai une base de donnes comme un ensemble
denregistrements intgrs, capable de fournir une description de lui-mme.
Et tout cela implique videmment le passage par une technologie
informatique associe certains langages (SQL en tant lexemple qui nous
intresse dans ce livre).
Un enregistrement est la reprsentation dune donne physique ou dun objet
conceptuel. Imaginons par exemple que vous souhaitiez conserver la trace
des clients dune entreprise. Vous assignez un enregistrement chaque
client. Chaque enregistrement dispose de multiples attributs tels que le nom,
ladresse et le numro de tlphone. Le nom, ladresse et ainsi de suite
constituent les donnes.
Une base de donnes est constitue de donnes et de mtadonnes. Une
mtadonne est elle-mme une donne qui dcrit la structure des donnes
utiles prsentes dans la base. Si vous savez comment vos donnes sont
arranges, alors vous pouvez les retrouver. Puisque la base de donnes
contient une description de sa propre structure, on dit quelle est
autodescriptive. La base de donnes est intgre, car elle contient non
seulement des donnes, mais aussi la description des relations qui les
unissent.
La base de donnes conserve les mtadonnes dans une zone nomme
dictionnaire des donnes qui dcrit les tables, les colonnes, les index, les
contraintes et toute autre caractristique la dfinissant.
Comme un systme de fichiers plein texte (dcrit plus loin dans ce chapitre)
ne dispose daucune mtadonne, les applications conues pour travailler
avec de tels fichiers doivent contenir dans leur programme des informations
quivalant aux mtadonnes.

Volume et complexit dune base de


donnes
Il existe des bases de donnes de tout volume, dun simple ensemble de
quelques enregistrements au mammouth qui contient des millions
denregistrements.
Une base de donnes personnelle est conue pour tre
utilise par une seule personne sur un unique ordinateur.
Une telle base adopte gnralement une structure
relativement simple et son volume est limit.

Une base de donnes dpartementale ou de groupe de


travail est utilise par les membres dun dpartement ou
dun groupe de travail dune organisation. Ce type de base
de donnes occupe gnralement un volume plus
important quune base de donnes personnelle et est
ncessairement plus complexe, car il doit grer les accs
simultans de multiples utilisateurs aux mmes donnes.

Une base de donnes organisationnelle peut tre


norme. Ce type de base est utilis pour stocker les
informations dimportantes organisations ou entreprises.
Quest-ce quun systme de gestion
de bases de donnes ?
Bonne question. Un systme de gestion de bases de donnes (SGBD) est un
ensemble de programmes utiliss pour dfinir, administrer et traiter des
bases de donnes et leurs applications associes. La base de donnes
administre est, par essence, une structure que vous crez pour contenir
des donnes. Un SGBD est loutil que vous utilisez pour crer cette
structure et traiter les donnes qui se trouvent dans la base de donnes.
De nombreux SGBD sont disponibles sur le march. Quelques-uns ne
fonctionnent que sur des grands systmes (ou mainframes), des ordinateurs
portables, des tablettes. Toutefois, la tendance de ces produits est de
fonctionner sur de multiples plates-formes ou sur des rseaux qui
contiennent diffrentes classes de machines. Une tendance encore plus
marque est de stocker les donnes dans des centres dhbergement de
donnes (data centers), voire de les stocker dans le cloud, qui peut tre un
cloud public gr par une entreprise telle quAmazon, Google ou Microsoft,
via Internet, ou un cloud priv gr par lorganisation qui stocke les
donnes sur son intranet.
De nos jours, cloud est un terme la mode utilis sans arrt dans les cercles
techniques. Tout comme ces choses blanches dans le ciel, ses contours sont
indfinis et il semble flotter quelque part. En ralit, cest un ensemble de
ressources informatiques accessibles depuis un navigateur, sur Internet ou
sur un intranet priv. Ce qui distingue les ressources informatiques dans le
cloud de celles dun data center physique, cest le fait que ces ressources
sont accessibles via un navigateur plutt que via un programme qui y accde
directement.
Un SGBD qui fonctionne sur diverses plates-formes, aussi bien petites que
grandes, est dit pouvoir monter en charge.

Quelle que soit la taille de lordinateur sur lequel fonctionne la base de


donnes, et que la machine soit connecte ou non un rseau, le flot des
informations entre lutilisateur et la base de donnes est toujours le mme.
La Figure 1.1 montre comment lutilisateur communique avec la base de
donnes via le SGBD. Le SGBD masque physiquement les dtails du
stockage des donnes, de sorte que lapplication na se proccuper que de
la manipulation de celles-ci et non de la manire dont elles sont extraites ou
stockes.

FIGURE 1.1 Diagramme de bloc dun systme dinformation base de SGBD.

LA VALEUR EST DANS LA STRUCTURE, PAS DANS LES


DONNES

Imaginons un instant que lon rduise un tre humain aux atomes qui
le composent (carbone, hydrogne, oxygne, nitrogne, plus quelques
autres dont le nom mchappe). Que resterait-il de vous ? Bien peu de
choses en vrit. Mais cest une mauvaise manire de prendre le
problme. Les gens ne sont pas simplement composs de collections
datomes isols. Nos atomes se combinent pour former des
protines, des enzymes, des hormones et bien dautres substances
qui coteraient des millions deuros le sachet dans lindustrie
pharmaceutique. La structure prcise de ces combinaisons datomes
est justement ce qui leur donne une si haute valeur. Par analogie, la
structure de nos bases est ce qui rend possible linterprtation de
donnes nayant par elles-mmes aucune signification prcise. La
structure ajoute ces donnes inertes du sens et de la cohrence. Elle
permet den dgager des schmas, des trames, des tendances, et
ainsi de suite. Des donnes non structures ( linstar datomes non
combins) nont que peu ou pas de valeur du tout.
Les fichiers plein texte
Quand il sagit de stocker des donnes non structures, le fichier plein texte
peut se rvler tre une excellente solution. Un tel fichier contient une
squence denregistrements prsente dans un unique format et rien dautre
(les donnes, toutes les donnes, mais rien que les donnes). Puisque ce
fichier ne contient aucune information sur la structure de linformation
(mtadonnes), il occupe un espace minimum.
Supposons que vous dsiriez stocker les noms et les adresses des clients
amricains de votre entreprise dans un fichier plein texte. Vous pourriez
adopter la structure suivante :

Harold Percival 26262 S. Howards Mill Rd


Westminster CA92683
Jerry Appel 32323 S. River Lane Rd
Santa Anna CA92705
Adrian Hansen 232 Glenwood Court
Anaheim CA92640
John Baker 2222 Lafayette St
Garden Grove CA92643
Michael Pens 77730 S. New Era Rd
Irvine CA92715
Bob Michimoto 25252 S. Kelmsley Dr
Stanton CA92610
Linda Smith 444 S.E. Seventh St
Costa Mesa CA92635
Robert Funnell 2424 Sheri Court
Anaheim CA92640
Bill Checkal 9595 Curry Dr
Stanton CA92610
Jed Style 3535 Randall St
Santa Anna CA92705

Comme vous pouvez le voir, le fichier ne contient que les donnes. Chaque
champ occupe un espace fixe (par exemple, le champ Nom
occupe 15 caractres) et aucune structure ne spare un champ dun autre. La
personne qui a cr cette base de donnes a dcid de la position et de la
longueur des champs. Tout programme qui voudrait utiliser ce fichier devra
connatre la manire dont les champs sont organiss, puisque le fichier
ne contient aucune information ce sujet.
Du fait de leur simplicit, les fichiers plein texte peuvent offrir une grande
rapidit de traitement. Par contre, toute la complexit de la gestion est
transfre aux programmes qui les grent. Les applications doivent savoir
exactement o et comment les donnes sont enregistres dans le fichier.
Cest pourquoi lutilisation dun fichier plein texte nest intressante que sur
de petits systmes. Ds que lon dpasse une certaine chelle, ils
deviennent un frein au dveloppement.
Une vritable base de donnes, si elle contient effectivement un certain
nombre dinformations qui ne sont pas directement utiles, prsente
lavantage de pouvoir tre exploite sur de nombreuses plates-formes
matrielles et systmes dexploitation. Il est aussi plus simple dcrire un
programme qui manipule une base de donnes quun fichier plein texte, car
le programme na pas connatre lavance lorganisation des donnes
quil traite.
De plus, la logique daccs aux donnes et de leur manipulation na pas
tre intgre dans le programme, car elle se trouve dj dans le SGBD. Par
consquent, il nest pas ncessaire de reprogrammer cette portion du
programme quand il sagit de porter ce dernier dune plate-forme matrielle
une autre. Et cest l o les fichiers plein texte atteignent trs vite leurs
limites.

Les modles de base de donnes


Dans les annes 1950, les premires bases de donnes taient structures
selon un modle hirarchique. Elles posaient des problmes de redondance
de donnes, et la rigidit de leur structure compliquait leur modification.
Bientt, elles furent suivies par des bases de donnes qui collaient au
modle rseau, pour tenter dliminer les inconvnients principaux du
modle hirarchique. Les bases de donnes en rseau minimisent la
redondance, mais au prix dune complexit structurelle accrue.
Quelques annes plus tard, le DR. E.F. Codd dIBM inventa le modle
relationnel, qui minimisait la redondance tout en permettant de comprendre
facilement la structure. Le langage SQL a t conu pour travailler sur des
bases de donnes relationnelles. Lapparition de telles bases permit de faire
passer les bases de donnes hirarchiques et rseau aux oubliettes de
lhistoire.
Un nouveau phnomne est lmergence de bases de donnes dsignes
comme NoSQL, qui nont pas la structure des bases de donnes
relationnelles et qui nutilisent pas le langage SQL. Je ne traite pas des
bases de donnes NoSQL dans ce livre.

Le modle relationnel
Le Dr E.F. Codd dIBM inventa le modle relationnel de base de
donnes en 1970, mais ce modle ne commena tre utilis dans des
produits quune dizaine dannes plus tard. Ironie de lhistoire, ce ne fut pas
IBM que revint la primeur de dlivrer le premier de ces produits. Lacte
de naissance fut sign par une toute jeune socit qui nomma son bb
Oracle.
Les bases de donnes relationnelles ont remplac les anciens schmas, car
le modle relationnel prsente un certain nombre davantages sur ceux qui
lont prcd. Le plus important de ces avantages est sans doute que, dans
une base de donnes relationnelle, vous pouvez changer la structure de cette
base sans pour autant avoir modifier les applications bases sur les
anciennes structures. Supposons par exemple que vous ajoutiez une ou
plusieurs nouvelles colonnes une table de base de donnes. Vous naurez
pas besoin de changer les applications prcdemment crites pour traiter
cette table, moins que vous nayez modifi une ou plusieurs des colonnes
manipules par lesdites applications.
Bien entendu, si vous supprimez une colonne rfrence par une application
existante, cette dernire risque de ne plus fonctionner correctement. Et cest
vrai quel que soit le modle de base de donnes que vous utilisez. Il ny a
pas de meilleure manire pour planter une application de base de
donnes que de lui demander de rcuprer une information qui nexiste plus.

Les composants dune base de


donnes relationnelle
Les bases de donnes relationnelles tirent leur flexibilit du fait que leurs
donnes rsident dans des tables largement indpendantes les unes des
autres. Vous pouvez ajouter, supprimer ou modifier des donnes dans une
table sans modifier celles qui se trouvent dans les autres tables, du moment
que la structure affecte nest pas un parent dautres tables (les relations
parent-enfant entre les tables sont expliques dans le Chapitre 5). Dans cette
section, je vais vous montrer en quoi consistent ces tables et comment elles
sont lies aux autres lments qui composent une base de donnes
relationnelle.

Devine qui vient dner ce soir ?


Nombreuses sont les relations que jinvite ma table durant les vacances.
Les bases de donnes ont aussi des relations, mais chacune de leur relation
dispose de sa propre table. Une base de donnes relationnelle est constitue
dune ou de plusieurs relations.
Une relation est un tableau deux dimensions, donc form de lignes et de
colonnes. Chaque cellule du tableau contient une et une seule valeur, et deux
lignes ne peuvent pas tre identiques.
Les tableaux deux dimensions sont ceux que vous utilisez dans des
tableurs de type Microsoft Excel ou OpenOffice.org Calc. Les statistiques
dun joueur de base-ball que lon retrouve au dos de cartes de collection
sont un autre exemple de tels tableaux. On trouve sur ces cartes des
colonnes pour lanne, lquipe, les parties, les diffrents types de points
marqus. Une range traite dune anne durant laquelle le joueur aura
particip aux vnements sportifs majeurs. Vous pouvez stocker ces donnes
dans une relation (une table) qui adopterait la mme structure de base. La
Figure 1.2 reprsente une table dune base de donnes relationnelle qui
contient les statistiques dun certain joueur. Dans la pratique, ce genre de
table proposerait des statistiques relatives tous les joueurs dune quipe.

FIGURE 1.2 Une table contenant les statistiques dun joueur de base-ball.
Les colonnes dun tableau sont consistantes, cest--dire quune colonne a
la mme signification dans chaque ligne. Si une colonne contient le nom
dun joueur dans une ligne, elle devra contenir le nom dun joueur dans
toutes les lignes. Lordre dans lequel les lignes et les colonnes apparaissent
dans le tableau na aucune signification. Le SGBD traite la table de la mme
manire, quel que soit lordre de ses colonnes. Il en va de mme pour les
lignes.
Chaque colonne de la table dune base de donnes reprsente un attribut de
la table. La signification dune colonne est la mme pour toutes les lignes de
la table. Par exemple, une table peut contenir les noms, adresses et numros
de tlphone de tous les clients dune organisation. Chaque ligne de la table
(aussi nomme enregistrement ou tuple) contient les informations relatives
un seul client. Chaque colonne reprsente un unique attribut, tel que le
numro du client, le nom du client, la rue du client, la ville du client, le
code postal du client ou encore son numro de tlphone. La
Figure 1.3 montre quelques-unes des lignes et des colonnes dune telle
table.

FIGURE 1.3 Chaque ligne de la base de donnes contient un enregistrement ; chaque


colonne de la base de donnes contient un unique attribut.

Dans ce modle de base de donnes, les relations correspondent aux tables


figurant dans toute base de donnes fonde sur ce modle. Rptez-le dix
fois rapidement pour vous en souvenir.

Profitez de la vue
Il vous est probablement dj arriv de vous arrter sur la route pour
contempler la vue. Les bases de donnes ont aussi des vues, mme si elles
ne sont pas aussi pittoresques. Les vues des bases de donnes tirent leur
beaut du fait quelles sont extrmement utiles quand vous travaillez sur vos
donnes.
Les tables peuvent contenir de nombreuses colonnes et lignes. Il arrive que
toutes les donnes vous intressent, et il arrive aussi que ce ne soit pas le
cas. Seules quelques colonnes de la table retiennent votre attention ou
seules quelques lignes rpondent vos conditions. Certaines colonnes dune
table et certaines colonnes dune autre table peuvent vous intresser. Pour
liminer les donnes dont vous navez pas besoin dans linstant, vous
pouvez crer une vue. Une vue est un sous-ensemble dune base de donnes
quune application est capable de traiter. Elle peut contenir des parties
dune ou de plusieurs tables.
Les vues sont parfois appeles tables virtuelles. Du point de vue de
lapplication ou de lutilisateur, les vues se comportent comme des tables.
Pour autant, elles nont pas dexistence physique. Les vues vous permettent
de jeter un il sur vos donnes, mais elles ne font pas partie des donnes en
elles-mmes.
Imaginons par exemple que vous travailliez sur une base de donnes qui
contient une table CLIENTS et une table FACTURES. La table CLIENTS
possde les colonnes CLIENT_ID, NOM, PRENOM, RUE, VILLE, ETAT,
CODE_POSTAL et TELEPHONE. La table FACTURES contient les
colonnes NUMERO_FACTURE, CLIENT_ID, DATE, TOTAL_VENTE,
TOTAL_REMIS et METHODE_PAIEMENT.
Un responsable des ventes du pays veut voir lcran le prnom, le nom et
le numro de tlphone des clients. Vous pouvez crer partir de la table
CLIENTS une vue qui contienne seulement ces trois colonnes et permette au
responsable de nafficher que les informations dont il a besoin, sans
sencombrer avec le contenu des autres colonnes. La Figure 1.4 montre
quoi ressemblerait cette vue.
Un responsable en charge dun dpartement ou dun tat pourrait vouloir ne
visualiser que les noms et les numros de tlphone des clients dont le code
postal est compris entre 90000 et 93999 (Californie centrale et Californie
du Sud). Une vue qui appliquerait une restriction sur les lignes et les
colonnes voulues pourrait effectuer ce travail. La Figure 1.5 montre do
cette vue tirerait ses donnes.
FIGURE 1.4 La vue du RESPONSABLE DES VENTES drive de la table CLIENTS.

FIGURE 1.5 La vue du RESPONSABLE DU DEPARTEMENT ne contient que quelques-


unes des lignes de la table CLIENTS.

Le responsable des ventes en cours peut vouloir visualiser les donnes NOM
et PRENOM de la table CLIENTS ainsi que les donnes DATE,
TOTAL_VENTE, TOTAL_REMIS et METHODE_PAIEMENT de la table
FACTURES, quand TOTAL_REMIS vaut moins que TOTAL_ VENTE, ce
qui sera le cas si le client na pas encore entirement rgl sa facture. Il faut
donc laborer une vue qui contienne des donnes extraites des deux tables.
La Figure 1.6 montre le flux de donnes entre la vue du responsable des
ventes en cours et les tables CLIENTS et FACTURE.

FIGURE 1.6 La vue EN_ COURS tire ses donnes de deux tables.

Les vues sont trs utiles car elles vous permettent dextraire et de formater
des donnes dune base de donnes sans altrer physiquement les donnes
stockes. Elles protgent aussi les donnes que vous ne voulez pas afficher,
car elles ne les contiennent pas. Le Chapitre 6 explique dans le dtail
comment crer une vue en SQL.

Schmas, domaines et contraintes


Une base de donnes nest pas seulement un ensemble de tables. De
nombreuses structures supplmentaires, sur diffrents niveaux, permettent
de maintenir lintgrit des donnes. Le schma de la base de donnes
dtaille lorganisation gnrale des tables. Le domaine dune colonne dune
table vous indique quelles valeurs vous pouvez stocker dans cette colonne.
Vous pouvez appliquer des contraintes une table dune base de donnes
pour empcher que quelquun (dont vous-mme) nenregistre des donnes
non valides dans la table.

Schmas
Lintgralit de la structure dune base de donnes est stocke dans son
schma ou vue conceptuelle. Cette structure est quelquefois aussi appele
vue logique complte de la base de donnes. Le schma est une mtadonne
et, en tant que telle, une partie intgrante de la base de donnes. La
mtadonne, qui dcrit la structure de la base de donnes, est stocke dans
des tables qui ressemblent en tout point aux tables qui contiennent des
donnes classiques. Une mtadonne nest rien de plus quune donne. Cest
la beaut de la chose.

Domaines
Un attribut dune relation (autrement dit une colonne dune table) peut
naccepter quun nombre fini de valeurs. Lensemble de ces valeurs
autorises constitue le domaine de lattribut.
Supposons que vous soyez un vendeur de voitures et que vous deviez grer
le nouveau modle Curarri GT 4000 coup sport. Vous conservez la trace
des voitures que vous avez en stock dans une table que vous nommez
INVENTAIRE. Vous nommez lune des colonnes de cette table COULEUR,
car elle contient la couleur extrieure de chaque voiture. La GT 4000 existe
en quatre coloris : gris, noir, blanc et rouge. Ces quatre couleurs constituent
le domaine de lattribut COULEUR.

Contraintes
Une contrainte est un lment important (quoique trop souvent nglig)
dune base de donnes. Cest une rgle qui prcise les valeurs que peut
prendre un attribut dune table.
En appliquant des contraintes une colonne, vous pouvez empcher les gens
de saisir des donnes non valides dans cette colonne. Bien entendu, chacune
des valeurs appartenant au domaine de la colonne doit satisfaire les
contraintes qui psent sur cette dernire. Comme je lai mentionn dans la
section prcdente, le domaine dune colonne est lensemble des valeurs
que cette colonne peut contenir. Une contrainte est une restriction sur ce que
la colonne a le droit de contenir. Les caractristiques dune colonne de
table, plus les contraintes qui sappliquent cette colonne, dterminent le
domaine de la colonne. En appliquant des contraintes, vous pouvez
empcher la saisie dune donne qui nappartient pas au domaine de la
colonne.
Dans lexemple du vendeur de voitures, vous pouvez contraindre la base de
donnes naccepter que les quatre couleurs du modle dans la colonne
COULEUR. Si loprateur de saisie tente de rentrer une autre teinte, par
exemple vert, le systme refusera la saisie.
Vous vous demandez dj ce qui va se passer si le constructeur dcide de
sortir une srie limite de la Curarri GT 4000 coup sport verte ! La
rponse est simple (roulez tambours) : il va falloir que les dveloppeurs
chargs de la maintenance de la base de donnes modifient le domaine de la
colonne COULEUR pour sadapter au nouveau modle. Ce genre de
situation se produit tout le temps, impliquant donc des adaptations de la
structure de la base de donnes. Seules les personnes qui savent comment
procder (et vous en faites partie) seront capables dviter un dsastre
commercial.

Le modle objet oppos au modle


relationnel
Le modle relationnel sest rvl extraordinairement utile dans un grand
nombre dapplications. Cependant, il nest pas exempt de dfauts. Ces
problmes sont devenus plus vidents avec lavnement des langages de
programmation orients objet tels que le C++, Java et C#. De tels langages
sont capables de sattaquer des questions bien plus complexes que les
langages traditionnels, en particulier parce quils implmentent des
concepts tels que lextensibilit des types de donnes, lencapsulation,
lhritage, le lien dynamique aux mthodes, les objets complexes et
composites et lidentit des objets.
Je ne vais pas expliquer dans ce livre quoi correspondent toutes ces
notions (mme si nous ferons rfrence certaines dentre elles
ultrieurement). Il faut simplement comprendre que le modle relationnel
classique nest pas compatible avec un bon nombre de ces fonctionnalits.
Il en rsulte que des systmes de gestion de bases de donnes bass sur le
modle objet ont t dvelopps et sont aujourdhui commercialiss.
Cependant, leur part de march est encore limite ce jour.
Score final : bases de donnes relationnelles : 1 ; bases de donnes
orientes objet : 0.

Le modle objet-relationnel
Les concepteurs de bases de donnes sont constamment en qute du meilleur
monde possible. Ils songent : Ne serait-il pas fabuleux si nous pouvions
disposer de tous les avantages que procurent les systmes de gestion de
bases de donnes orients objet tout en restant compatibles avec le systme
relationnel que nous connaissons et apprcions tous ? Ce type de rflexion
a men au modle objet-relationnel. Les SGBD objet-relationnel tendent le
modle relationnel en y intgrant la gestion de la modlisation oriente
objet des donnes. Des fonctionnalits orientes objet ont t rajoutes au
standard international SQL pour permettre aux vendeurs de SGBD
relationnels de transformer leurs produits en SGBD orients objet, tout en
restant compatibles avec le standard. Si le standard SQL-92 ne traite que du
modle purement relationnel, le standard SQL-1999 (galement appel
SQL3) dcrit un modle de bases de donnes objet-relationnel.
SQL:2003 inclut encore plus de fonctionnalits orientes objet, et les
versions suivantes du standard SQL ont pouss encore plus loin dans ce
sens.
Je prsente dans ce livre le standard international SQL ISO/ IEC. Cest--
dire, et pour lessentiel, un modle de bases de donnes relationnelles. Je
dcris aussi les extensions orientes objet qui ont t rajoutes dans
SQL:1999 ainsi que celles introduites dans les versions suivantes. Les
fonctionnalits orientes objet du nouveau standard permettent aux
dveloppeurs dutiliser des bases de donnes SQL pour rsoudre des
problmes trop complexes rsoudre pour les anciens concepts purement
relationnels. Les vendeurs de SGBD incorporent les fonctionnalits
orientes objet du standard ISO dans leurs produits. Quelques-unes de ces
fonctionnalits existent depuis des annes, mais dautres restent encore
inclure.

Considrations sur la conception de


bases de donnes
Une base de donnes est la reprsentation dune structure physique ou
conceptuelle telle quune organisation, une usine de voitures ou les
statistiques des performances de tous les clubs de base-ball. La prcision
de la reprsentation dpend du niveau de dtail apport lors de la
conception. La somme defforts que vous investissez dans la conception de
votre base de donnes devrait dpendre du type dinformation que vous
comptez y stocker. Trop de dtails rime avec efforts inutiles, temps perdu et
gaspillage despace sur le disque. Pas assez de dtails peut rendre votre
base de donnes inutilisable.
Etudiez le niveau de dtail dont vous avez besoin sur linstant et celui dont
vous aurez besoin dans le futur. Cest lavenir que vous devez penser lors
de votre conception. Mais ne soyez pas surpris si vous devez procder
quelques ajustements pour satisfaire aux contraintes du monde rel et leurs
volutions.
Les systmes de gestion de bases de donnes actuels, dots dinterfaces
graphiques attrayantes et doutils de conception intuitifs, peuvent entretenir
chez le concepteur un faux sentiment de scurit. Ces systmes laissent
penser que la conception dune base de donnes sapparente beaucoup
celle dune feuille de calcul dans un tableur. Malheureusement, ce nest pas
le cas. La conception dune base de donnes est une tche complexe. Si
vous vous y prenez mal, vous produirez une base de donnes qui ne
rsistera pas au temps. Bien souvent, le problme napparat que lorsque
vous avez dpens beaucoup dnergie saisir les donnes. Et quand vous
ralisez enfin que ce problme existe, il a gnralement pris une telle
ampleur que la seule solution est de reprendre zro la conception de la
base de donnes et la saisie de ces dernires. Le bon ct des choses est
que cela vous sert de leon en vous poussant construire une seconde
version de bien meilleure qualit que la premire
Chapitre 2
Les bases de SQL
DANS CE CHAPITRE :
Comprendre SQL.

Se dfaire de quelques ides prconues sur SQL.

Jeter un il sur les diffrents standards SQL.

Se familiariser avec les commandes communes de SQL et les mots rservs.

Reprsenter des nombres, des caractres, des dates, des heures et dautres
types de donnes.

Etudier les valeurs nulles et les contraintes.

Mettre SQL en marche sur un systme client/serveur.

SQL en rseau.

S
QL est un langage souple que vous pouvez utiliser de diffrentes
manires. Cest loutil le plus employ pour communiquer avec une base
de donnes relationnelle. Dans ce chapitre, jexpliquerai ce quest SQL
et ce quil nest pas, en le distinguant plus particulirement des autres
langages. Puis, je dcrirai les commandes et les types de donnes que SQL
supporte dans sa version standard avant de dvoiler quelques concepts
cls : les valeurs nulles et les contraintes. Enfin, je prsenterai rapidement
la place que SQL occupe dans un environnement client/serveur, ainsi que
sur Internet et sur des intranets.

Ce que SQL nest pas


La premire chose quil faut comprendre quand on parle de SQL est que ce
nest pas un langage procdural comme le Basic, le C, le C++, le C# et
Java. Pour rsoudre un problme laide dun de ces langages procduraux,
vous crivez une procdure qui effectue une opration spcifique, puis une
autre, et ce jusqu ce que la tche soit accomplie. La procdure peut tre
une squence linaire ou boucler sur elle-mme, mais dans les deux cas le
programmeur spcifie lordre dexcution.
SQL est non procdural. Pour rsoudre un problme avec SQL, vous lui
indiquez simplement ce que vous voulez ( lgal dAladin et de sa lampe
magique) au lieu dindiquer au systme comment rcuprer ce que vous
voulez. Le systme de gestion de bases de donnes (SGBD) dcide de la
meilleure manire dexaucer votre souhait.
Je viens de vous dire que SQL nest pas un langage procdural. Cest dans
lensemble vrai. Cependant, des millions de programmeurs sont habitus
rsoudre des problmes dune manire procdurale. Cest pourquoi il y a eu
ces dernires annes une pression considrable pour que de telles
fonctionnalits soient ajoutes SQL. Cest pourquoi ce langage comprend
aujourdhui des instructions qui se rattachent la programmation
procdurale telles que les blocs BEGIN, linstruction IF, les fonctions et
les procdures. Tout cela a t ajout de manire pouvoir stocker sur le
serveur des programmes utilisables par de multiples utilisateurs.
Pour illustrer ce que je veux dire par indiquer au systme ce que vous
voulez , supposez que vous disposiez dune table EMPLOYES et que vous
souhaitiez y rcuprer les lignes correspondant toutes les personnes
senior . Selon vous, un senior se dfinit comme quelquun dont lge
dpasse 40 ans ou qui gagne plus de 60 000 par an. Vous pouvez
rcuprer les informations que vous recherchez en utilisant la requte
suivante :

SELECT * FROM EMPLOYES WHERE AGE>40 OR


SALAIRE>600000 ;

Cette requte retourne toutes les lignes de la table EMPLOYES dans


lesquelles ou bien la valeur de la colonne AGE est suprieure 40 ou bien
la valeur de la colonne SALAIRE est suprieure 60 000 (ou bien les deux
la fois). En SQL, vous navez pas besoin de prciser comment
linformation doit tre rcupre. Le moteur de la base de donnes examine
la base et dcide par lui-mme de la manire de rpondre votre requte.
Vous navez besoin que de spcifier quelles donnes vous recherchez.
Une requte est une question que vous posez la base de donnes. Si une
donne contenue dans la base rpond aux conditions que vous formulez dans
votre requte, SQL vous renverra cette donne.

Les implmentations actuelles de SQL ne comportent pas la plupart des


constructions de base prsentes dans les autres langages de programmation.
Les applications du monde rel utilisent gnralement au moins quelques-
unes de ces constructions, cest pourquoi SQL est qualifi de sous-langage
de donnes. Mme avec les extensions ajoutes en 1999, 2003,
2005 et 2008, vous devrez utiliser SQL en combinaison avec un langage
procdural, tel que le C++, pour produire des applications compltes.
Vous pouvez extraire de linformation partir dune base de donnes de
deux manires :
En formulant une requte ad hoc depuis la console de
lordinateur en tapant les instructions SQL puis en
lisant le rsultat lcran. La console est le terme
traditionnellement utilis pour dsigner le matriel qui joue
le rle de clavier et dcran sur les systmes PC. Vous
pouvez formuler ainsi vos requtes si vous souhaitez
obtenir rapidement une rponse une question spcifique.
Vous navez jamais eu besoin dune certaine information et
vous nen aurez trs vraisemblablement plus jamais besoin.
Mais ce jour-ci, cette heure-ci, cest exactement ce quil
vous faut. Tapez la requte SQL approprie sur votre
clavier, et la rponse va safficher sur lcran en moins de
temps quil nen faut pour le dire.

En excutant un programme qui rcupre


linformation dans la base de donnes et produit un
rapport soit lcran, soit sur une imprimante. Ajouter
une requte directement dans votre programme est la
meilleure solution si cette requte est complexe et si vous
comptez lutiliser plusieurs fois. Vous navez ainsi la
formuler quune fois, puis y faire appel aussi souvent que
vous le voulez. Le Chapitre 16 vous explique comment
incorporer du code SQL dans des programmes crits dans
un autre langage.

Un (tout) petit peu dhistoire


SQL est n dans les laboratoires de recherche dIBM, tout comme la thorie
des bases de donnes relationnelles. Au dbut des annes 1970, alors que
les chercheurs dIBM travaillaient sur ce qui allait devenir les SGBD
relationnels (ou SGBDR), ils crrent un sous-langage de donnes pour
travailler sur ces systmes. Ils nommrent la premire version de ce langage
SEQUEL (Structure English QUEry Language ou Langage de requtes
structur). Cependant, quand vint le moment de distribuer ce langage sous la
forme dun produit, ils voulurent sassurer que les gens comprendraient en
quoi leur produit tait diffrent de toutes les prcdentes versions de
SGBD. Cest pourquoi ils dcidrent de donner au nouveau produit un nom
qui soit diffrent de SEQUEL, mais qui soit assimilable un produit de la
mme famille. Ils le nommrent donc SQL.
La syntaxe de SQL est une forme danglais structur, et cest de l quil tient
son nom. Toutefois, SQL nest pas un langage structur au sens o les
informaticiens lentendent. Cest pourquoi, en dpit de ce qui est rpandu,
SQL nest pas lacronyme de langage de requte structur . Cest
simplement une squence de trois lettres sans signification, comme le nom
du langage C qui ne signifie rien.
Les travaux dIBM sur les bases de donnes relationnelles et sur SQL
devinrent trs populaires dans lindustrie avant mme quIBM nintroduise
son SGBD SQL/DS en 1981. cette poque, Relational Software Inc.
(aujourdhui Oracle Corporation) avait dj distribu son premier SGBD.
peine ns, ces produits imposrent immdiatement un standard pour une
nouvelle classe de systmes de gestion de bases de donnes. Ils
incorporaient SQL, qui devint de facto le standard des sous-langages de
donnes. Les diteurs dautres systmes de gestion de bases de donnes
produisirent leurs propres versions de SQL. Ces versions comportaient
toutes les fonctionnalits des produits dIBM en y rajoutant des extensions
pour tirer le meilleur parti du SGBD sous-jacent. Puisque tous les diteurs
utilisaient une forme particulire de SQL, la compatibilit entre les
diffrents SGBD du march tait videmment faible.
Une implmentation est un SGBDR particulier qui fonctionne sur une plate-
forme matrielle spcifique.

Rapidement, un mouvement se cra pour raliser un standard


universellement reconnu de SQL auquel tous les diteurs pourraient adhrer.
En 1986, lANSI publia un standard formel nomm SQL-86. LANSI mit
jour son standard en 1989 (SQL-89) puis en 1992 (SQL-92). Chaque fois
que les diteurs de SGBDR sortaient de nouvelles versions de leurs
produits, ils tentaient de coller toujours plus ces spcifications. Cest
pourquoi, finalement, SQL est devenu un langage vritablement standard et
portable.
La dernire version complte du standard SQL est SQL:2011
(ISO/IEC 9075X : 2011). Dans ce livre, je traite de SQL comme le standard
SQL:2011 le dcrit. Toute implmentation spcifique de SQL scarte bien
entendu plus ou moins de ce standard. Mais les diteurs de logiciels tentent
de supporter un sous-ensemble essentiel et cohrent du langage SQL
standard. La version complte du standard ISO/IEC est propose la vente
sur http://webstore.ansi.org, mais vous ne souhaiterez sans
doute pas lacqurir moins que vous nentrepreniez de crer votre propre
systme de gestion de bases de donnes fond sur le standard. Le standard
est hautement technique, cest--dire virtuellement incomprhensible pour
qui na pas tudi les langages informatiques.

Les commandes SQL


Le langage SQL comporte un nombre limit de commandes qui sont
spcifiquement lies la manipulation des donnes. Quelques-unes de ces
commandes sont des fonctions de dfinition de donnes, dautres sont des
fonctions de manipulation de donnes, et dautres encore des fonctions de
contrle de donnes. Je traite des commandes de dfinition et de
manipulation de donnes dans les Chapitres 4 13 et des commandes de
contrle de donnes dans les Chapitres 14 et 15.
Pour se conformer au standard SQL:2011, une implmentation doit
comporter toutes les fonctionnalits de base. Elle peut aussi inclure
certaines des extensions ce noyau dur (comme le dcrit la spcification
SQL:2011). Le Tableau 2.1 liste les commandes de base de SQL:2011. Si
vous tes de ces programmeurs qui aiment essayer de nouvelles
fonctionnalits, rejoignez lquipe !
TABLEAU 2.1 Les commandes de SQL:2011.

ADD DEALLOCATE PREPARE FREE LOCATOR

ALLOCATE CURSOR DECLARE GET DESCRIPTOR


ALLOCATE DECLARE LOCAL GET DIAGNOSTICS
DESCRIPTOR TEMPORARY TABLE
ALTER DOMAIN DELETE GRANT PRIVILEGE

ALTER ROUTINE DESCRIBE INPUT GRANT ROLE


ALTER SEQUENCE DESCRIBE OUTPUT HOLD LOCATOR
GENERATOR

ALTER TABLE DISCONNECT INSERT

ALTER TRANSFORM DROP MERGE

ALTER TYPE DROP ASSERTION OPEN


CALL DROP ATTRIBUTE PREPARE

CLOSE DROP CAST RELEASE SAVEPOINT

COMMIT DROP CHARACTER SET RETURN

CONNECT DROP COLLATION REVOKE


CREATE DROP COLUMN ROLLBACK

CREATE DROP CONSTRAINT SAVEPOINT


ASSERTION

CREATE CAST DROP DEFAULT SELECT


CREATE DROP DOMAIN SET CATALOG
CHARACTER SET

CREATE DROP METHOD SET CONNECTION


COLLATION
CREATE DOMAIN DROP ORDERING SET CONSTRAINTS

CREATE FUNCTION DROP ROLE SET DESCRIPTOR

CREATE METHOD DROP ROUTINE SET NAMES


CREATE ORDERING DROP SCHEMA SET PATH

CREATE DROP SCOPE SET ROLE


PROCEDURE

CREATE ROLE DROP SEQUENCE SET SCHEMA

CREATE SCHEMA DROP TABLE SET SESSION


AUTHORIZATION

CREATE SEQUENCE DROP TRANSFORM SET SESSION


CHARACTERISTICS

CREATE TABLE DROP TRANSLATION SET SESSION


COLLATION

CREATE DROP TRIGGER SET TIME ZONE


TRANSFORM

CREATE DROP TYPE SET TRANSACTION


TRANSLATION

CREATE TRIGGER DROP VIEW SET TRANSFORM


GROUP

CREATE TYPE EXECUTE IMMEDIATE START TRANSACTION


CREATE VIEW FETCH UPDATE

DEALLOCATE
DESCRIPTOR

Les mots rservs


En plus de ces commandes, un certain nombre dautres mots ont une
signification particulire en SQL et sont rservs des usages spcifiques.
Vous ne pouvez donc pas les employer pour nommer des variables ou
toute autre fin. Vous comprendrez facilement pourquoi des tables, des
colonnes ou des variables ne peuvent porter des noms qui correspondent
des mots rservs. Imaginez quelle confusion une instruction telle que la
suivante pourrait induire :

SELECT SELECT FROM SELECT WHERE SELECT = WHERE ;

LAnnexe A contient une liste complte des mots rservs de SQL.

Les types de donnes


Diffrentes implmentations de SQL grent diffrents types de donnes. La
spcification SQL:2003 reconnat six types prdfinis gnraux :
Les numriques.

Les binaires.

Les chanes.

Les boolens.

Les dates/heures.

Les intervalles.

XML.

Chacun de ces types peut contenir plusieurs sous-types (les numriques


exacts, les numriques approximatifs, les chanes de caractres, les chanes
de bits, les chanes dobjets). En plus de ces types prdfinis, SQL gre les
collections, les constructions et les types dfinis par lutilisateur. Nous y
reviendrons plus loin dans ce chapitre.
Si vous utilisez une implmentation de SQL qui gre un ou plusieurs types
de donnes que la spcification SQL : ne mentionne pas, vous pouvez
rendre votre base de donnes plus portable en vitant dy recourir. Avant
que vous ne dcidiez de crer et dutiliser des types de donnes dfinis par
lutilisateur, assurez-vous que tous les SGBD que vous pourriez vouloir
grer lavenir supportent aussi ces types.

Les numriques exacts


Comme vous laurez probablement devin daprs leur nom, les types de
donnes numriques exacts vous permettent dexprimer exactement la valeur
dun nombre. Cinq types de donnes tombent dans cette catgorie :
INTEGER

SMALLINT

BIGINT

NUMERIC

DECIMAL

Le type de donnes INTEGER


Une donne de type INTEGER na pas de partie dcimale et sa prcision
dpend de chaque implmentation spcifique de SQL. En tant que
dveloppeur, vous ne pouvez donc pas spcifier la prcision que vous
souhaitez.
La prcision dun nombre est la quantit de bits sur laquelle ce nombre est
cod.

Le type de donnes SMALLINT


Le type de donnes SMALLINT sert aussi pour les entiers, mais la
prcision accorde SMALLINT sur une implmentation spcifique ne
peut dpasser celle de INTEGER sur cette mme version. Les
implmentations pour systmes IBM/370 reprsentent gnralement les
SMALLINT et les INTEGER respectivement laide de 16 et de 32 bits.
Bien souvent, les prcisions de SMALLINT et de INTEGER sont les
mmes.
Si vous dfinissez une colonne dune table de base de donnes comme tant
une donne entire et que vous savez que la plage des valeurs de la colonne
ne dpassera jamais la prcision du type de donnes SMALLINT pour
limplmentation que vous utilisez, vous pouvez alors utiliser ce type plutt
que INTEGER. Cela permettra votre SGBD dconomiser de la place.

Le type de donnes BIGINT


BIGINT se dfinit comme tant un type dont la prcision est au moins
aussi grande que INTEGER. Bien entendu, cette prcision dpend de
limplmentation.

Le type de donnes NUMERIC


Le type de donnes NUMERIC permet de reprsenter des nombres qui
comportent une partie dcimale. Vous pouvez spcifier et la prcision et
lchelle de la donne NUMERIC (rappelez-vous que la prcision est le
nombre maximal de bits possibles).
Lchelle dun nombre est la quantit de chiffres que comporte sa partie
dcimale. Lchelle dun nombre ne peut tre ni ngative ni plus grande que
la prcision de ce nombre.
Si vous spcifiez le type de donnes NUMERIC, votre implmentation de
SQL vous donnera exactement le nombre de bits et lchelle que vous
souhaitez. Vous pourriez spcifier simplement NUMERIC et utiliser
lchelle et la prcision par dfaut, ou NUMERIC (p) et dfinir alors la
prcision que vous demandez et lchelle par dfaut, ou encore NUMERIC
(p, e) et spcifier la prcision et lchelle que vous souhaitez. Les
paramtres p et e sont remplacer par les valeurs que vous souhaitez
utiliser.
Supposons par exemple que la prcision par dfaut du type de donnes
NUMERIC de votre implmentation de SQL soit 12 et que lchelle par
dfaut soit 6. Si vous assignez une colonne de la base de donnes le type
de donnes NUMERIC, la colonne pourra contenir des nombres dont la
valeur nexcdera pas 999 999,999999. Si vous spcifiez le type de
donnes NUMERIC (10) pour cette colonne, la colonne pourra contenir
des nombres dont la valeur ne dpassera pas 9 999,999999. Le paramtre
(10) spcifie la quantit maximale de chiffres possible dans le nombre.
Si vous spcifiez le type de donnes NUMERIC (10,2), cette colonne
pourra contenir des nombres dont la valeur nexcdera pas 99 999 999,99.
Dans ce cas vous disposez toujours de 10 chiffres mais deux seulement sont
ddis la partie dcimale.
Les donnes NUMERIC sont utiliser pour stocker des nombres tels
que 595,72. Cette valeur a une prcision de 5 (le nombre total de chiffres)
et une chelle de 2 (la quantit de chiffres qui se trouvent droite de la
virgule). Le type de donnes NUMERIC(5,2) permet de dfinir un tel
nombre.

Le type de donnes DECIMAL


Le type de donnes DECIMAL est semblable au type de donnes
NUMERIC. Il peut aussi disposer dune partie dcimale et vous pouvez
spcifier sa prcision et son chelle. La seule diffrence est que la
prcision que votre implmentation lui accorde peut tre plus grande que
celle que vous aurez spcifie. Dans ce cas, cest la plus grande prcision
qui sera utilise. Si vous ne spcifiez ni prcision ni chelle,
limplmentation utilise ses valeurs par dfaut, exactement comme elle le
fait pour le type NUMERIC.
Un lment que vous spcifiez comme tant un NUMERIC (5,2) ne peut
jamais contenir un nombre dont la valeur est suprieure 999,99. Une
dfinition telle que DECIMAL (5,2) permet toujours denregistrer des
nombres dont la valeur peut aller jusqu 999,99, mais aussi des nombres
plus grands encore si limplmentation le permet.
Utilisez le type NUMERIC ou DECIMAL si votre donne comporte une
partie dcimale, et choisissez les types SMALLINT et INTEGER si la
donne est un nombre entier. Adoptez le type NUMERIC si vous voulez
maximiser la portabilit, car une valeur dont vous dfinissez le type comme
NUMERIC (5,2) occupera exactement la mme place sur tous les
systmes.
Les numriques approximatifs
Certaines quantits peuvent prendre des valeurs dans une plage si grande
quun ordinateur offrant une taille denregistrement fixe ne pourrait
reprsenter ces valeurs exactement (cette taille peut tre par exemple
de 32 bits, 64 bits ou encore 128 bits). Lexactitude nest alors plus
ncessaire et une approximation devient acceptable. SQL dfinit trois types
de donnes numriques approximatifs pour traiter ce genre de valeur.

Le type de donnes REAL


Le type de donnes REAL vous permet de stocker des nombres virgule
flottante en simple prcision, cette dernire dpendant de limplmentation,
qui est elle-mme lie au matriel que vous utilisez. Par exemple, la
prcision est (videmment) plus importante sur une machine 64 bits que sur
un systme 32 bits.
Un nombre virgule flottante est un nombre qui comporte une partie
dcimale. La partie dcimale flotte , cest--dire quelle peut apparatre
nimporte quel endroit dans le nombre. 3,14 et 3,14159 sont des exemples
de nombres virgule flottante.

Le type de donnes DOUBLE PRECISION


Le type de donnes DOUBLE PRECISION vous permet de stocker un
nombre virgule flottante en double prcision, cette dernire dpendant
toujours de limplmentation. La signification du mot DOUBLE dpend
aussi de limplmentation (tonnant, non ?). Larithmtique en double
prcision est utilise par les scientifiques. Diffrentes disciplines
scientifiques ont divers besoins en terme de prcision. Certaines
implmentations de SQL sadressent plus une catgorie particulire
dutilisateurs, tandis que dautres sont destines un public diffrent.
Sur certains systmes, le type DOUBLE PRECISION occupe exactement
deux fois plus de place que le type REAL, tant pour la mantisse que pour
lexposant. (Vous pouvez reprsenter nimporte quel nombre sous forme
dune mantisse multiplie par dix lev la puissance de lexposant. Par
exemple, vous pouvez crire 6,626 sous la forme 6,626 E 3. Le
nombre 6,626 est la mantisse que vous multipliez par dix lev la
puissance de lexposant, cest--dire 3 dans cet exemple.)
Vous ne tirez aucun bnfice reprsenter des nombres dont les valeurs sont
trs proches les unes des autres (par exemple 6,626 et 6,626001) laide
dun type de donnes approximatif. Cependant, vous devez utiliser un type
de donnes approximatif pour stocker les nombres dont la valeur est proche
de zro ou bien plus grande que un tel que 6626 E -34 (un trs petit
nombre). Les types numriques exacts ne permettent pas de stocker de tels
nombres. Dautres systmes reprsentent le type DOUBLE PRECISION
laide dune mantisse deux fois plus grande et dun exposant presque deux
fois plus grand que la mantisse et lexposant du type REAL. Dautres
systmes encore reprsentent le type DOUBLE PRECISION laide
dune mantisse deux fois plus grande et dun exposant ayant la mme
capacit que le type REAL. La prcision est alors double, mais pas
lintervalle.
La spcification SQL nessaie pas darbitrer les dbats ou dimposer la
signification de DOUBLE PRECISION. Elle indique simplement que la
prcision dun nombre DOUBLE PRECISION doit tre plus grande que
celle dun REAL. Cette contrainte peut paratre quelque peu succincte, mais
elle tient compte de la grande diversit des matriels que lon peut
rencontrer et reprsente donc probablement le meilleur compromis
possible.

Le type de donnes FLOAT


Le type de donnes FLOAT est utiliser si vous pensez faire un jour
migrer votre base de donnes dune plate-forme matrielle vers une autre
dont la taille des registres est diffrente. Le type de donnes FLOAT vous
permet de spcifier la prcision, comme par exemple dans FLOAT (5).
Votre systme utilisera la simple prcision ou la double prcision suivant ce
que requiert ce que vous avez spcifi.
Utiliser le type FLOAT plutt que les types DECIMAL ou REAL facilite
le portage de votre base de donnes dun matriel un autre, car il vous
permet de spcifier la prcision. Les prcisions de DECIMAL et de
FLOAT dpendent pour leur part du matriel.
Si vous ntes pas certain du type numrique exact (NUMERIC/ DECIMAL)
ou du type numrique approximatif (FLOAT/REAL) que vous devez utiliser,
dfinissez toujours un type numrique exact. Les types de donnes
numriques exacts consomment moins de ressources systme et, comme il se
doit, permettent de stocker des valeurs exactes (plutt quapproximatives).
Vous devriez tre en mesure de dterminer lavance si la plage des
valeurs que peut prendre une donne est telle que vous navez dautre
solution que dutiliser un type de donnes numrique approximatif.

Les chanes de caractres


Les bases de donnes permettent aujourdhui de stocker des types de
donnes trs varis, dont des images, des sons et des animations. Bientt ce
sera peut-tre les odeurs. Quel plaisir si vous pouviez humer la pizza que
vous vous apprtez commander via Internet Mais, dans la vraie vie
daujourdhui, les types de donnes les plus utiliss sont les nombres et les
chanes de caractres.
Il existe trois principaux types de donnes caractres :
Les chanes de longueur fixe (CHARACTERou CHAR).

Les chanes de longueur variable (CHARACTER VARYING ou


VARCHAR).

Les objets larges de type caractre (CHARACTER LARGE


OBJECT ou CLOB).

Vous pouvez aussi disposer de trois variantes de ces types de donnes


caractres :
NATIONAL CHARACTER.

NATIONAL CHARACTER VARYING.

NATIONAL CHARACTER LARGE OBJECT.

Le type de donnes CHARACTER


Si vous dfinissez une colonne comme tant de type CHARACTER ou
CHAR, vous pourrez spcifier le nombre de caractres quelle contient en
utilisant la syntaxe CHARACTER(x), o x est la longueur de la chane.
Par exemple, si vous indiquez que le type de donnes dune colonne est
CHARACTER (16), la longueur maximale des donnes que vous pourrez y
saisir sera de 16 caractres. Si vous ne spcifiez aucun argument (cest--
dire, si vous ne fournissez aucune valeur la place de x), SQL supposera
que la longueur que vous souhaitez est de un (1) caractre.
Si vous saisissez une donne dans un champ CHARACTER dune longueur
spcifie, et que cette donne comporte moins de caractres que nen
prcise votre type, SQL remplira lespace restant laide de blancs.

Le type de donnes CHARACTER VARYING


Le type de donnes CHARACTER VARYING est utilis si la taille des
entres dune colonne peut varier, mais que vous ne voulez pas que SQL
complte les chanes laide despaces. Ce type vous permet donc de
stocker le nombre exact de caractres que lutilisateur aura saisis. Il
nexiste pas de valeur par dfaut pour ce type de donnes. Pour le dfinir,
utilisez la forme CHARACTER VARYING(x) ou VARCHAR(x), o x est le
nombre maximal de caractres que vous autorisez.

Le type de donnes CHARACTER LARGE


OBJECT
Le type de donnes CHARACTER LARGE OBJECT (CLOB) a t
introduit dans SQL:1999. Comme son nom le laisse entendre, il est utilis
pour stocker des chanes de caractres immenses, trop grandes pour le type
CHARACTER. Les CLOB ressemblent des chanes de caractres
classiques, mais leur utilisation est soumise un certain nombre de
restrictions.
Un CLOB ne peut tre utilis dans un prdicat PRIMARY KEY, FOREIGN
KEY ou UNIQUE. De plus, il ne peut tre utilis dans une comparaison
autre que lgalit ou lingalit. Parce quils sont trs grands, les
applications ne transfrent gnralement pas les CLOB dans une base de
donnes. Un client spcial nomm localisateur CLOB est utilis pour
manipuler les donnes CLOB. Cest un paramtre dont la valeur identifie un
objet large de type caractre.
Un prdicat est une commande qui peut tre soit vraie, soit fausse.

Les types de donnes NATIONAL


CHARACTER, NATIONAL CHARACTER
VARYING et NATIONAL CHARACTER LARGE
OBJECT
Certains langages utilisent des caractres qui leur sont spcifiques. Par
exemple, lallemand (comme dailleurs le franais) possde des caractres
spciaux qui nexistent pas en anglais. Quelques langages tels que le russe
utilisent un jeu de caractres totalement diffrent de langlais. Mme si
langlais est le jeu de caractres par dfaut de votre systme, vous pourrez
quand mme utiliser des jeux de caractres trangers, car les types de
donnes NATIONAL CHARACTER, NATIONAL CHARACTER
VARYING et NATIONAL CHARACTER LARGE OBJECT fonctionnent
comme les types de donnes CHARACTER, CHARACTER VARYING et
CHARACTER LARGE OBJECT, ceci prs que le jeu de caractres que
vous spcifiez peut tre diffrent du jeu de caractres dfini sur votre
systme. Il est possible de spcifier le jeu de caractres quand vous
dfinissez la colonne dune table. Si vous le voulez, SQL vous permet
dattribuer un jeu de caractres diffrent chaque colonne. Dans lexemple
suivant, nous crons une table qui utilise diffrents jeux de caractres :

CREATE TABLE TRADUCTION (


LANGAGE_1 CHARACTER (40),
LANGAGE_2 CHARACTER VARYING (40) CHARACTER SET
GREEK,
LANGAGE_3 NATIONAL CHARACTER (40),
LANGAGE_4 CHARACTER (40) CHARACTER SET KANJI
);
La colonne LANGAGE_1 contient des caractres du jeu de caractres par
dfaut de limplmentation. La colonne LANGAGE_3 correspond aux
caractres du jeu de caractres national de limplmentation. La colonne
LANGAGE_2 est destine contenir des caractres grecs. Et la colonne
LANGAGE_4 contiendra des caractres kanji. Aprs une longue absence,
les jeux de caractres asiatiques, tels que le kanji, sont de nouveau prsents
dans les SGBD.

Les chanes binaires


Les types de donnes chanes BINARY ont t introduits dans SQL:2008.
Comme les donnes binaires sont fondamentales depuis lordinateur
Atanasoff-Berry des annes 1930, cette reconnaissance de leur importance
semble assez tardive dans SQL (mais mieux vaut tard que jamais, je
suppose). Il existe trois diffrents types de donnes binaires : BINARY,
BINARY VARYING, et BINARY LARGE OBJECT.

Le type de donnes BINARY


Si vous dfinissez le type de donnes dune colonne comme BINARY, vous
pourrez spcifier le nombre doctets que la colonne peut contenir en
utilisant la syntaxe BINARY(x), o x est le nombre en question. Par
exemple, si vous spcifiez BINARY (16), la chane binaire peut
comprendre 16 octets. Les donnes binaires doivent tre saisies octet par
octet, en commenant par le premier octet.

Le type de donnes BINARY VARYING


Utilisez le type BINARY VARYING lorsque la longueur de la chane est
variable. Pour spcifier ce type de donnes, utilisez la forme BINARY
VARYING(x) ou VARBINARY(x), o x est le nombre maximum
doctets permis. La taille minimale de la chane binaire est zro et sa taille
maximale est x.

Le type de donnes BINARY LARGE OBJECT


Le type de donnes BINARY LARGE OBJECT (BLOB) est utilis pour
dnormes chanes binaires qui sont trop grandes pour le type BINARY. Les
fichiers dimages et de musiques sont des exemples. Les BLOBs se
comportent beaucoup comme des chanes binaires, mais SQL impose un
certain nombre de restrictions leur manipulation.
En particulier, vous ne pouvez pas utiliser un BLOB comme prdicat
PRIMARY KEY, FOREIGN KEY ou UNIQUE. De plus, il est impossible
de comparer des BLOBs autrement que pour lgalit ou lingalit. Les
BLOBs sont normes, si bien que les applications ne les transfrent pas
dune base de donnes. Elles utilisent un type de donnes client particulier
nomm localisateur de BLOB pour manipuler les donnes dun BLOB. Ce
localisateur est un paramtre dont la valeur identifier le gros objet binaire.

Les boolens
Le type de donnes BOOLEAN comprend les valeurs vrai (true), faux
(false) et inconnu (unknown). Si un boolen dont la valeur est vrai ou
faux est compar NULL ou la valeur inconnu, le rsultat sera la valeur
inconnu.

Les dates et les heures


Le standard SQL dfinit cinq types de donnes diffrents pour grer les
dates et les heures. Cependant ces types se recoupent tant les uns les autres
que certaines implmentations ne les grent pas tous.
Les implmentations qui ne supportent pas les cinq types de donnes pour
les dates et les heures peuvent vous poser des problmes si vous tentez de
migrer vos bases de donnes sur un autre systme. Si cela arrive, vrifiez
que les implmentations source et destination reprsentent les dates et les
heures de la mme manire.

Le type de donnes DATE


Le type de donnes DATE mmorise lanne, le mois et le jour, dans cet
ordre. Lanne est un nombre de quatre chiffres, le mois et le jour sont des
nombres deux chiffres. Une valeur DATE peut reprsenter nimporte
quelle date depuis lanne 0001 jusqu lanne 9999. La longueur de
DATE est de 10 positions, comme dans 1957-08-14.

Le type de donnes TIME WITHOUT TIME


ZONE
Le type de donnes TIME WITHOUT TIME ZONE mmorise les heures,
les minutes et les secondes. Les heures et les minutes utilisent chacune deux
chiffres. Les secondes peuvent occuper deux chiffres, mais elles peuvent
aussi comporter une partie dcimale. Il est donc possible de
reprsenter 9 heures 32 minutes et 58,436 secondes sous la forme 09 : 32 :
58.436.
La prcision de la partie dcimale dpend de limplmentation, mais elle
est dau moins six chiffres. Une valeur TIME WITHOUT TIME ZONE
occupe huit positions (en comprenant les deux-points) quand la valeur na
aucune partie dcimale ou neuf positions (en comprenant le sparateur
dcimal) plus la taille de la partie dcimale quand la valeur en comporte
une. Vous pouvez spcifier le type de donnes TIME WITHOUT TIME
ZONE comme TIME, ce qui correspond une heure sans partie dcimale,
ou comme TIME WITHOUT TIME ZONE (p), o p est le nombre de
chiffres quoccupe la partie dcimale. Dans lexemple prcdent, le type de
donnes utilis est TIME WITHOUT TIME ZONE (3).

Le type de donnes TIMESTAMP WITHOUT


TIME ZONE
Le type de donnes TIMESTAMP WITHOUT TIME ZONE stocke la date
et lheure. Les longueurs ainsi que les restrictions appliques aux valeurs
des donnes TIMESTAMP WITHOUT TIME ZONE sont les mmes que
pour DATE et TIME WITHOUT TIME ZONE, une diffrence prs : la
longueur par dfaut de la partie dcimale de lheure dune TIMESTAMP
WITHOUT TIME ZONE est de six chiffres et non de zro.

Si la valeur na pas de partie dcimale, la longueur de TIMESTAMP


WITHOUT TIME ZONE est de 19 positions : dix positions pour la date,
un espace qui tient lieu de sparateur et huit positions, dans cet ordre. Si la
valeur a une partie dcimale (six chiffres par dfaut), la longueur est
de 20 positions plus le nombre de chiffres de la partie dcimale. La
vingtime position est occupe par le sparateur dcimal. Vous spcifiez le
type dun champ comme TIMESTAMP WITHOUT TIME ZONE en
utilisant soit TIMESTAMP WITHOUT TIME ZONE soit TIMESTAMP
WITHOUT TIME ZONE (p), o p est le nombre de chiffres de la partie
dcimale. La valeur de p ne peut tre ngative, et limplmentation
dtermine sa valeur maximale.

Le type de donnes TIME WITH TIME ZONE


Le type de donnes TIME WITH TIME ZONE est identique au type
TIME WITHOUT TIME ZONE, ceci prs quil contient une information
supplmentaire : un dcalage horaire par rapport au temps universel
(autrement dit par rapport au mridien de Greenwich ou GMT). La valeur
de ce dcalage peut aller de 12 : 59 + 13 : 00. Cette information
supplmentaire occupe six positions aprs le temps : un sparateur, un signe
plus ou moins, puis le dcalage en heures (deux chiffres) et en minutes
(deux chiffres) spares par un deux-points. Une valeur TIME WITH
TIME ZONE sans partie dcimale (par dfaut) occupe 14 positions. Si
vous spcifiez une partie dcimale, la longueur est de 15 positions plus le
nombre de chiffres que vous aurez allou cette partie dcimale.

Le type de donnes TIMESTAMP WITH


TIME ZONE
Le type de donnes TIMESTAMP WITH TIME ZONE fonctionne
exactement comme le type TIMESTAMP WITHOUT TIME ZONE, ceci
prs quil contient lui aussi un dcalage horaire. Cette information
supplmentaire occupe six positions. La longueur totale dune TIMESTAMP
WITH TIME ZONE passe donc 25 positions sans partie dcimale et
26 positions plus le nombre de chiffres allous la partie dcimale si elle
en comporte.

Les intervalles
Les types de donnes intervalles sont apparents aux types de donnes date
et heure. Un intervalle est la diffrence entre deux valeurs date et heure.
Dans de nombreuses applications qui manipulent des dates, des heures ou
les deux la fois, vous avez parfois besoin de dterminer lintervalle qui
spare deux dates ou deux heures.
SQL reconnat deux types distincts dintervalles : anne-mois et jour-heure.
Le premier reprsente lcart en annes et mois entre deux dates. Le second
correspond la diffrence en jours, heures, minutes et secondes entre deux
instants dun mme mois. Il nest pas possible de mlanger les deux dans un
calcul, car la longueur des mois varie (28, 29, 30 ou 31 jours).

Le type XML
Le type de donnes prdfini XML est le petit dernier de la famille. Les
donnes XML ont une structure arborescente, ce qui signifie quun nud
racine peut avoir plusieurs nuds enfants, chacun tant son tour
susceptible de possder sa propre descendance. Introduit dans SQL:2003,
le type XML a t enrichi dans SQL/XML : 2005. Ldition 2005 dfinit
cinq sous-types paramtrs en plus du type dorigine. Les valeurs XML
peuvent tre des instances de deux ou plusieurs types, car certains sous-
types sont eux-mmes des sous-types dautres sous-types (peut-tre
faudrait-il les dsigner par sous-sous-types, voire sous-sous-sous-types ;
fort heureusement, SQL:2008 dfinit un standard pour se rfrer aux sous-
types).
Les modificateurs primaires du type XML sont SEQUENCE, CONTENT et
DOCUMENT. Les modificateurs secondaires sont UNTYPED, ANY et
XMLSCHEMA. La Figure 2.1 montre la structure arborescente qui illustre les
relations entre les sous-types.
FIGURE 2.1 Les relations entre les sous-types XML.

Voyons brivement les types XML que vous vous devez de connatre.
Commenons par les types de base pour terminer par les plus complexes :
XML(SEQUENCE) : Toute valeur XML est soit une valeur
SQL NULL, soit une squence XQuery. De cette manire,
chaque valeur XML est une instance du type
XML(SEQUENCE). XQuery est un langage de requte
spcifiquement conu pour extraire des informations
partir de donnes XML. Il sagit du type XML le plus basique.

XML(SEQUENCE) est le moins restrictif des types XML. Il


peut accepter des valeurs qui ne respectent pas totalement
les canons XML. Les autres types sont, quant eux,
sensiblement moins conciliants.

XML(CONTENT(ANY)) : Il sagit dun type lgrement plus


restrictif que XML(SEQUENCE). Chaque valeur XML qui est
soit un NULL, soit un nud de document XQuery (ou un
enfant de ce nud) est une instance de ce type. Toute
instance de XML(CONTENT(ANY)) est galement une
instance de XML(SEQUENCE). Les valeurs du type
XML(CONTENT(ANY)) ne sont pas ncessairement
conformes aux canons XML. Il peut sagir des rsultats
intermdiaires dune requte qui seront par la suite remis
en bonne et due forme.

XML(CONTENT(UNTYPED)) : Ce type est encore plus


restrictif que le prcdent. Par consquent, toute valeur du
type XML(CONTENT(UNTYPED)) est aussi une instance
des types XML(CONTENT(ANY)) et XML(SEQUENCE).
Toute valeur XML qui est soit la valeur nulle, soit une valeur
non nulle de type XML(CONTENT(ANY)), est un nud dun
document XQuery D, tel que ce qui suit est vrai pour tout
nud lment contenu dans larbre T dont la racine est D :

La proprit type-name est xdt : untyped.

La proprit nilled est False.

Pour tout nud attribut contenu dans T, la


proprit name est xdt : untypedAtomic.

Pour tout nud attribut contenu dans T, la


proprit type est une valeur de type
XML(CONTENT(UNTYPED)).

XML- (CONTENT(XMLSCHEMA)) : Cest le second sous-


type de XML(CONTENT(ANY)) avec
XML(CONTENT(UNTYPED)). Toute valeur XML qui est soit la
valeur nulle, soit une valeur non nulle de type
XML(CONTENT(ANY)) est aussi un nud dun document
XQuery D, tel que tout nud lment contenu dans larbre
T de racine D :

Est valide conformment au schma XML S, ou


Est valide conformment lespace de noms N dans
le schma S, ou

Est valide conformment la dclaration de


schma E dans un schma XML S, ou

Est une valeur de type


XML(CONTENT(XMLSCHEMA)), dont le descripteur de
type comprend celui du schma S et, si N est
spcifi, lURI de lespace de noms de N, ou si E est
spcifi, lURI de lespace de noms de E et le NCName
de E.

XML(DOCUMENT(ANY)) : Il sagit dune autre variante du


type XML(CONTENT(ANY)) avec une restriction
supplmentaire : une instance de XML(DOCUMENT(ANY))
est un nud de document possdant exactement un
lment enfant, zro ou plusieurs nuds commentaires, et
zro ou plusieurs nuds dinstructions de traitement
XQuery.

XML(DOCUMENT(UNTYPED)) : Chaque valeur qui est soit


la valeur NULL, soit une valeur non nulle de type
XML(CONTENT(UNTYPED)) qui se trouve dans un nud
document dont la proprit children comprend
exactement un nud lment, zro ou plusieurs nuds
commentaires, et zro ou plusieurs instructions de
traitement XQuery, est une valeur de type
XML(DOCUMENT(UNTYPED)). Toutes les instances de
XML(DOCUMENT(UNTYPED)) sont galement des
instances du type XML(CONTENT(UNTYPED)). Ce sont
galement des instances du type XML(DOCUMENT(ANY)).
XML(DOCUMENT(UNTYPED)) est le plus restrictif de tous
les sous-types. En dautres termes, les restrictions des
autres sous-types sappliquent galement lui. Tout
document qualifi comme tant un
XML(DOCUMENT(UNTYPED)) est aussi une instance de
tous les autres sous-types XML.

Les types ROW


Le type de donnes ROW a t introduit dans SQL:1999. Il nest pas trs
facile de comprendre son usage, et il se peut quen tant quutilisateur novice
ou intermdiaire de SQL vous nayez jamais vous en servir. Aprs tout,
les gens sen sont bien passs entre 1986 et 1999.
Une des principales caractristiques du type de donnes ROW est quil
viole les rgles de normalisation nonces par E.F. Codd laube des bases
de donnes relationnelles. Je reviendrai sur ces rgles dans le Chapitre 5.
Lune des caractristiques de la premire forme normale est quun champ
dune ligne dune table ne peut contenir plusieurs valeurs. Un champ doit
donc recevoir une et une seule valeur. Cependant, le type de donnes ROW
vous permet de dclarer quune ligne de donnes tout entire sera contenue
dans un seul champ dune seule ligne. En dautres termes, il est possible
dinsrer une ligne dans une ligne.
Les formes normales, selon le Dr Codd, dfinissent les caractristiques des
bases de donnes relationnelles. Linclusion du type ROW dans le standard
SQL a t la premire tentative dextension du modle relationnel pur.
Considrez linstruction SQL suivante, qui dclare ladresse dune personne
sous la forme dun type ROW :

CREATE ROW TYPE type_adresse (


Rue CHARACTER VARYING (25)
Ville CHARACTER VARYING(20)
Etat CHARACTER (2)
Code_Postal CHARACTER VARYING (9)
);
Une fois dfini, le nouveau type ROW peut tre utilis dans la dfinition
dune table :

CREATSSSE TABLE CLIENTS (


ClientID INTEGER PRIMARY KEY,
Prnom CHARACTER VARYING (25),
Nom CHARACTER VARYING (20),
Adresse type_adresse
Tlphone CHARACTER VARYING (15)
);

Tout lintrt est ici de pouvoir dfinir une et une seule fois ce quest une
adresse et de pouvoir rutiliser cette dfinition dans la dclaration de
diverses tables : table de clients, table des employs, etc.

Les types Collection


Une fois le processus de transgression des rgles intangibles de SQL entam
avec SQL:1999, la dfinition de types violant la premire forme normale
est devenue possible. Un champ peut donc ds lors contenir une pleine
collection dobjets et non plus une seule et unique entit. Le type ARRAY a
t introduit avec SQL:1999, et le type MULTISET a t ajout dans
SQL:2003.
Deux collections ne peuvent tre compares que si elles ont le mme type
(soit ARRAY, soit MULTISET) et si les types de leurs lments sont
comparables. Du fait que les tableaux comportent un nombre dfini
dentres, il est possible de comparer les lments correspondants. Ce nest
pas le cas des MULTISET, mais la comparaison reste faisable si (a) une
numration existe pour chaque multiset concern, et si (b) les numrations
peuvent tre apparies.

Le type ARRAY
Comme le type ROW, le type de donnes ARRAY viole lui aussi la
premire forme normale (1NF), mais dune manire diffrente. Le type
ARRAY est une collection, pas un type distinct comme le sont les types
CHARACTER ou NUMERIC. Pour lessentiel, un type ARRAY permet un
autre type de prendre plusieurs valeurs qui seront mmorises dans un seul
champ dune table.
Supposons par exemple que votre entreprise dsire pouvoir contacter ses
clients tout instant, quils soient au travail, leur domicile ou sur la route.
Vous souhaiteriez donc stocker plusieurs numros de tlphone pour chaque
personne. Vous pouvez le faire en dclarant lattribut Tlphone sous la
forme dun tableau de la manire suivante :

CREATE TABLE CLIENTS (


ClientID INTEGER PRIMARY KEY,

Nom CHARACTER VARYING (25),


Prnom CHARACTER VARYING (20),
Adresse type_adresse
Tlphone CHARACTER VARYING (15)
);

La notation ARRAY[3] vous permet de stocker jusqu trois numros de


tlphone dans la table CLIENTS. Ce type de donnes enfreint les
restrictions imposes par le Dr Codd quand il nona les rgles de
normalisation en prfrant lintgrit des donnes la flexibilit de leur
gestion. SQL:1999 a rendu la gestion des donnes plus souple mais rend
aussi leur structure plus complexe.
Plus la structure devient complexe, plus vous devez prendre garde que son
utilisation remette en cause lintgrit de votre base de donnes. Il est
ncessaire de mesurer avec prcision les effets de chaque action que vous
effectuez sur votre base de donnes. Un tableau est ordonn dans le sens o
chacun de ses lments est associ avec exactement une position ordinale
dans ledit tableau.
Si la cardinalit dun tableau est infrieure au maximum dclar, les
cellules inutilises dans le tableau sont considres comme inexistantes.
Elles ne sont pas considre comme contentant des valeurs nulles ; elles
nexistent tout simplement pas.
Vous pouvez accder aux lments spcifiques dun tableau en faisant
figurer leur index entre crochets. Si vous avez un tableau nomm Tlphone,
alors Tlphone[3] vous permet de vous rfrer au troisime lment
figurant dans ce tableau.
Depuis SQL:1999, il est possible de trouver la cardinalit dun tableau en
invoquant la fonction CARDINALITY. Depuis SQL:2011, vous pouvez
dcouvrir la cardinalit maximale dun tableau en utilisant la fonction
ARRAY_MAX_CARDINALITY. Cette fonction est trs utile, car elle vous
permet dcrire des routines de porte gnrale qui sappliquent des
tableaux de cardinalits maximales diffrentes. Les routines o la
cardinalit maximale est code en dur ne sappliquent quaux tableaux de la
cardinalit maximale correspondante, et doivent donc tre rcrites pour
sappliquer des tableaux de cardinalits maximales diffrentes.
Alors que SQL:1999 a introduit le type de donnes ARRAY et la possibilit
dadresser les lments spcifiques dun tableau, rien na t prvu pour
supprimer des lments du tableau. Cet oubli a t corrig dans
SQL:2011 avec lintroduction de la fonction TRIM_ARRAY, qui vous
permet de supprimer des lments la fin dun tableau.

Le type MULTISET
Un multiset est une collection non ordonne. Des lments spcifiques du
multiset peuvent ne pas tre rfrencs, car ils ne sont affects aucune
position ordinale particulire.

Les types REF


Les types REF ne font pas partie du noyau de SQL. Cela signifie quun
SGBD peut se proclamer compatible avec le standard SQL sans
implmenter les types REF. Il ne sagit pas dun type de donnes distinct
comme le sont CHARACTER et NUMERIC. Cest un pointeur vers une
donne, un type de donnes ou un type de donnes abstrait qui rside dans
une ligne dune table (un site). Drfrencer le pointeur permet de retrouver
la valeur stocke dans le site cible.
Si vous ny comprenez rien, ne vous inquitez pas, car vous ntes pas le
seul. Lutilisation des types REF requiert une connaissance avance des
principes de la programmation oriente objet. Ce livre se gardera bien de
plonger dans les arcanes de ce sujet. En fait, puisque les types REF ne font
pas partie du cur de SQL, vous feriez mieux de vous en passer. Si vous
souhaitez rester compatible avec un maximum de plates-formes de SGBD,
tenez-vous-en aux fonctionnalits du noyau de SQL.

Les types dfinis par lutilisateur


Les types dfinis par lutilisateur (UDT, pour User-Defined Types) ont t
introduits avec SQL:1999. Ils viennent du monde de la programmation
oriente objet (POO). En tant que programmeur SQL, vous ntes plus
limit par les types de donnes dfinis dans la spcification standard. Vous
pouvez dfinir vos propres types de donnes en vous basant sur les
principes des types de donnes abstraites (ADT, pour Abstract Data Types)
courants dans les langages orients objet tels que le C++.
Lun des principaux intrts des UDT est quils peuvent tre utiliss pour
grer le problme de compatibilit entre SQL et le langage emball
autour de SQL. Un problme rcurrent de SQL est que ses types de donnes
prdfinis ne sont pas forcment les mmes que ceux employs par les
langages dans lesquels des instructions SQL sont intgres. Grce aux UDT,
le programmeur dune base de donnes peut crer dans SQL des types de
donnes qui correspondent exactement aux types du langage quil utilise.
Un UDT encapsule des attributs et des mthodes. Le monde extrieur voit
les attributs et les rsultats produits par les mthodes, mais
limplmentation spcifique de ces mthodes lui est cache. Il est possible
dimposer des restrictions sur laccs aux attributs et aux mthodes dun
UDT en spcifiant quils sont publics, privs ou protgs.
Les attributs (ou les mthodes) publics sont accessibles
tous les utilisateurs de lUDT.

Les attributs (ou les mthodes) privs ne sont


accessibles qu lUDT lui-mme.

Les attributs (ou les mthodes) protgs ne sont


accessibles qu lUDT lui-mme ou ses types drivs.

Vous voyez quun UDT de SQL se comporte pour lessentiel comme une
classe dans un langage de programmation orient objet. Il existe deux
formes de types dfinis par lutilisateur : les types distincts et les types
structurs.

Les types distincts


Les types distincts sont les plus lmentaires des types dfinis par
lutilisateur. Ils prennent la forme dun type de donne unique et sont
construits partir dun des types prdfinis (appels dans ce cas types
source). Plusieurs types distincts qui sont tous bass sur un mme type
source sont diffrents les uns des autres et ne sont donc pas directement
comparables. Par exemple, vous pouvez utiliser des types distincts pour
reprsenter diverses monnaies :

CREATE DISTINCT TYPE DollarUS AS DECIMAL (9,2);

cre un nouveau type de donnes pour les dollars, bas sur le type prdfini
DECIMAL. Vous pouvez ensuite ajouter un autre type distinct de la manire
suivante :

CREATE DISTINCT TYPE Euro AS DECIMAL (9,2);

Il est maintenant possible de dfinir des tables qui utilisent ces types :

CREATE TABLE FactureUS (


FacID INTEGER PRIMARY KEY,

ClientID INTEGER,
EmpID INTEGER,
TotalVente DollarUS,
Taxe DollarUS,
Port DollarUS,
GrandTotal DollarUS
);

CREATE TABLE FactureEuro (


FacID INTEGER PRIMARY KEY,
ClientID INTEGER,
EmpID INTEGER,
TotalVente Euro,
Taxe Euro,
Port Euro,
GrandTotal Euro
);

Le type DollarUS et le type Euros sont tous les deux bass sur le type
DECIMAL, mais leurs instances ne peuvent tre directement compares
entre elles ni avec des instances du type DECIMAL. Dans la ralit, il est
possible de convertir en SQL des dollars US en euros laide dun
oprateur spcial (CAST). Une fois la conversion effectue, la comparaison
devient possible.

Types structurs
La seconde forme de type dfini par lutilisation (le type structur) est
exprime laide dune liste dattributs et de mthodes au lieu dtre base
sur un unique type source prdfini.

Constructeurs
Lorsque vous crez un UDT structur, le SGBD lui associe automatiquement
une fonction dite constructeur qui prend le mme nom que cet UDT. Le
travail du constructeur consiste initialiser les attributs de lUDT leur
valeur par dfaut.

Mutateurs et accesseurs
Toujours lors de la cration dun UDT structur, le SGBD ajoute tout aussi
automatiquement deux autres fonctions : un mutateur et un accesseur. Un
mutateur, lorsquil est invoqu, change la valeur dun attribut du type
structur correspondant. linverse, un accesseur sert retrouver la valeur
dun attribut dans un type structur. Vous pouvez inclure des accesseurs dans
des instructions SELECT afin de rcuprer des valeurs dans une base de
donnes.
Sous-types et supertypes
Il peut exister une relation hirarchique entre deux types structurs. Prenons
un exemple. Un type appel MusiqueCDudt possde un sous-type
dnomm RockCDudt et un autre dnomm ClassiqueCDudt. Par rapport
ces deux styles musicaux, MusiqueCDudt est leur supertype. RockCDudt
est un sous-type propre de MusiqueCDudt sil nexiste aucun
intermdiaire entre eux, autrement dit quelque chose qui soit la fois sous-
type de MusiqueCDudt et supertype de RockCDudt. Si, maintenant, on cre
un sous-type de RockCDudt appel HeavyMetalCDudt, ce dernier
sera par hritage un sous-type de MusiqueCDudt, mais pas un sous-type
propre. Vous suivez toujours ?
Exemple de type structur
Vous pouvez crer des UDT structurs de la manire suivante :

/* Cre un UDT appel MusiqueCDudt */


CREATE TYPE MusiqueCDudt AS
/* Spcifie les attributs */
Titre CHAR(40),
Cout DECIMAL(9,2),
PrixConseille DECIMAL(9,2),
/* Les sous-types sont autoriss */
NOT FINAL ;

CREATE TYPE RockCDudt UNDER MusiqueCDudt NOT


FINAL;

Le sous-type RockCDudt hrite des attributs du supertype


MusiqueCDudt.

CREATE TYPE HeavyMetalCDudt UNDER RockCDudt


FINAL;

Maintenant que vous avez les types, il est possible de crer les tables qui
les utilisent. Par exemple :

CREATE TABLE METALSKU (


Album HeavyMetalCDudt,
SKU INTEGER);

Il ny a plus qu ajouter des lignes la table :

BEGIN
/* Dclare une variable temporaire a */
DECLARE a = HeavyMetalCDudt ;
/* Excute la fonction constructeur */
SET a = HeavyMetalCDidt() ;
/* Excute la premire fonction mutateur */
SET a = a.Titre(Edouard the Great) ;
/* Excute la deuxime fonction mutateur */
SET a = a.Cout(7.5) ;
/* Excute la troisime fonction mutateur */
SET a = a.PrixConseille(15.99) ;

INSERT INTO METALSKU VALUES (a, 31415926);


END

Les types dfinis par lutilisateur pour les


types Collection
Dans la section prcdente Types distincts , je vous ai montr comme
crer un type dfini par lutilisateur partir dun type prdfini, en utilisant
lexemple de la cration du type USDollar partir du type Euros. Cette
possibilit a t introduite dans SQL:1999. SQL:2011 ltend en vous
permettant de crer un nouveau type dfini par lutilisateur partir dun
type Collection. Cela permet au dveloppeur de dfinir des mthodes
sappliquant un tableau comme un tout, et non plus chacun de ses
lments, comme limposait SQL:1999.

Liste des types de donnes


Le Tableau 2.2 contient la liste des divers types de donnes, chacun tant
accompagn dun exemple.

TABLEAU 2.2 Les types de donnes.

Type de donnes Exemple


CHARACTER (20) Radio Amateur

VARCHAR (20) Radio Amateur

CLOB (1000000) Cette chane de caractres fait un


million de caractres
SMALLINT, BIGINT 7500
ou INTEGER

NUMERIC ou 3425.432
DECIMAL

REAL, FLOAT ou 6.626E-34


DOUBLE PRECISION

BLOB (1000000) 1001001110101011010101010101

BOOLEAN true
DATE DATE 1957-08-14

TIME (2) WITHOUT TIME 12 : 46 : 02.43 WITHOUT TIME


TIME ZONE1 ZONE

TIME (3) WITH TIME 12 : 46 : 02.432-08 : 00


TIME ZONE WITH TIME ZONE

TIMESTAMP WITHOUT TIMESTAMP 1957-08-14 12 : 46 : 02


TIME ZONE (0) WITHOUT TIME ZONE
TIMESTAMP

Type de donnes Exemple


TIMESTAMP WITH TIMESTAMP 1957-08-14 12 : 46 : 02-
TIME ZONE (0) 08 : 00 WITH TIME ZONE
TIMESTAMP

INTERVAL DAY INTERVAL 4 DAY


XML(SEQUENCE) <Client>Allen G. Taylor</Client>

ROW ROW (Rue VARCHAR (25), Ville


VARCHAR (20), Etat CHAR (2), Code_
Postal VARCHAR (9))
ARRAY INTEGER ARRAY [15]

MULTISET Aucun littral ne sapplique au type MULTISET

REF Pas un type mais un pointeur


USER DEFINED TYPE Type de monnaie bas sur DECIMAL

Largument spcifie le nombre de chiffres de la partie dcimale.

Votre implmentation spcifique de SQL peut ne pas supporter tous les types
de donnes qui viennent dtre dcrits dans cette section. De plus, il est
possible que votre implmentation utilise des types de donnes non standard
que je ne dcris pas ici.

Les valeurs nulles


Si un champ dune base de donnes contient une donne, ce champ a une
valeur spcifique. Un champ qui ne contient aucune donne est dit avoir une
valeur nulle (NULL). Noubliez pas que :
Dans un champ numrique, une valeur nulle na pas la
mme signification que zro.

Dans un champ caractre, une valeur nulle nest pas un


caractre espace.
Le zro numrique et le caractre espace sont des valeurs dfinies. Une
valeur nulle indique que la valeur du champ nest pas dtermine.
Un champ peut prendre une valeur nulle dans de nombreux cas. Voici
quelques exemples :
La valeur existe mais vous ne la connaissez pas
encore. Vous passez MASSE nul dans la ligne Top de la
table QUARK avant que la masse du quark ne soit
dtermine.

La valeur nexiste pas encore. Vous dfinissez TOTAL_


VENDU comme tant nul dans la ligne SQL pour Les Nuls
de la table LIVRES, car vous ne savez pas encore combien
dexemplaires ont t vendus.

Le champ nest pas utilisable pour cette ligne


particulire. Vous affectez SEXE une valeur nulle dans la
range Z6PO de la table EMPLOYES, car Z6PO est un
drode.

La valeur est hors de porte. Vous attribuez la valeur


nulle RICHESSE dans la range BILL GATES de la table
FORTUNES, car le maximum possible de 999 999 999 euros
est largement dpass.

Un champ peut prendre une valeur nulle pour de nombreuses raisons. Ne


tirez pas des conclusions htives sur la signification dune valeur nulle.

Les contraintes
Les contraintes sont des restrictions que vous appliquez sur les donnes que
quelquun peut saisir dans la base de donnes. Par exemple, si les entres
dune certaine colonne numrique doivent appartenir une certaine plage de
valeurs. Si quelquun tente de saisir une valeur qui nappartient pas cet
intervalle, la base de donnes risque dtre contamine. Vous pouvez
prvenir cette nuisance en appliquant une contrainte de plage la colonne.
Gnralement, un programme qui utilise une base de donnes applique des
contraintes cette base. Cependant, les SGBD les plus rcents vous
permettent dimposer directement des contraintes vos bases. Cela prsente
plusieurs avantages. Si plusieurs applications utilisent la mme base de
donnes, vous naurez appliquer les contraintes quune seule fois. De
plus, ajouter des contraintes au niveau de la base de donnes est toujours
plus simple que de les intgrer dans une application. Dans de nombreux cas,
il suffit dajouter une clause votre instruction CREATE.
Je dcrirai en dtail les contraintes et les assertions (qui sont des
contraintes que vous appliquez plusieurs tables) dans le Chapitre 5.

Utiliser SQL sur un systme


client/serveur
SQL est un sous-langage de donnes qui fonctionne sur un systme isol ou
sur un systme multi-utilisateur. SQL est particulirement efficace sur les
systmes client/serveur. Sur de tels systmes, les utilisateurs de plusieurs
machines clients qui se connectent la machine serveur peuvent accder
une base de donnes au travers dun rseau local (LAN) ou de tout autre
moyen de communication. Le programme qui fonctionne sur la machine
client contient les commandes SQL de manipulation de donnes. La portion
du SGBD qui rside ct client envoie les commandes au serveur via le
moyen de communication qui les relie. Sur lautre versant, la portion
serveur du SGBD interprte et excute les commandes SQL, puis renvoie
les rsultats au client. Vous pouvez encoder des oprations trs complexes
en SQL sur le client, puis les faire dcoder et excuter sur le serveur. Cela
permet de surcrot dconomiser de la bande passante.
Si vous rcuprez les donnes en utilisant SQL sur un systme
client/serveur, seules les donnes que vous demandez transitent via le
support de communication qui relie le client au serveur. linverse, sur un
systme se contentant de partager des ressources et qui nutilise quun
serveur dot dune intelligence minimale, des volumes de donnes normes
doivent circuler sur le rseau pour que vous puissiez rcuprer les donnes
dont vous avez besoin. Il est inutile de prciser que ce genre doprations
ralentit considrablement les oprations (tout en accroissant les failles dans
la scurit). Larchitecture client/serveur combine SQL permet dobtenir
de bonnes performances sur tous les types de rseaux.

Le serveur
Tant quil ne reoit pas de requte du client, le serveur ne fait rien. Il ne fait
quattendre. Si plusieurs clients lui prsentent des requtes simultanment,
le serveur doit y rpondre immdiatement. Il diffre des machines clients en
ce quil dispose dun vaste espace de stockage disque. Le serveur est
optimis pour accder rapidement aux donnes. Et comme il doit grer
beaucoup de requtes simultanes, il a besoin dun processeur rapide, voire
mme de plusieurs processeurs.

Ce quest le serveur
Le serveur (abrviation pour serveur de base de donnes) est la partie dun
systme client/serveur qui contient la base de donnes. On y trouve aussi le
ct serveur du SGBD. Cette partie du SGBD interprte les commandes
manant des clients et les traduit en oprations sur la base de donnes. Le
logiciel serveur formate aussi les rsultats des requtes et renvoie les
rsultats au client qui la demand.

Ce que fait le serveur


Le travail du serveur est relativement simple et vident. Tout ce quun
serveur doit faire est de lire, interprter et excuter les commandes que des
clients lui envoient par le rseau. Ces commandes sont rdiges dans lun
des nombreux sous-langages de donnes.
Un sous-langage ne dfinit pas compltement un langage : il en implmente
seulement une partie. Un sous-langage de donnes ne traite que de la gestion
des donnes. Ce sous-langage contient des oprations pour insrer, mettre
jour, supprimer et slectionner des donnes, mais il ne dispose pas
dinstructions de contrle de flux telles que les boucles DO, les variables
locales, les fonctions, les procdures ou les oprations dentre/sortie sur
les imprimantes. SQL est le plus courant des sous-langages de donnes. Les
autres sous-langages de donnes propritaires ont t supplants par SQL
sur tous les types de machines. Depuis SQL:1999, SQL a acquis nombre des
fonctionnalits qui manquent aux sous-langages de donnes traditionnels.
Cependant, il nest pas encore devenu un langage de programmation
gnraliste part entire, et il doit pour cette raison tre combin un
langage hte pour raliser des applications de bases de donnes.

Le client
La partie client dun systme client/serveur consiste en un composant
matriel et un composant logiciel. Le composant matriel est lordinateur
client et son interface au rseau local. Le client matriel peut parfaitement
tre identique au matriel serveur. Ce qui distingue le client du serveur,
cest le logiciel.

Ce quest le client
Le rle principal du client consiste fournir une interface utilisateur. Pour
autant que lutilisateur est concern, la machine client est lordinateur et
linterface utilisateur est lapplication. Lutilisateur peut ne mme pas
raliser quun processus se droule sur un serveur. Le serveur est
gnralement hors de sa vue (dans une autre pice, dans un autre btiment,
lautre bout de la plante). Hormis linterface utilisateur, le client
contient aussi le programme dapplication et la partie client du SGBD. Le
programme dapplication effectue les tches spcifiques que vous lui
demandez, comme saisir des fiches de paye ou des commandes. La partie
client du SGBD excute les commandes de ce programme et change des
donnes et des commandes SQL de manipulation de donnes avec le ct
serveur du SGBD.

Ce que fait le client


Le client affiche linformation lcran et rpond aux informations que
lutilisateur transmet via le clavier, la souris ou tout autre priphrique. Le
client peut aussi traiter des donnes qui proviennent dautres postes du
rseau (quelle que soit par ailleurs la nature physique de celui-ci). La partie
client du SGBD effectue tout le travail de rflexion . Cest donc celle qui
intresse le plus le dveloppeur. La partie serveur ne fait que traiter les
requtes que lui prsente le client dune manire mcanique, rptitive.

Utiliser SQL sur lInternet ou un


intranet
La gestion des bases de donnes via Internet ou un intranet est radicalement
diffrente de la gestion via un systme client/ serveur classique. Tout
dabord, sur un systme client/serveur traditionnel, lessentiel des
fonctionnalits du SGBD rside sur la machine client. Sur un systme bas
sur Internet, lessentiel du SGBD se trouve sur le serveur. Le client peut
nhberger rien dautre quun navigateur Web. Au mieux, il contient une
extension du navigateur, telle quun plug-in pour Netscape ou un contrle
ActiveX. Par consquent, la masse critique du systme se trouve
reporte sur le serveur. Cela prsente plusieurs avantages :
La portion client du systme (le navigateur) est peu
onreuse.

Vous disposez dune interface utilisateur standardise.

La maintenance du client est facile.

La relation client/serveur est standardise.

Vous possdez un support tout fait courant pour afficher


des donnes multimdias.

Les principaux inconvnients que prsente la manipulation dune base de


donnes via Internet sont la scurit et lintgrit des donnes :
Pour protger linformation de toute altration ou
consultation par un tiers non autoris, le serveur Web et le
client doivent supporter une technique puissante de
cryptage.

Les navigateurs ne procdent pas de vritables contrles


de validation des donnes saisies.

Les tables de la base de donnes qui rsident sur plusieurs


serveurs peuvent se dsynchroniser.
Les extensions client et serveur conues pour grer ces problmes ont fait
dInternet une architecture pour laquelle il est possible de dvelopper des
applications de base de donnes. Larchitecture dun intranet ressemble
celle dInternet, mais la scurit pose un moindre problme. Comme
lorganisation qui assure la maintenance de lintranet dispose dun contrle
physique sur les machines clients, les serveurs et le rseau qui les relie, un
intranet est bien moins expos aux attaques des pirates. Cependant, les
problmes du contrle des informations saisies et de la dsynchronisation
demeurent.
Chapitre 3
Les composants de SQL
DANS CE CHAPITRE :
Crer des bases de donnes.

Manipuler des donnes.

Protger les bases de donnes.

S
QL est un langage conu pour la cration et la maintenance des donnes
dans des bases relationnelles. Quoique les vendeurs de systmes de
gestion de bases de donnes relationnelles utilisent leur propre version
de SQL, un standard ISO/ANSI (rvis en 2011) dfinit ce quest SQL.
Toutes les implmentations scartent plus ou moins de cette norme. Par
consquent, sen tenir au standard est la meilleure tactique pour faire
fonctionner une base de donnes sur plus dune plate-forme.
Bien que SQL ne soit pas vraiment un langage de programmation, il est
quand mme dot de quelques outils impressionnants. Trois langages pour
le prix dun vous permettent de crer, de modifier, de maintenir et de
scuriser une base de donnes relationnelle :
Le langage de dfinition de donnes (DDL, pour Data
Definition Language) : Cest la partie de SQL que vous
utilisez pour crer (dfinir compltement) une base de
donnes, modifier sa structure et la dtruire quand vous
nen avez plus besoin.

Le langage de manipulation de donnes (DML, pour


Data Manipulation Language) : Il permet la maintenance
dune base de donnes. En utilisant ce puissant outil, vous
pouvez spcifier exactement ce que vous voulez faire avec
les donnes de votre base de donnes : les entrer, les
modifier ou les extraire.

Le langage de contrle de donnes (DCL, pour Data


Control Language) : Une armure pour protger vos
donnes. Quand il est utilis correctement, DCL permet de
scuriser votre base de donnes ; la qualit de cette
protection dpend de limplmentation. Si votre
implmentation ne fournit pas une protection suffisante,
vous devez hausser le niveau de celle-ci dans votre
programme dapplication.

Ce chapitre prsente DDL, DML et DCL.

Le langage de dfinition de donnes


(DDL)
Le langage de dfinition de donnes (DDL) est une partie de SQL que vous
utilisez pour crer, modifier ou dtruire les lments de base (cest le cas
de le dire) dune base de donnes relationnelle. Il sagit des tables, des
vues, des schmas, des catalogues, des clusters et ventuellement dautres
choses. Dans cette section, je prsente la hirarchie qui lie tous ces
lments ainsi que les commandes qui permettent de les manipuler.
Dans le Chapitre 1, jai parl des tables et des schmas en prcisant quun
schma est une structure gnrale qui contient des tables. Les tables et les
schmas sont donc deux lments de la hirarchie du contenu dune base de
donnes relationnelle. Vous pouvez dcomposer cette hirarchie ainsi :
Les tables contiennent des lignes et des colonnes.

Les schmas contiennent des tables et des vues.

Les catalogues contiennent des schmas.


La base de donnes elle-mme contient des catalogues. Vous verrez quon
dsigne parfois la base de donnes par le terme cluster.

Y a qu ! est un mauvais conseil


Supposons que vous soyez charg de crer une base de donnes pour votre
socit. Excit lide de crer une structure utile, valable, bien conue et
de grande importance pour le futur, vous prenez place devant votre
ordinateur et commencez saisir des commandes SQL CREATE. Correct ?
Eh bien non ! Cest en fait la meilleure solution pour aboutir au dsastre. De
nombreux projets de dveloppement de bases de donnes partent dans le
mur ds le dpart parce que lexcitation lemporte sur une planification
rigoureuse. Mme si vous avez une ide trs prcise de la structure de votre
base de donnes, vous devez tout crire noir sur blanc avant de toucher le
clavier de votre ordinateur.
Le dveloppement de bases de donnes peut assez bien tre compar au jeu
dchecs. Dans une comptition dchecs, vous trouvez un dplacement qui
vous parat bon. La pendule tourne, la tension fait son uvre, et lurgence
de jouer ce coup vous treint. Mais il y a une forte probabilit pour que
vous ayez manqu quelque chose. Les GM (Grands Matres) conseillent
souvent aux dbutants de sasseoir sur leurs mains. Et ce nest qu moiti
une plaisanterie. Si placer vos mains sous vos cuisses vous vite de jouer
un coup mal calcul, alors cest le bon geste faire. Si vous prenez un peu
plus de temps pour tudier la position, vous pourrez trouver un coup encore
meilleur (ou dcouvrir lattaque foudroyante que vous rserve votre
adversaire). De la mme manire, plonger dans la cration dune base de
donnes sans une rflexion pralable suffisante conduit presque toujours
une structure qui, dans le meilleur des cas, sera mal optimise. Et conduit
droit au dsastre dans le pire des cas (comme une invitation la corruption
des donnes lance aux quatre vents). Certes, sasseoir sur vos mains ne
vous aidera pas avancer. Prendre un stylo dans une de ces mains et
commencer planifier sur papier le schma de votre base de donnes, si.
La liste suivante recense quelques procdures que vous devez conserver
lesprit quand vous planifiez votre base de donnes :
Identifiez toutes les tables.

Dfinissez les colonnes que chaque table doit contenir.


Attribuez une cl primaire unique chaque table (je parle
des cls dans les Chapitres 4 et 5).

Assurez-vous que chaque table de la base de donnes


partage au moins une colonne avec une autre table. Ces
colonnes partages servent tablir des liens logiques
entre linformation contenue dans une table et une
information correspondante dans une autre table.

Passez chaque table dans la troisime forme normale


(3NF) ou plus pour prvenir toute anomalie pouvant tre
engendre par une insertion, une suppression ou une mise
jour (je traite de la normalisation des bases de donnes
dans le Chapitre 5).

Quand vous aurez termin votre conception sur le papier, vous pourrez la
transfrer sur lordinateur laide de la commande SQL CREATE. Plus
vraisemblablement, vous utiliserez linterface graphique utilisateur (GUI)
du SGBD pour cela. Si vous utilisez votre GUI, votre SGBD convertira
toutes vos actions en SQL dans les coulisses .

Crer des tables


Une table dune base de donnes est un tableau deux dimensions compos
de lignes et de colonnes. Vous pouvez crer une table en utilisant la
commande SQL CREATE TABLE. Vous spcifiez en paramtre le nom et le
type de donnes de chaque colonne.
Une fois que vous avez cr la table, vous allez y stocker des donnes (ce
qui est une fonction de DML et non de DDL). Si vos besoins voluent, vous
pouvez modifier la structure de la table en utilisant la commande ALTER
TABLE. Sil arrive un jour que la table ne soit plus utile, il est possible de
lliminer en utilisant la commande DROP. Les diffrentes formes des
commandes CREATE et ALTER, ainsi que la commande DROP, constituent
le langage de dfinition de donnes de SQL.
Imaginons que vous tes le concepteur dune base de donnes et que vous ne
voulez plus que vos tables dgnrent cause de mises jour rptes.
Vous dcidez alors de structurer les tables de votre base de donnes selon
la meilleure forme normale pour prserver lintgrit des donnes.
La normalisation (cest elle seule un vaste sujet dtudes) est une manire
de structurer les tables dune base de donnes pour que les mises jour
nintroduisent pas danomalies. Chaque table que vous crez contient des
colonnes qui correspondent des attributs qui sont troitement lis entre
eux.
Par exemple, vous pouvez crer une table CLIENTS avec les attributs
CLIENT_ID, NOM, PRENOM, RUE, VILLE, ETAT, CODE_POS-TAL et
TELEPHONE. Tous ces attributs sont plus troitement lis lentit client
qu toute autre entit dune base de donnes qui contient parfois de
nombreuses tables. Ces attributs reprsentent toutes les informations
permanentes que vous conservez sur vos clients.
La plupart des systmes de gestion de bases de donnes disposent dun outil
graphique pour crer des tables de bases de donnes. Cependant, vous
pouvez aussi crer des tables en utilisant une commande SQL. Lexemple
suivant vous montre comment crer une table CLIENTS de cette manire :

CREATE TABLE CLIENTS (


CLIENT_ID INTEGER NOT NULL,
PRENOM CHARACTER (15),
NOM CHARACTER (20) NOT NULL,
RUE CHARACTER (25),
VILLE CHARACTER (20),
ETAT CHARACTER (2),
CODE_POSTAL INTEGER,
TELEPHONE CHARACTER (13) ) ;

Vous prcisez pour chaque colonne son nom (par exemple, CLIENT_ID),
son type de donnes (par exemple, INTEGER) et ventuellement une ou
plusieurs contraintes (par exemple, NOT NULL).
La Figure 3.1 vous montre une portion de la table CLIENTS remplie de
quelques donnes.
FIGURE 3.1 La table CLIENTS cre en utilisant la commande CREATE TABLE.

Si limplmentation de SQL que vous utilisez ne rpond pas compltement


au standard ANSI/ISO, la syntaxe que vous devrez utiliser peut diffrer de
celle que jutilise dans ce livre. Consultez la documentation de votre SGBD
pour plus dinformations ce sujet.

Chambre avec vue


Un jour, vous aurez besoin de rcuprer des donnes de la table CLIENTS.
Vous ne voudrez pas visualiser tout, mais simplement quelques colonnes et
quelques lignes. Vous aurez alors besoin dune vue.
Une vue est une table virtuelle. Sur la plupart des implmentations, une
vue na aucune existence physique indpendante. La dfinition de la vue
existe dans les mtadonnes de la base, mais ses donnes proviennent de la
table ou des tables dont vous drivez cette vue. Les donnes de la vue ne
sont donc pas physiquement dupliques quelque part sur le disque.
Certaines vues contiennent des colonnes et des lignes spcifiques dune
seule table. Dautres, les vues multitables, proposent des donnes qui
proviennent de plusieurs tables.

Vue avec une seule table


La rponse vos questions se trouve parfois dans une seule table de votre
base de donnes. Dans ce cas, vous pouvez crer une vue simple. Par
exemple, supposons que vous dsiriez consulter les noms et les numros de
tlphone de tous les clients amricains qui vivent dans ltat du New
Hampshire. Vous crez une vue partir de la table CLIENTS en utilisant la
commande SQL suivante :

CREATE VIEW NH_CLIENT AS


SELECT CLIENTS.PRENOM,
CLIENTS.NOM,
CLIENTS.TELEPHONE

FROM CLIENTS
WHERE CLIENTS.ETAT = NH ;

La Figure 3.2 vous montre comment la vue est drive de la table


CLIENTS.

FIGURE 3.2 Vous drivez la vue NH_ CLIENT de la table CLIENTS.

Ce code est tout fait correct, mais vous pourriez arriver au mme rsultat
plus rapidement si limplmentation de SQL que vous utilisez prsumait que
toutes les rfrences aux tables sont faites derrire la clause FROM. Dans
ce cas, vous pouvez rduire la commande ces quelques lignes :

CREATE VIEW NH_CLIENT AS


SELECT PRENOM, NOM, TELEPHONE
FROM CLIENTS
WHERE ETAT = NH;

Quoique la seconde syntaxe soit plus agrable crire et lire, elle est plus
sensible aux effets dune commande ALTER TABLE. Ces effets seront
ngligeables dans lexemple que nous venons de voir, car notre vue nutilise
pas de jointure. Cependant, les vues qui utilisent JOIN sont moins robustes
si vous nutilisez pas des noms totalement qualifis. Je traite des jointures
au Chapitre 11.
Crer une vue multitable
Il arrive souvent que vous deviez extraire des donnes de deux ou plusieurs
tables pour rpondre une question. Par exemple, supposons que vous
travailliez pour un magasin de sport et que vous dsiriez obtenir la liste des
clients qui ont achet un quipement de ski lanne dernire pour leur
envoyer un mailing promotionnel. Vous aurez besoin dinformations
contenues dans les tables CLIENT, PRODUIT, FACTURE et LIGNE_FAC-
TURE. Vous pouvez crer une vue multitable qui contienne toutes ces
informations. Une fois que vous aurez cr cette vue, elle tiendra compte
des mises jour effectues sur les tables depuis la dernire fois o vous
laurez consulte.
La base de donnes du magasin de sport contient quatre tables : CLIENT,
PRODUITS, FACTURE et LIGNE_FACTURE. Ces tables sont structures
comme le montre le Tableau 3.1.

TABLEAU 3.1 Les tables du magasin de sport.

Table Colonne Type de donnes Contrainte

CLIENT CLIENT_ID INTEGER NOT NULL

PRENOM CHARACTER (15)


NOM CHARACTER (20) NOT NULL
RUE CHARACTER (25)
VILLE CHARACTER (20)
ETAT CHARACTER (2)

CODE_POSTAL INTEGER
TELEPHONE CHARACTER (13)

PRODUIT PRODUIT_ID INTEGER NOT NULL

NOM CHARACTER (25)


DESCRIPTION CHARACTER (30)
CATEGORIE CHARACTER (15)
VENDEUR_ID INTEGER
NOM_VENDEUR CHARACTER (30)

FACTURE NUMERO_FACTURE INTEGER L NOT NUL

CLIENT_ID INTEGER

DATE_FACTURE DATE

TOTAL_VENTE NUMERIC (9,2)


TOTAL_REMIS NUMERIC (9,2)

FORME_PAIEMENT CHARACTER (10)

LIGNE_FACTURE NUMERO_LIGNE INTEGER NOT NULL

NUMERO_FACTURE INTEGER

PRODUIT_ID INTEGER

QUANTITE INTEGER

PRIX_VENTE NUMERIC (9,2)

Notez que quelques colonnes du Tableau 3.1 contiennent la contrainte NOT


NULL. Ces colonnes sont soit des cls primaires de leur table, soit des
colonnes dont vous ne voulez pas quelles contiennent une valeur nulle. La
cl primaire dune table identifie de manire unique chaque ligne. Elle doit
contenir une valeur non nulle. Je traite des cls dans le Chapitre 5.
Les tables sont relies entre elles par des colonnes quelles possdent en
commun. La Figure 3.3 illustre ces relations. Elles sont dcrites ci-dessous.

La table CLIENT entretient une relation un plusieurs


avec la table FACTURE. Un client peut effectuer plusieurs
achats, ce qui gnre autant de factures. Cependant,
chaque facture nest lie qu un unique client.
La table FACTURE entretient une relation un plusieurs
avec la table LIGNE_FACTURE. Une facture peut contenir
plusieurs lignes, mais chaque ligne napparat que sur une
et une seule facture.

La table PRODUIT entretient aussi une relation un


plusieurs avec la table LIGNE_FACTURE. Un produit peut
apparatre dans plusieurs lignes sur une ou plusieurs
factures. Cependant, chaque ligne ne peut correspondre
qu un unique produit.

FIGURE 3.3 La structure de la base de donnes du magasin de sport.

La table CLIENT est relie la table FACTURE par la


colonne CLIENT_ID. La table FACTURE est relie la table
LIGNE_FACTURE par la colonne NUMERO_FACTURE. La
table PRODUIT est relie la table LIGNE_FACTURE par la
colonne PRODUIT_ID.

Ces liens sont lessence dune base de donnes relationnelle.


Pour obtenir linformation que vous recherchez sur vos clients, vous aurez
besoin de NOM, PRENOM, RUE, VILLE, ETAT et CODE_POS-TAL dans
la table CLIENT, de CATEGORIE dans la table PRODUIT et de
NUMERO_FACTURE dans la LIGNE_FACTURE. Vous pouvez crer la vue
en utilisant les commandes suivantes :

CREATE VIEW SKI_CLIENT1 AS


SELECT NOM,
PRENOM,
RUE,
VILLE,
ETAT,
CODE_POSTAL,
NUMERO_FACTURE
FROM CLIENT JOIN FACTURE
USING (CLIENT_ID) ;
CREATE VIEW SKI_CLIENT2 AS
SELECT NOM,
PRENOM,
RUE,
VILLE,
ETAT,
CODE_POSTAL,
PRODUIT_ID
FROM SKI_CLIENT1 JOIN LIGNE_FACTURE
USING (NUMERO_FACTURE) ;
CREATE VIEW SKI_CLIENT3 AS
SELECT NOM,
PRENOM,
RUE,
VILLE,
ETAT,
CODE_POSTAL,
CATEGORIE
FROM SKI_CLIENT2 JOIN PRODUIT
USING (PRODUIT_ID) ;
CREATE VIEW SKI_CLIENT AS
SELECT DISTINCT NOM,
PRENOM,
RUE,
VILLE,
ETAT,
CODE_POSTAL,
FROM SKI_CLIENT3
WHERE CATEGORIE = Ski ;

Ces instructions CREATE VIEW combinent les donnes des diffrentes


tables en utilisant loprateur JOIN. La Figure 3.4 et les notes qui suivent
dtaillent ce processus.
La premire instruction combine les colonnes de la table
CLIENT avec une colonne de la table FACTURE pour crer la
vue SKI_CLIENT1.

La deuxime instruction combine les colonnes de la table


SKI_CLIENT1 avec une colonne de la table
FACTURE_LIGNE pour crer la vue SKI_CLIENT2.

La troisime instruction combine les colonnes de la table


SKI_CLIENT2 avec une colonne de la table PRODUIT pour
crer la vue SKI_CLIENT3.
FIGURE 3.4 La cration dune vue multitable en utilisant des jointures.

La quatrime instruction supprime toutes les lignes qui


nentrent pas dans la catgorie ski . Le rsultat final est
une vue (SKI_CLIENT) qui contient les noms et les
adresses de tous les clients qui ont achet au moins un
produit de la catgorie ski .

Le mot cl DISTINCT dans la clause SELECT de la


quatrime instruction CREATE VIEW vous garantit que
vous naurez quune et une seule entre pour chaque client,
mme si certains clients ont achet plusieurs articles de
ski.

Il est possible de crer une vue multitable en une seule instruction SQL.
Toutefois, si vous pensez que lune ou lautre des commandes prcdentes
sont complexes, imaginez quel degr de complexit atteindrait celle qui
cumulerait toutes leurs fonctions. Je prfre la simplicit la complexit, si
bien que chaque fois que cest possible, je choisis le moyen le plus simple
daccomplir une fonction, mme si ce nest pas trs efficient .

Organiser les tables en schmas


Une table est un ensemble de lignes et de colonnes qui traite gnralement
dentits dun type spcifique telles que les clients, les produits ou les
factures. Dans la ralit, il faut parfois manipuler des informations lies
plusieurs de ces entits. Sur le plan organisationnel, vous rassemblez les
tables que vous associez ces entits pour former un schma logique (un
schma logique est la structure organisationnelle qui correspond un
ensemble de tables lies entre elles).
En plus des schmas logiques, la base de donnes contient des schmas
physiques. Le schma physique est la manire dont la donne et ses objets
associs, tels que des index, sont physiquement organiss sur les
priphriques de stockage du systme. Quand je mentionne le schma dune
base de donnes, je me rfre au schma logique et non au schma physique.
Dans un systme o plusieurs projets indpendants peuvent coexister, vous
pouvez assigner toutes les tables qui sont relies entre elles un seul
schma. Les autres groupes de tables seront le cas chant placs dans leurs
propres schmas.
Vous devriez nommer les schmas pour vous assurer que personne ne
mlangera accidentellement les tables dun projet avec celles dun autre
projet. Chaque projet dispose de son propre schma associ, que vous
distinguez des autres par son nom. Cependant, il est frquent que des tables
de diffrents projets portent le mme nom (par exemple CLIENT ou
PRODUIT). Pour lever toute ambigut, vous devriez dsigner vos tables
dans vos instructions SQL en les prfixant par le nom de leur schma
(comme dans NOM_SCHEMA. TABLE_NOM). Si vous ne fournissez aucun
nom de schma, SQL considre que la table appartient au schma par
dfaut.

Ordonner par catalogue


Utiliser plusieurs schmas peut se rvler insuffisant quand le systme de
gestion de bases de donnes est trs volumineux. En effet, sur un
environnement distribu de base de donnes que manipulent de nombreux
utilisateurs, vous pouvez rencontrer des schmas qui portent le mme nom.
Pour viter que ce problme ne se pose, SQL a ajout un lment
supplmentaire dans la hirarchie des conteneurs : le catalogue. Un
catalogue est un ensemble nomm de schmas.
Vous pouvez qualifier le nom dune table en utilisant le nom de son
catalogue et le nom de son schma. Cela vous garantit que la table ne sera
pas confondue avec une table homonyme dun schma homonyme. Le nom
de table ainsi qualifi prendra la forme suivante :

NOM_CATALOG.NOM_SCHEMA.NOM_TABLE

La hirarchie des conteneurs dune base de donnes comprend son


sommet les clusters, mais rares sont les systmes qui en requirent
lutilisation. La plupart du temps, les choses sarrtent au catalogue. Un
catalogue regroupe des schmas, un schma regroupe des tables et des vues,
lesquelles sont constitues de colonnes et de lignes.
Le catalogue inclut aussi linformation de schma. Cette dernire contient
les tables systme. Les tables systme grent les mtadonnes associes aux
autres schmas. Dans le Chapitre 1, jai dfini une base de donnes comme
une collection denregistrements intgrs capable de se dcrire elle-mme.
Ce sont les mtadonnes contenues dans les tables systme qui rendent cette
description possible.
Du fait que les catalogues sont identifis par leur nom, il est possible den
utiliser plusieurs dans une base de donnes. Chaque catalogue peut contenir
plusieurs schmas, et chaque schma peut contenir son tour plusieurs
tables. Et, bien entendu, chaque table est susceptible de possder de
multiples colonnes et de multiples lignes. Ces relations hirarchiques sont
reprsentes sur la Figure 3.5.

FIGURE 3.5 La structure hirarchique dune base de donnes SQL.

Se familiariser avec les commandes


DDL
Le langage de dfinition de donnes (DDL) permet de manipuler la structure
de la base de donnes alors que DML, le langage de manipulation de
donnes, permet de traiter les donnes stockes dans cette structure. Sous
SQL, DDL est compos de trois commandes :
CREATE : Vous utilisez les diverses formes de la
commande CREATE pour crer les structures essentielles
de la base de donnes.

ALTER : Vous utilisez la commande ALTER pour modifier


les structures que vous avez cres.

DROP : Si vous utilisez la commande DROP sur une table,


la commande dtruit non seulement les donnes de la
table mais aussi sa structure.

Dans les sections suivantes, je vais vous donner une description rapide des
commandes de DDL. Nous nous servirons de ces commandes dans les
exemples des Chapitres 4 et 5.

CREATE
La commande CREATE vous permet de crer de nombreux objets de SQL
dont les schmas, les domaines, les tables et les vues. En utilisant
linstruction CREATE SCHEMA, vous pouvez crer un schma, identifier
son propritaire et spcifier son jeu de caractres par dfaut. Par exemple :

CREATE SCHEMA VENTES


AUTHORIZATION RESPONSABLE_VENTES
DEFAULT CHARACTER SET ASCII_FULL ;

Utilisez linstruction CREATE DOMAIN pour appliquer des contraintes


des valeurs de colonne ou pour spcifier un ordre de regroupement. Les
contraintes que vous appliquez au domaine dterminent la nature des objets
que ce dernier a le droit de contenir. Vous pouvez crer des domaines aprs
avoir dfini un schma. Par exemple :
CREATE DOMAIN Age AS INTEGER
CHECK (AGE > 20) ;

Pour les tables, vous disposez de linstruction CREATE TABLE. Et


linstruction CREATE VIEW sert comme il se doit crer des vues. Ci-
avant dans ce chapitre, je vous ai prsent des exemples dutilisation de ces
deux instructions. Quand vous utilisez CREATE TABLE pour crer une
nouvelle table, vous pouvez simultanment spcifier des contraintes sur les
colonnes de cette dernire.
Cependant, il arrive que vous deviez dfinir des contraintes qui ne
sappliquent pas une table en particulier mais tout le schma. Servez-
vous alors de linstruction CREATE ASSERTION pour dfinir ces
contraintes.
Vous disposez aussi des instructions CREATE CHARACTER, CREATE
COLLATION et CREATE TRANSLATION pour crer des jeux de
caractres, des squences dinterclassement et des tables de traduction.
(Une squence dinterclassement dfinit lordre dans lequel vous effectuez
des comparaisons et des tris. Les tables de traduction contrlent la
conversion de chanes de caractres dun jeu de caractres un autre.)

ALTER
Une fois que vous aurez cr une table, il se peut que vous ayez la
modifier. Linstruction ALTER TABLE vous servira ajouter, modifier et
supprimer des colonnes dans cette table. ALTER sutilise aussi sur des
domaines.

DROP
Il est trs facile de supprimer une table du schma dune base de donnes.
Utilisez simplement la commande DROP TABLE. Cela supprime toutes les
donnes de la table ainsi que les mtadonnes qui dfinissent cette dernire
dans le dictionnaire des donnes.

Le langage de manipulation de
donnes (DML)
Comme je lai dit au dbut de ce chapitre, DDL est la partie de SQL qui
permet de crer, modifier et dtruire des structures de la base de donnes.
DDL ne manipule pas les donnes elles-mmes. Ce rle est dvolu au
langage de manipulation de donnes (DML). Quelques instructions de DML
sont faciles comprendre, dautres semblent souvent trs complexes. En
effet, si une instruction DML comprend plusieurs expressions, clauses,
prdicats ou sous-requtes, il peut devenir trs difficile de comprendre ce
quelle signifie. Il est alors indispensable de dcouper linstruction en
morceaux et dtudier chacun dentre eux.
Les instructions DML dont vous disposez sont INSERT, UPDATE, DELETE
et SELECT. Ces instructions peuvent comprendre plusieurs parties, dont de
multiples clauses. Chaque clause peut son tour contenir des expressions
de valeurs, des connecteurs logiques, des prdicats, des fonctions
dagrgation et des sous-requtes. Toutes ces clauses vous permettent de
mieux extraire linformation de la base de donnes en discriminant
prcisment les enregistrements quelle contient. Dans le Chapitre 6, je
traite de lutilisation des commandes de DML. Je rentrerai dans le dtail de
celles-ci dans les Chapitres 8 14.

Les expressions de valeurs


Vous pouvez utiliser des expressions de valeurs pour combiner deux ou
plusieurs valeurs. Il existe neuf sortes dexpressions de valeurs, chacune
correspondant un type de donnes prcis :
Numrique.

Chane.

Date et heure.

Intervalle.

Boolen.

Dfini par lutilisateur.

Ligne.
Collection.

Les types Boolen, Dfini par lutilisateur et Ligne ont t introduits dans
SQL:1999. Certaines implmentations ne les grent pas encore. Si vous
voulez utiliser ces types de donnes, vrifiez ce quen dit votre
implmentation.

Les expressions de valeurs numriques


Pour combiner des valeurs numriques, utilisez les oprateurs daddition
(+), de soustraction (-), de multiplication (*) et de division (/). Les lignes
suivantes contiennent quelques exemples de telles expressions :

12 7
15/3 - 4
6 * (8 + 2)

Les valeurs qui figurent dans cet exemple sont des littraux numriques. Ces
valeurs pourraient tout aussi bien tre des noms de colonnes, des
paramtres, des variables htes ou des sous-requtes. Lessentiel est quil
sagisse toujours de valeurs numriques. En voici quelques exemples :

SOUSTOTAL + TAXE + PORT


6 * KM/HEURE
:mois/12

Le deux-points ( : ) du dernier exemple signale que le terme qui suit (mois)


est soit un paramtre, soit une variable hte.

Les expressions de chanes


Les expressions de chanes peuvent inclure loprateur de concatnation
(||). Utilisez la concatnation pour fusionner deux chanes de caractres,
comme le montre le Tableau 3.2.

TABLEAU 3.2 Exemples de concatnation de chanes.

Expression Rsultat
renseignement renseignement militaire
|| militaire

tra || duction traduction

VILLE|| Une seule chane compose de la ville, de ltat et


||ETAT|| du code postal, chacun tant spar par un seul
||CODE_POSTAL espace.

Certaines implmentations de SQL utilisent loprateur + pour la


concatnation. Vrifiez ce point dans votre documentation.

Quelques implmentations peuvent proposer dautres oprateurs de chane


que la concatnation, mais le standard SQL ne les supporte pas.

Les expressions de valeurs de type


date/heure et intervalle
Les expressions de valeurs date/heure manipulent des dates et des heures.
Des donnes de type DATE, TIME, TIMESTAMP et INTERVAL peuvent
figurer dans ces expressions. Le rsultat dune expression date/heure est une
autre expression date/heure. Vous pouvez ajouter ou soustraire un intervalle
dune date/heure et spcifier des informations relatives au dcalage horaire.
Voici un exemple dutilisation dune telle expression :

DATE_PRET + INTERVAL 7 DAY

Une bibliothque pourrait utiliser une expression de ce type pour dterminer


quand envoyer une note de rappel un abonn pour quil rapporte les livres
emprunts. Lexemple qui suit utilise cette fois-ci lheure :

TIME 18:55:48 AT LOCAL

Le mot cl AT LOCAL signifie que lheure est exprime en temps national.


Les expressions de type intervalle valuent le temps pass entre deux
date/heure. Il y a deux types dintervalles : anne-mois et jour-heure. Vous
ne pouvez pas les mlanger au sein dune mme expression.
Par exemple, quelquun pourrait rendre un livre la bibliothque aprs la
date limite. En utilisant une expression de type intervalle, vous pourriez
calculer combien de jours se sont couls depuis cette date butoir et
calculer lamende correspondante :

(DATE_RETOUR-DATE_LIMITE) DAY

Comme un intervalle peut tre soit de type anne-mois, soit de type jour-
heure, vous devez prciser quel type vous souhaitez utiliser. Dans lexemple
prcdent, jai spcifi DAY.

Les expressions de valeurs boolennes


Une expression de valeur boolenne teste la vracit dun prdicat. Voici un
exemple dexpression boolenne :

(CLASSE = DOCTORANT) IS TRUE

Sil sagissait dune condition pour rcuprer des lignes dune table qui
recense des tudiants, seules celles qui correspondent des doctorants vous
seraient retournes. Pour obtenir les enregistrements de tous ceux qui ne
sont pas doctorants, vous pourriez utiliser :

NOT (CLASSE = DOCTORANT) IS TRUE

Ce qui peut aussi scrire :

(CLASSE = DOCTORANT) IS FALSE

Voici comment rcuprer toutes les lignes dont la colonne CLASSE


contient une valeur nulle :

(CLASSE = DOCTORANT) IS UNKNOWN

Les expressions de valeurs de type dfini


par lutilisateur
Les types dfinis par lutilisateur sont dcrits dans le Chapitre 2. Cette
fonctionnalit permet aux utilisateurs de dfinir leurs propres types de
donnes au lieu dutiliser ceux de SQL. Les expressions qui utilisent des
donnes de type dfini par lutilisateur doivent valuer un lment du mme
type.

Les expressions de valeurs de ligne


Une expression valeur de ligne spcifie, et ce nest pas une surprise, une
valeur de ligne. Celle-ci peut consister en une ou plusieurs expressions
spares par une virgule. Par exemple :

(Joseph Tykociner, Professeur Emrite, 1918)

Il sagit dune ligne dune table dcrivant toute lhistoire dune universit.
Elle contient le nom, le rang et lanne dintgration dun professeur.

Les expressions de valeurs de collection


Une expression valeur de collection est value comme un tableau.

Les expressions de valeurs de rfrence


Une expression valeur de rfrence est value comme une valeur qui
rfrence un autre composant de la base de donnes, comme une colonne de
table.

Les prdicats
Les prdicats sont les quivalents SQL des propositions logiques.
Linstruction suivante est un exemple de proposition :

Ltudiant est un senior.

Dans une table qui contient des informations sur les tudiants, le domaine de
la colonne CLASSE peut tre SENIOR, JUNIOR, DIPLOME, THESARD
ou NULL. Vous pouvez utiliser le prdicat CLASSE = SENIOR pour
isoler toutes les lignes pour lesquelles le prdicat est faux ou toutes les
lignes pour lesquelles le prdicat est vrai. Parfois, la valeur du prdicat
pour une ligne est indtermine (NULL). Dans ce cas, vous pourriez dcider
soit dliminer la ligne, soit de la retenir (aprs tout, ltudiant pourrait tre
un senior). Le traitement adapt dpend du cas de figure.
CLASSE = SENIOR est un exemple de prdicat de comparaison. SQL
dispose de six oprateurs de comparaison. Un prdicat de comparaison
simple nutilisera quun seul dentre eux. Le Tableau 3.3 contient une liste
de prdicats de comparaison et des exemples de leur utilisation.
Dans lexemple prcdent, seules les deux premires entres (CLASSE =
SENIOR et CLASSE <> SENIOR) ont un sens, les autres
comparaisons nayant dautre signification que celle dun tri alphabtique,
ce qui nest peut-tre pas ce que vous attendiez.

TABLEAU 3.3 Oprateurs de comparaison et prdicats de comparaison.

Oprateur Comparaison Expression

= Egal CLASSE = SENIOR

<> Diffrent de CLASSE <> SENIOR

< Infrieur CLASSE < SENIOR

> Suprieur CLASSE > SENIOR

<= Infrieur ou gal CLASSE <= SENIOR

>= Suprieur ou gal CLASSE >= SENIOR

Connecteurs logiques
Les connecteurs logiques vous permettent de construire des prdicats
complexes partir dexpressions plus simples. Supposons par exemple que
vous souhaitiez identifier les enfants prodiges dans une base de donnes
dtudiants. Deux propositions pourraient identifier ces enfants :
Ltudiant est un senior
Lge de ltudiant est infrieur 14

Vous pouvez faire appel au connecteur logique AND pour fabriquer un


prdicat compos qui isole les enregistrements correspondant aux tudiants
recherchs. Par exemple :

CLASSE = SENIOR AND AGE < 14

Si vous utilisez le connecteur AND, les deux prdicats doivent tre valids
(vrais) pour que le prdicat compos le soit aussi. Utilisez le connecteur OR
quand vous voulez que le prdicat compos soit valid si lun ou lautre des
prdicats qui le compose est valid (ou les deux). NOT est le troisime
connecteur logique. proprement parler, NOT ne permet pas de connecter
des prdicats, mais il inverse la valeur de lexpression laquelle vous
lappliquez. Prenons un exemple :

NOT (CLASSE = SENIOR)

Cette expression est valide si CLASSE nest pas gal SENIOR.

Les fonctions densemble


Quelquefois, linformation que vous voulez extraire dune table ne dpend
pas du contenu dune ligne, mais de plusieurs lignes. SQL dispose de cinq
fonctions densemble (ou) pour ce cas. Ces fonctions sont COUNT, MAX,
MIN, SUM et AVG. Chaque fonction extrait des donnes dun ensemble de
lignes.

COUNT
La fonction COUNT retourne le nombre de lignes de la table spcifie qui
vrifient le critre spcifi. Pour compter le nombre de seniors
prcoces dans la base de donnes dtudiants, utilisez par exemple
linstruction suivante :

SELECT COUNT (*)


FROM ETUDIANT
WHERE GRADE = 12 AND AGE < 14 ;

MAX
La fonction MAX renvoie la valeur maximale que prend une colonne dans
un ensemble de lignes. Supposons que vous souhaitiez trouver ltudiant qui
a le plus danciennet dans votre cole. Vous utiliseriez une instruction
comme celle-ci :

SELECT NOM, PRENOM, AGE


FROM ETUDIANT
WHERE AGE = (SELECT MAX(AGE) FROM ETUDIANT);

Cette instruction retourne tous les tudiants dont lge est gal lge
maximal. Cest--dire que si lge de ltudiant le plus ancien est 23, cette
instruction retournera les noms et les prnoms de tous les tudiants qui
ont 23 ans.
Cette requte utilise une sous-requte. La sous-requte SELECT
MAX(AGE) FROM ETUDIANT est incluse dans la requte principale.

MIN
La fonction MIN fonctionne exactement comme la fonction MAX, ceci
prs quelle recherche la valeur minimale dune colonne dans un ensemble
de lignes. Pour trouver le plus jeune tudiant, vous pourriez utiliser la
requte suivante :

SELECT NOM, PRENOM, AGE


FROM ETUDIANT
WHERE AGE = (SELECT MIN(AGE) FROM ETUDIANT);

Cette requte retourne tous les tudiants dont lge est celui de ltudiant le
plus jeune.

SUM
La fonction SUM effectue la somme des valeurs dune colonne donne. La
colonne doit possder lun des types de donnes numriques reconnus, et la
valeur de la somme doit appartenir la plage des valeurs autorises pour
cette colonne. Par exemple, si la colonne est de type SMALLINT, la somme
ne doit pas dpasser la limite suprieure du type de donnes SMALLINT.
Dans la base de donnes des clients que nous avons utilise plus haut, la
table FACTURE contient un enregistrement de toutes les ventes. Pour
trouver la valeur totale de celles-ci, utilisez la fonction SUM de la manire
suivante :

SELECT SUM(TOTAL_VENTE) FROM FACTURE;

AVG
La fonction AVG retourne la moyenne de toutes les valeurs dune colonne
donne. Comme la fonction SUM, AVG ne sapplique quaux colonnes dont
le type de donnes est numrique. Pour trouver la valeur moyenne des
ventes, appelez la fonction AVG de la manire suivante :

SELECT AVG(TOTAL_VENTE) FROM FACTURE

Souvenez-vous que les valeurs nulles nont pas de valeurs. Par consquent,
si des lignes de TOTAL_VENTE contiennent des valeurs nulles (inconnues
ou non encore dfinies), elles seront purement et simplement ignores dans
le calcul de la moyenne.

Sous-requtes
Comme vous avez pu le constater dans la section prcdente, les sous-
requtes sont des requtes insres dans dautres requtes. Partout o vous
pouvez utiliser une expression, vous pouvez aussi utiliser une sous-requte.
Les sous-requtes sont particulirement utiles pour relier linformation que
contient une table celle qui se trouve dans une autre table. Vous pouvez en
effet inclure une requte portant sur une table dans une requte concernant
une autre table. En imbriquant plusieurs sous-requtes, il est possible
daccder aux informations provenant de deux ou de plusieurs tables pour
gnrer le rsultat final.
Le langage de contrle de donnes
(DCL)
Le langage de contrle de donnes (DCL) dispose de quatre instructions :
COMMIT, ROLLBACK, GRANT et REVOKE. Ces instructions servent toutes
protger la base de donnes de modifications accidentelles ou
intentionnelles qui pourraient mettre en danger son intgrit.

Les transactions
Votre base de donnes est plus vulnrable aux dangers pendant que vous ou
quiconque la modifiez. Mme sil ny a quun seul utilisateur, toute
modification peut se rvler dangereuse pour la base de donnes. Une panne
logicielle ou matrielle alors que ldition est en cours peut laisser la base
de donnes dans un tat instable entre ce quelle tait avant la modification
et ce quelle aurait d tre aprs cette modification.
SQL protge votre base de donnes en limitant les oprations susceptibles
daffecter la base de donnes de telle sorte que ces oprations ne peuvent se
drouler que dans le cadre de transactions. Durant une transaction, SQL
enregistre chaque opration sur les donnes dans un fichier journal (ou log).
Si un vnement quelconque interrompt la transaction avant que linstruction
COMMIT ny mette un terme, vous pouvez restaurer le systme dans son
tat initial en utilisant linstruction ROLLBACK. ROLLBACK excute le
fichier de log dans le sens inverse, annulant toutes les actions qui y figurent.
Une fois restaur ltat initial de la base de donnes, vous pouvez
rechercher la cause du problme et procder une nouvelle transaction.
Tant quun problme logiciel ou matriel peut survenir, votre base de
donnes est susceptible dtre endommage. Pour minimiser les risques, les
SGBD effectuent toutes les oprations qui modifient la base de donnes
dans le contexte de transactions et valident ces oprations les unes aprs les
autres. Les systmes de gestion de bases de donnes modernes utilisent le
logging en plus des transactions pour garantir quun problme logiciel,
matriel ou oprationnel ne causera pas de dommages la base de donnes.
Une fois que la transaction a t valide, elle est prserve de tout (sauf des
catastrophes majeures !). Insistons encore : tant que linstruction COMMIT
na pas t excute, la machine remonter le temps permet de revenir
jusquau point de dpart dune transaction. Une fois le problme corrig,
lhistoire peut reprendre son fil normal.
Sur un systme multi-utilisateur, une base de donnes risque dtre
corrompue et/ou de produire des rsultats errons sans que survienne une
quelconque panne logicielle ou matrielle. Les interactions entre les
diffrents utilisateurs qui accdent la mme table au mme instant sont en
effet susceptibles de poser de srieux problmes. En limitant les
modifications de sorte quelles ne puissent se produire que dans le cadre de
transactions, SQL rsout aussi cette difficult.
En effectuant toutes les oprations qui peuvent affecter la base de donnes
dans le cadre de transactions, vous pouvez isoler les actions dun utilisateur
de celles dun autre utilisateur. Cela est vital pour garantir que les rsultats
seront corrects.
Vous vous demandez peut-tre comment les interactions entre deux
utilisateurs peuvent produire des rsultats errons. Supposons par exemple
que Didier lise un enregistrement dans une table dune base de donnes. Un
instant plus tard, David modifie la valeur dun champ numrique dans cet
enregistrement. Didier crit alors au mme emplacement une donne qui est
fonction de ce quil a lu quelques secondes plus tt. Comme Didier nest
pas au courant des modifications de David, la valeur quil saisit nest pas
correcte.
Un autre problme peut survenir si Didier crit dans un enregistrement puis
que David lit ce dernier. Si Didier annule sa transaction, David ne sera pas
inform de cette opration, et il procdera des modifications sur la base
dinformations qui ne sont plus jour.

Les utilisateurs et les privilges


Hormis la corruption des donnes qui rsulte de pannes logicielles ou
matrielles, ou encore dinteractions malencontreuses entre utilisateurs, un
autre danger menace lintgrit dune base de donnes : les utilisateurs eux-
mmes. Certaines personnes ne devraient pas pouvoir accder du tout aux
donnes. Dautres devraient ne pouvoir accder qu certaines donnes,
mais pas toutes. Et dautres encore devraient pouvoir accder tout sans
aucune contrainte. Vous avez donc besoin dun systme permettant de
cataloguer les utilisateurs et daffecter (ou de refuser) des privilges aux
membres des diffrentes catgories.
Le crateur dun schma spcifie qui est considr comme tant son
propritaire. En tant que propritaire du schma, vous avez le droit
daccorder des privilges daccs vos utilisateurs. Tout privilge que
vous naccordez pas explicitement est considr comme tant refus. Les
privilges sont aussi susceptibles dtre retirs tout moment. Un utilisateur
doit passer par une procdure dauthentification afin de prouver son
identit. Ce nest quaprs avoir montr patte blanche quil sera capable
daccder aux fichiers et aux donnes pour lesquels il dispose de
privilges. La procdure exacte dpend de limplmentation (voire du
matriel si la scurit exige une lecture dempreintes digitales ou de liris).
SQL vous permet de protger les objets suivants :
Les tables.

Les colonnes.

Les vues.

Les domaines.

Les jeux de caractres.

Les squences dinterclassement.

Les traductions.

Je traite des jeux de caractres, des squences dinterclassement et des


traductions dans le Chapitre 5.
SQL supporte plusieurs types de protection : voir, ajouter, modifier,
supprimer, rfrencer et utiliser les bases de donnes. Il existe de surcrot
des protections associes lexcution de routines externes.
Vous accordez un privilge daccs en faisant appel linstruction GRANT
et vous le supprimez avec linstruction REVOKE. En supervisant le
fonctionnement de linstruction SELECT, le DCL contrle qui a le droit de
voir un objet de la base de donnes comme une table, une colonne ou encore
une vue. De mme, la matrise sur linstruction INSERT permet de
dterminer qui peut ajouter de nouvelles lignes une table. De mme aussi,
restreindre lemploi de linstruction UPDATE permet de nautoriser la
modification des lignes des tables quaux seuls utilisateurs autoriss. Et
restreindre lusage de linstruction DELETE sert dfinir qui a le droit de
supprimer des lignes dans des tables.
Si une table dune base de donnes dfinit comme cl trangre une colonne
qui est cl primaire dans une autre table, vous pouvez ajouter une contrainte
la premire table de sorte quelle rfrence la seconde (les cls
trangres sont dcrites dans le Chapitre 5). Quand une table en rfrence
ainsi une autre, son propritaire peut tre mme de dduire des
informations sur le contenu de la seconde. Et si vous tes le propritaire de
la seconde table, il nest pas certain que cette perspective vous enchante.
Linstruction GRANT REFERENCES de SQL vous donne le pouvoir
dempcher une telle intrusion. La section suivante prsente le problme
pos par une rfrence inattendue et montre comment linstruction GRANT
REFERENCES permet de le rsoudre. Grce linstruction GRANT
USAGE, il est possible de contrler qui a le droit dutiliser ou de visualiser
le contenu dun domaine, dun jeu de caractres, dune squence
dinterclassement ou dune traduction.
Le Tableau 3.4 contient la liste des instructions que SQL met votre
disposition pour accorder et retirer des privilges.

TABLEAU 3.4 Les types de protection.

Opration de protection Instruction

Permettre de voir une table GRANT SELECT

Interdire de voir une table REVOKE SELECT

Permettre dajouter des GRANT INSERT


lignes une table

Interdire dajouter des lignes REVOKE INSERT


une table

Permettre de modifier des GRANT UPDATE


donnes dans des lignes
dune table
Interdire de modifier des REVOKE UPDATE
donnes dans des lignes
dune table

Permettre de supprimer des GRANT DELETE


lignes dans une table

Interdire de supprimer des REVOKE DELETE


lignes dans une table

Permettre de rfrencer une GRANT REFERENCES


table

Interdire de rfrencer une REVOKE REFERENCES


table

Permettre dutiliser un GRANT USAGE ON DOMAIN, GRANT


domaine, une traduction de USAGE ON CHARACTER SET, GRANT
USAGE ON TRANSLATION
caractres ou une collation

Interdire dutiliser un REVOKE USAGE ON DOMAIN, REVOKE


domaine, une traduction de USAGE ON CHARACTER SET, REVOKE
caractres ou une collation USAGE ON TRANSLATION

Vous pouvez attribuer diffrents niveaux daccs diffrentes personnes, et


ce en fonction de leurs besoins. Voici quelques exemples :

GRANT SELECT
ON CLIENT
TO RESPONSABLE_VENTES;

permet une personne, en loccurrence le responsable des ventes, de voir


la table CLIENT.
Lexemple suivant autorise quiconque disposant dun accs au systme de
voir la liste des prix publics :
GRANT SELECT
ON PRIX_PUBLICS
TO PUBLIC;

Nous voulons maintenant permettre au responsable des ventes dditer la


liste des prix publics. Il doit avoir la possibilit de modifier le contenu de
lignes dj prsentes, mais sans pouvoir ni en supprimer ni en ajouter :

GRANT UPDATE
ON PRIX_PUBLICS
TO RESPONSABLE_VENTES;

Si le responsable des ventes est autoris ajouter de nouvelles lignes dans


la liste des prix publics, nous crirons :

GRANT INSERT
ON PRIX_PUBLICS
TO RESPONSABLE_VENTES;

Grce ce dernier exemple, le rle du responsable des ventes saccrot


encore, et il peut maintenant supprimer des lignes de la table :

GRANT DELETE
ON PRIX_PUBLICS
TO RESPONSABLE_VENTES;

Les contraintes dintgrit


rfrentielle peuvent
compromettre vos donnes
Vous pourriez croire que le contrle des fonctions de visualisation, de
cration, de modification et de suppression dans une table suffit vous
protger. En fait, un pirate comptent pourrait trs bien vous dvaliser en
utilisant une autre mthode.
Une base de donnes relationnelle correctement conue possde une
intgrit rfrentielle, ce qui signifie que les donnes dune table de cette
base sont en cohrence avec les donnes de toutes les autres tables. Pour
assurer cette intgrit rfrentielle, les concepteurs de bases de donnes
appliquent aux tables des contraintes qui limitent ce quil est possible dy
saisir. Si votre base de donnes est dote de contraintes dintgrit
rfrentielle, un utilisateur peut avoir la possibilit de crer une nouvelle
table utilisant comme cl trangre une colonne dune table confidentielle.
Cette colonne sert alors de lien via lequel quelquun peut subtiliser des
informations confidentielles.
Prcisons cette ide. Vous tes un clbre analyste boursier, disons de Wall
Street. Beaucoup de gens croient en la pertinence de vos achats, si bien que
chaque fois que vous ngociez des actions pour le compte de vos clients, de
nombreuses personnes suivent le mouvement, ce qui fait monter les cours.
Vous conservez vos analyses dans une base de donnes qui contient une
table nomme QUATRE_ETOILES. Toutes vos recommandations les plus
prcieuses y sont stockes. Bien entendu, vous restreignez laccs la table
QUATRE_ETOILES de manire 1) que seuls vos clients payants puissent
y accder et 2) quils ne puissent le faire que quand vous les y autorisez
(par le biais par exemple dune lettre dinformation priodique).
Cependant, vous restez vulnrable si quelquun peut crer une nouvelle
table qui utilise le nom dune colonne de QUATRE_ ETOILES comme
cl trangre, comme dans lexemple suivant :

CREATE TABLE BONNES_ACTIONS (


ACTION CHARACTER (30) REFERENCES QUATRE_ETOILES
);

Le pirate peut maintenant essayer dinsrer le nom de chaque action cote


en Bourse. Les insertions russies lui indiqueront quelles actions sont
stockes dans votre table confidentielle, et il ne lui faudra pas beaucoup de
temps pour piller vos si prcieuses informations.
Vous pouvez vous protger de tels assauts en faisant trs attention lorsque
vous saisissez des instructions telles que celle-ci :

GRANT REFERENCES (ACTION)


ON QUATRE_ETOILES
TO JESUISUN_HACKER;

Clairement, jexagre ici. Vous ne donneriez jamais accs une table


critique une personne qui ne serait pas digne de confiance, nest-ce pas ?
Du moins, si vous avez ralis ce que vous faites. Toutefois, les pirates ne
matrisent pas seulement la technique de nos jours. Ils sont aussi des experts
de lingnierie sociale, lart de tromper les gens pour leur faire faire ce
quils ne feraient pas normalement. Mfiez-vous de ceux qui mentionnent
quoi que ce soit en lien avec des informations confidentielles.
vitez daccorder des privilges des personnes qui pourraient en abuser.
Vous ntes pas dispos prter votre voiture quelquun pour un long
voyage ? Alors ne lui accordez pas de privilge REFERENCE sur une
table que vous jugez importante.
La liste suivante dcrit deux autres bonnes raisons de naccorder des
privilges quavec parcimonie :
Si lautre personne (le pirate) spcifie une contrainte sur
BONNES_ACTIONS en utilisant loption RESTRICT et que
vous tentez ensuite de supprimer une ligne de votre table,
le SGBD vous informera que vous ne pouvez pas le faire car
ce serait violer lintgrit relationnelle.

Si vous voulez utiliser la commande DROP pour dtruire


votre table, vous verrez quil vous faudra dabord attendre
que lautre personne (toujours le mchant pirate) ait
supprim sa contrainte (ou sa table).

Pour conclure, retenez que permettre une autre personne de spcifier des
contraintes dintgrit sur votre table gnre non seulement des failles de
scurit, mais aussi la met dans une position o elle pourrait vous barrer le
chemin

Dlguer la responsabilit de la
scurit
Si vous voulez que votre systme reste scuris, vous devez svrement
limiter lattribution des privilges daccs ainsi que le nombre de
personnes auxquelles vous les accordez. Cependant, les gens qui narrivent
pas travailler parce quils sont bloqus par de trop grandes restrictions
risquent de vous harceler du matin au soir. Pour viter la dpression,
nhsitez pas dlguer certaines responsabilits dans la gestion de la
scurit de votre base de donnes. Considrez lexemple suivant :

GRANT UPDATE
ON PRIX_PUBLICS
TO RESPONSABLE_VENTES WITH GRANT OPTION

Cette instruction ressemble au prcdent exemple GRANT UPDATE en ce


que cette instruction permet au responsable des ventes de mettre jour la
liste des prix. Cependant, elle lui donne aussi le droit de rtrocder ce
privilge nimporte quelle autre personne. Si vous utilisez cette forme de
linstruction GRANT, vous choisissez non seulement de faire confiance la
personne laquelle vous accordez le privilge, mais aussi celles qui
cette personne le transmettra.
La forme ultime de la confiance, et donc la forme ultime de vulnrabilit,
est dexcuter une instruction telle que celle-ci :

GRANT ALL PRIVILEGES


ON QUATRE_ETOILES
TO BENEDICT_ARNOLD WITH GRANT OPTION;

Faites trs attention quand vous utilisez de telles instructions (puisque vous
donnez par ricochet tous les privilges la plante entire).
II
Utiliser SQL pour crer des bases
de donnes

DANS CETTE PARTIE :

Crer des structures simples.

tablir des relations entre les tables.


Chapitre 4
Crer et maintenir une simple
structure de base de donnes
DANS CE CHAPITRE :
Crer, modifier et supprimer une table de base de donnes en utilisant un
RAD.

Crer, modifier et supprimer une table de base de donnes en utilisant SQL.

Migrer votre base de donnes vers un autre SGBD.

L
informatique volue si vite que la succession des gnrations peut
parfois paratre confuse. Les langages de haut niveau (ou de troisime
gnration) tels que FORTRAN, COBOL, Basic, Pascal et C furent les
premiers utiliser les bases de donnes. Quelque temps plus tard, des
langages spcifiquement conus pour les bases de donnes tels que dBase,
Paradox et R:BASE (troisime gnration et demie ?) firent leur apparition.
La dernire tape de cette volution est lmergence denvironnements de
dveloppement tels quAccess, Delphi, IntraBuilder et C++ Builder
(langages de quatrime gnration ou L4G) qui permettent de crer des
applications avec trs peu de programmation procdurale, voire aucune.
Mais nous nen sommes dj plus ces gnrations, depuis lapparition
denvironnements de dveloppement rapides (RAD, pour Rapid
Application Development) et les environnements intgrs de dveloppement
(IDE pour Integrated Development Environnments) tels quEclipse et Visual
Studio. NET, qui peuvent tre utiliss avec de nombreux langages (tels que
C, C++, C#, Python, Java, Visual Basic ou PHP). Vous pouvez les utiliser
pour assembler des composants applicatifs et raliser ainsi une application.
Du fait que SQL nest pas un langage complet, il nappartient pas une des
catgories que je viens de prsenter. Il utilise des instructions la manire
des langages de troisime gnration, mais il est pour lessentiel non
procdural, comme le sont les L4G. Mais peu importe la classification de
SQL. Vous pouvez lutiliser en conjonction avec tous les principaux outils
de dveloppement des langages de troisime et quatrime gnration. Vous
pouvez crire le code SQL vous-mme ou le faire gnrer par
lenvironnement de dveloppement. Le code produit est dans les deux cas
du pur SQL.
Dans ce chapitre, je vais vous expliquer comment crer, modifier et
supprimer une table en utilisant un RAD. Je vous montrerai ensuite comment
faire la mme chose en SQL.

Crer une simple base de donnes


en utilisant un outil RAD
Les gens utilisent des bases de donnes pour conserver la trace
dinformations importantes. Parfois linformation quils cherchent
enregistrer est simple, parfois elle ne lest pas. Un bon systme de gestion
de bases de donnes fournit ce dont vous avez besoin dans chaque cas.
Quelques-uns sappuient sur SQL. Dautres, comme les outils RAD, vous
proposent un environnement graphique orient objet. Quelques SGBD
proposent les deux. Dans les sections suivantes, je vous montrerai comment
crer une base de donnes laide dun outil graphique. Jutilise Microsoft
Access, mais la procdure est la mme avec dautres environnements de
dveloppement pour Windows.

Un scnario probable
La premire tape dans la cration dune base de donnes consiste
dterminer les informations que vous voulez conserver. Prenons un
exemple : supposons que vous veniez de gagner 11 millions deuros au
Loto. Des gens dont vous naviez plus entendu parler depuis des annes et
des amis de trente ans se rappellent votre bon souvenir. Certains vous
proposent dinvestir dans des affaires qui rapporteront coup sr. Dautres
reprsentent des causes pour lesquelles vous devriez faire des dons. En bon
gestionnaire, vous avez tt fait de raliser que certaines affaires semblent
moins intressantes que dautres. Et que certaines causes valent moins
quon les dfende que dautres. Vous dcidez de stocker toutes les
propositions qui vous sont faites dans une base de donnes afin de les
recenser et de les tudier quitablement.
Vous choisissez de conserver la trace des informations suivantes :
Nom.

Prnom.

Adresse.

Ville.

tat ou province.

Code postal.

Tlphone.

Relation (votre relation cette personne).

Proposition.

Affaire ou uvre.

Comme vous ne voulez pas vous perdre en subtilits, vous dcidez de


stocker toutes ces informations dans une seule table de la base de donnes.

Crer une table de base de


donnes
Lorsque vous lancez lenvironnement de dveloppement Access 2013, vous
tes accueilli par lcran repris sur la Figure 4.1. De l, vous pouvez crer
une table de base de donnes de diffrentes manires. Je vais commencer
par le mode Feuille de donnes, car elle vous montre comment crer une
base de donnes partir de rien.
FIGURE 4.1 Lcran daccueil de Microsoft Access.

Crer une table de base de donnes dans


le mode Feuille de donnes
Par dfaut, Access 2013 souvre sur le mode Feuille de donnes. Pour crer
une base de donnes Access dans cette vue, double-cliquez sur le modle
Base de donnes du Bureau vide. Votre feuille de donnes Access attend
que vous saisissiez des donnes dans Table 1, la premire table de votre
base de donnes, comme sur la Figure 4.2. Vous pourrez modifier le nom de
la table pour lui donner un nom plus signifiant ultrieurement. Access donne
votre base de donnes le nom par dfaut Base de donnes1 (ou
Base de donnes31 si vous avez dj cr 30 bases de donnes et
que vous ne vous tes pas donn la peine de les renommer). Il vaut mieux
donner un nom signifiant la base de donnes pour viter toute confusion.
Cest une mthode qui part de rien, mais il existe dautres manires de crer
une table dans une base de donnes Access. Par la suite, nous utiliserons le
mode Cration.

Crer une table dans une base de


donnes en vue Cration
Dans le mode Feuille de donnes (reprsente sur la Figure 4.2), il est trs
facile de crer une table de base de donnes : vous navez qu commencer
saisir les donnes. Toutefois, cette manire de faire est sujette aux erreurs,
car on oublie rapidement des dtails. Il vaut mieux utiliser le mode Cration
en suivant les tapes suivantes :

FIGURE 4.2 Le mode Feuille de donnes dans lenvironnement de dveloppement


Access.

1. Dans le mode Feuille de calcul (par dfaut), cliquez sur


longlet Accueil dans le ruban et cliquez sur Affichage
en dessous de licne qui se trouve dans langle
suprieur gauche de la fentre. Slectionnez Mode
cration dans le menu droulant.

Lorsque vous choisissez le mode Cration, une bote de


dialogue apparat pour vous demander le nom de la table.

2. Saisissez LOTO et cliquez OK.


Le mode Cration apparat (reprsent sur la Figure 4.3).

Notez que la fentre est divise en zones fonctionnelles.


Deux dentre elles sont particulirement utiles pour crer
des tables de bases de donnes :
Les options du mode Cration : Un menu en haut de la
fentre donne accs aux options Accueil, Crer,
Donnes externes, Outils de base de donnes et
Cration.

Lorsque ce ruban est affich, les outils disponibles


dans le mode Cration sont reprsents par des
icnes se trouvant immdiatement sous le menu. Sur
la Figure 4.3, la mise en exergue montre que les
icnes Cration et Cl primaire sont slectionnes.

FIGURE 4.3 Lcran de dmarrage du mode Cration.


Le panneau des proprits du champ : Dans cette
zone qui permet de dfinir les champs de la base de
donnes, le curseur clignote dans la colonne Nom du
champ de la premire ligne. Access suggre que vous
spcifiez ici une cl primaire, que vous la nommiez
ID, et il lui donnera automatiquement le type de
donnes NumroAuto.

NumroAuto est un type de donnes Access, et non un type


de donnes standard en SQL. Il incrmente un entier dans
le champ chaque fois que vous ajoutez un nouvel
enregistrement dans la table. Ce type de donnes vous
garantit que le champ que vous utilisez comme cl primaire
ne prendra pas deux fois la mme valeur, toute cl primaire
devant tre unique.

3. Dans la zone Proprits du champ, modifiez Nom du


champ pour la cl primaire en le passant de ID NUME-
RO_PROPOSITION.

Le nom propos dans Nom du champ pour la cl primaire,


ID, nest pas trs explicite. Si vous prenez lhabitude de le
changer en quelque chose de plus signifiant (et/ou de
fournir une description dans la colonne Description), il sera
plus facile de garder une trace de la raison dtre des
champs dans votre base de donnes. Ici, les noms des
champs sont suffisamment explicites.

La Figure 4.4 vous montre quoi ressemble la cration de la


table de la base de donnes cette tape.
4. Dans le panneau Proprits du champ, vrifiez les
hypothses formules automatiquement par Access
sur le champ NUMERO_PROPOSITION.

La Figure 4.4 montre que ces hypothses sont les


suivantes :
La taille du champ est Entier long.

Les nouvelles valeurs sont gnres par


incrmentation.

FIGURE 4.4 Utilisez un nom de champ signifiant pour dfinir la cl primaire.

Lindexation est active et les doublons ne sont pas


autoriss.

Lalignement du texte est gnral.

Comme cest souvent le cas, les hypothses formules par


Access conviennent ce que vous souhaitez faire. Si ce
ntait pas le cas, vous pourriez les modifier en saisissant de
nouvelles valeurs.

5. Spcifiez le reste des champs que vous souhaitez voir


dans la table.

La Figure 4.5 vous montre le mode Cration une fois que


vous avez saisi le champ Prnom.

FIGURE 4.5 La fentre de cration de la table une fois que vous avez dfini Prnom.

Le type de donnes pour PRENOM est Texte court


plutt que NumroAuto, si bien que les proprits du
champ sont diffrentes. En loccurrence, Access a
donn PRENOM la taille de champ par dfaut, cest-
-dire 255 caractres. Je ne connais pas grand monde
dont le prnom soit aussi long. Access est assez fut
pour nallouer de mmoire quen fonction de ce qui
est saisi. Il nalloue pas 255 octets laveugle.
Toutefois, dautres environnements de
dveloppement peuvent ne pas en tre capables.
Jaime prciser une valeur raisonnable comme taille
de champ. Cela mvite des problmes quand je
passe dun environnement de dveloppement un
autre.
Lhypothse par dfaut dAccess est que Prnom
nest pas un champ obligatoire. Vous pourriez saisir
un enregistrement dans la table LOTO et laisser ce
champ vide, ce qui permettrait de tenir compte des
gens qui nont quun nom, comme Cher ou Bono.

ANTICIPEZ LORSQUE VOUS CONCEVEZ VOTRE TABLE

Dans certains environnements de dveloppement (diffrents


dAccess), rduire la taille du champ Prnom 15 octets permet
dconomiser 240 octets pour chaque enregistrement dans la base de
donnes si vous utilisez des caractres ASCII (UTF-8), 480 octets si
vous utilisez des caractres UTF-16, ou 960 octets si vous utilisez des
caractres UTF-32. Lconomie devient vite considrable. Tant que
vous y tes, jetez un il sur les autres hypothses par dfaut
formules sur les autres proprits du champ, et essayez danticiper
comment vous voudrez les utiliser tandis que la base de donnes
senrichira. Il faut se proccuper de certaines tout de suite pour plus
defficacit (la taille du champ est un bon exemple) ; dautres ne
sappliqueront que dans des cas obscurs.

Vous aurez sans doute remarqu quune autre proprit de champ


revient souvent : la proprit Index. Si vous nenvisagez pas de
rcuprer la valeur du champ, ne gaspillez pas la puissance de votre
ordinateur pour lindexer. Toutefois, notez que dans une grande table
comportant de nombreuses lignes, vous pouvez acclrer
considrablement la rcupration en indexant le champ que vous
utilisez pour identifier lenregistrement que vous souhaitez rcuprer.
En matire de conception de tables de bases de donnes, le diable se
loge dans les dtails.

6. Passez la taille du champ 15.

Pour savoir pourquoi cest une bonne ide, reportez-vous


lencadr Anticipez lorsque vous concevez votre table .

7. Pour vous assurer que vous pouvez rcuprer un


enregistrement rapidement dans la table LOTO partir
de Prnom, passez la proprit Index de ce champ
Oui, comme sur la Figure 4.6.

FIGURE 4.6 La fentre de cration une fois que Prnom a t dfini.


La Figure montre quelques modifications que jai apportes
dans le panneau Proprits du champ :
Jai rduit la taille maximale du champ de 255 20.

Jai pass Null interdit Oui, Chane vide autorise


Non et Index Oui - Avec doublons. Je veux que
chaque proposition comprenne le nom de famille de
la personne qui en est lauteur. Un nom de taille nulle
nest pas autoris, et le champ Nom doit tre index.

Jai autoris les doublons ; deux ou plusieurs


personnes peuvent parfaitement avoir le mme nom
de famille. Cest pratiquement certain dans le cas de
la table LOTO ; jattends des propositions de mes
trois frres, ainsi que de mes enfants et de ma fille
qui nest pas encore marie, sans mentionner mes
cousins.

Loption Oui - Sans doublons, que je nai pas choisie,


serait adapte pour un champ qui serait la cl
primaire de la table. En effet, la cl primaire dun
enregistrement devrait toujours tre unique.

8. Saisissez le reste des champs, en modifiant la


proprit Taille du champ comme ncessaire selon le
cas.

La Figure 4.7 vous prsente le rsultat.


FIGURE 4.7 La fentre de cration de la table une fois que tous les champs ont t dfinis.

Comme vous pouvez le constater sur la Figure 4.7, le champ


pour les entreprises et les associations (AFFAIRE_ OEUVRE)
nest pas index. Il nest pas utile dindexer un champ qui na
que deux entres possibles ; lindexation ne viendrait pas
rduire la slection dans une proportion telle quelle en
vaudrait la peine.

Access utilise le terme de champ plutt que celui dattribut


ou de colonne. Le programme ntait pas initialement
relationnel ; il utilisait une terminologie base de fichier,
champ et enregistrement, commune aux systmes base de
fichiers plat.

9. Enregistrez votre table en cliquant sur licne figurant


une disquette dans langle suprieur gauche de la
fentre.
Il est bon danticiper lorsque vous dveloppez une base de
donnes. Par exemple, cest une bonne ide que
denregistrer frquemment votre travail, cliquez simplement
sur licne figurant une disquette de temps en temps. De la
sorte, vous vous pargnerez de reprendre votre travail sil
survient une coupure de courant ou un vnement imprvu.
Aussi, mme si vous pouvez parfaitement donner le mme
nom la base de donnes et lune de ses tables, vous
risquez dinduire en confusion les administrateurs et les
utilisateurs par la suite. Il vaut donc mieux se faire une rgle
dutiliser des noms diffrents.
Une fois que vous aurez enregistr votre table, vous dcouvrirez que vous
devrez modifier un peu votre cration, comme je lexplique dans la section
suivante Modifier la structure de votre table .

Modifier la structure de votre table


Bien souvent, les bases de donnes que vous concevez ne tournent pas rond
ds la premire fois. Si vous travaillez pour le compte dun client, vous
pouvez tre quasiment certain que ce dernier va revenir la charge pour
vous demander de modifier la base de donnes, de sorte quelle conserve la
trace de telle ou telle information supplmentaire.
Si vous laborez la base de donnes pour votre propre compte, vous vous
heurterez probablement aux limitations de votre structure, car il est
impossible de tout prvoir lors de la conception. Par exemple, vous allez
peut-tre recevoir des propositions depuis diverses contres et donc devoir
ajouter une colonne PAYS. Ou alors vous dciderez de conserver ladresse
de messagerie de vos contacts, et vous devrez insrer une colonne
COURRIEL. Dans tous les cas, il vous faudra revenir sur la structure que
vous avez cre. Dans cette section, je vais utiliser Access afin de modifier
la table que je viens de crer. Notez que les autres outils RAD disposent de
fonctionnalits semblables.
Sil devient ncessaire que vous mettiez jour les tables de votre base de
donnes, prenez un instant pour passer en revue tous les champs quelles
utilisent. Par exemple, vous pourriez en venir ajouter un second champ
ADRESSE pour les personnes dont ladresse est complexe et un champ
PAYS pour tenir compte des propositions manant dautres pays.
Quoiquil soit plutt facile de mettre jour les tables dune base de
donnes, vous devriez viter de le faire autant que possible. Toute
application qui dpend de la prcdente structure de la base de donnes
risque de ne plus pouvoir fonctionner et devra tre modifie. Si vous avez
beaucoup dapplications de ce type, la tche risque dtre trs pnalisante.
Essayez danticiper les volutions ncessaires. Il vaut mieux passer un peu
plus de temps sur la conception de la base de donnes que davoir mettre
jour des applications crites il y a des annes. En effet, vous risquez
davoir oubli comment elles fonctionnent, et de ne pas pouvoir les mettre
jour.
Pour insrer de nouvelles lignes et tenir compte dvolutions, ouvrez la
table et suivez ces tapes :

1. Dans la fentre de cration de la table, cliquez du


bouton droit sur le petit carr color sur la gauche du
champ VILLE pour slectionner la ligne, et
slectionnez Insrer une ligne dans le menu qui
apparat.

Une ligne vierge apparat au-dessus de lemplacement du


curseur, qui dcale les lignes existantes, comme sur la
Figure 4.8.

2. Saisissez les champs que vous souhaitez ajouter


votre table.

Jai ajout le champ ADRESSE2 au-dessus du champ VILLE,


et un champ PAYS au-dessus du champ TELEPHONE.

3. Une fois que vous avez termin vos modifications,


enregistrez la table avant de la fermer.

Le rsultat doit ressembler la Figure 4.9.


Crer un index
Comme le nombre de propositions que vous recevez peut facilement se
compter en centaines, vous aurez besoin dun outil vous permettant disoler
rapidement les enregistrements qui vous intressent en fonction de diffrents
critres. Supposons par exemple que vous souhaitiez regarder uniquement
les propositions de toutes les personnes qui se prtendent votre frre. En
partant de lide quaucun de vos frres na chang son nom pour des motifs
professionnels ou futiles, il est facile de srier les propositions
correspondantes en vous basant sur la valeur du champ Nom, comme le
montre la requte SQL ad hoc suivante :

SELECT * FROM POUVOIR


WHERE Nom = Marx ;

FIGURE 4.8 La fentre de cration de la table aprs avoir rajout un emplacement


pour une seconde ligne dadresse.
FIGURE 4.9 Votre table rvise devrait ressembler ceci.

Cependant, cette stratgie ne peut pas sappliquer aux propositions qui


manent de vos beaux-frres ou de vos belles-surs. Il est possible de se
concentrer sur ces propositions en tudiant la valeur dun autre champ :

SELECT * FROM POUVOIR


WHERE Relation = beau-frre

OR
Relation = belle-soeur ;

Toutes ces requtes fonctionnent parfaitement, mais elles risquent de ne pas


sexcuter rapidement si POUVOIR contient beaucoup de donnes (des
dizaines de milliers denregistrements). En effet, SQL passe la table en
revue ligne par ligne, la recherche des entres qui pourraient satisfaire la
clause WHERE. Vous pouvez considrablement acclrer les choses en
associant un index la table POUVOIR (un index est une table de
pointeurs ; chaque ligne dans lindex pointe vers une ligne correspondante
de la table).
Vous pouvez dfinir un index propre chacune des manires par lesquelles
vous comptez accder vos donnes. Si vous ajoutez, modifiez ou
supprimez des lignes dans la table, vous naurez plus la trier de nouveau :
il vous suffira dactualiser lindex. Et cette mise jour seffectue beaucoup
plus rapidement que le tri dune table. Une fois que vous disposerez dun
index correspondant au tri que vous souhaitez, vous pourrez lutiliser pour
accder aux lignes de la table presque instantanment.
Comme NUMERO_PROPOSITION est unique et court, utiliser ce champ
est le moyen le plus rapide pour accder un enregistrement donn. Cest
donc un candidat idal pour devenir cl primaire. Pour la mme raison, la
cl primaire de chaque table et de toutes les tables devrait toujours tre
indexe. Voil qui tombe dailleurs bien, car Access indexe
automatiquement les cls primaires ! Cependant, vous devez connatre la
valeur NUMERO_ PROPOSITION de lenregistrement que vous cherchez
pour pouvoir accder ces donnes. Cest pourquoi vous pourriez crer
des index bass sur dautres champs tels que NOM, CODE POSTAL ou
RELATION. Prenons un exemple concret. Dans le cas dune table indexe
sur le champ Nom, ds quune recherche trouve une ligne contenant Marx,
elle a du mme coup dtect tous les autres enregistrements ayant la mme
valeur dans la colonne Nom. Vous pouvez donc retrouver Chico,
Groucho, Harpo et Zeppo pratiquement aussi vite que Chico seul.
La gestion dun index provoque une charge de travail supplmentaire, et
donc ralentit un peu votre systme. Cependant, il permet daccder
beaucoup plus rapidement aux donnes. Vous devez donc vous efforcer de
trouver un bon compromis entre ces deux ples contradictoires.
Voici quelques conseils pour vous aider choisir les bons champs pour
indexer votre table :

Indexez les champs que vous utilisez le plus souvent. De


cette manire, il sera possible daccder rapidement aux
donnes sans que le surcrot de travail impos au systme
ne pnalise inconsidrment vos recherches.

Ne perdez pas votre temps crer des index pour des


champs qui ne vous servent jamais dans vos critres. Ce
serait un gaspillage inutile de temps et despace.

Crer un index pour un champ dont la valeur ne permet


pas didentifier formellement une srie cohrente
denregistrements na gnralement pas de sens. Par
exemple, indexer le champ AFFAIRE_OEUVRE ne ferait que
diviser votre table en deux catgories. Ce nest donc pas un
candidat intressant.

Lefficacit dun index varie dune implmentation une autre. Si vous


faites migrer une base de donnes dune plate-forme une autre, il est
possible que les index qui donnaient de bons rsultats sur le premier
systme ne fonctionnent plus aussi bien sur le second. En fait, ils peuvent
mme pnaliser vos performances. Vous devez optimiser la gestion des
index en fonction de chaque SGBD et de chaque configuration matrielle.
Essayez diffrents schmas dindexation pour juger de celui qui vous
procure les meilleures performances densemble. Optimisez vos index de
manire limiter au maximum leur impact ngatif sur les recherches et la
mise jour des donnes.
Pour indexer la table POUVOIR, slectionnez simplement Oui pour Index
dans le panneau Proprits du champ dans la fentre de cration de la table.
Access cre automatiquement un index pour CodePostal, car ce champ
est souvent utilis pour rcuprer des informations. Access indexe aussi
automatiquement la cl primaire.
Vous pouvez voir que CodePostal nest pas une cl primaire et nest
pas ncessairement unique. Cest exactement linverse pour
NUMERO_PROPOSITION. Ajoutez des index supplmentaires pour Nom
et Relation, car ces champs serviront probablement de critres lors de
recherches.
Une fois que vous avez cr tous vos index, sauvegardez la nouvelle
structure de la table avant de la fermer.
Si vous utilisez un autre RAD que Microsoft Access, la dmarche dcrite
dans cette section ne sapplique pas votre situation. Cependant, le
processus gnral devrait tre le mme.
Supprimer une table
Au cours de la construction dune table telle que POUVOIR, il se peut que
vous passiez par quelques versions intermdiaires qui ne correspondent
finalement pas vos souhaits. La prsence de ces tables inacheves peut
induire vos futurs utilisateurs en erreur. Vous feriez donc mieux de les
supprimer tant que vous savez quoi elles correspondent. Pour ce faire,
cliquez du bouton droit sur la table que vous souhaitez supprimer dans la
liste Toutes les tables sur le ct gauche de la fentre. Un menu apparat, et
lune des options quil propose est Supprimer. Lorsque vous cliquez sur
Supprimer, comme le montre la Figure 4.10, la table est retire de la base
de donnes.

FIGURE 4.10 Slectionnez Supprimer pour supprimer une table.

Si Access supprime une table, il supprimera aussi toutes celles qui en


dpendent, ainsi que tous ses index.
Crer une table avec le DDL de SQL
Toutes les fonctions de dfinition de la base de donnes dont vous disposez
via un outil RAD tel quAccess peuvent aussi tre effectues en SQL. Plutt
que de cliquer dans des menus avec la souris, vous devrez saisir des
commandes au clavier. Certaines personnes, qui prfrent manipuler des
objets visuels, pensent que les outils RAD sont plus faciles dutilisation.
Dautres, plus orientes vers la formulation de leur besoin par des
squences dinstructions logiques, trouvent que les instructions SQL sont
plus simples.
Certains concepts se prtent mieux une reprsentation graphique, tandis
que dautres se grent plus directement sous SQL. Il est donc utile de bien
matriser lune et lautre de ces mthodes.
Dans les sections suivantes, jutilise SQL pour effectuer les oprations de
cration, modification et suppression de table que nous venons deffectuer
laide du RAD.

Utiliser SQL avec Microsoft Access


Access est par essence un outil de dveloppement rapide (RAD) qui ne
ncessite pas de programmation. Il est videmment possible dcrire des
instructions SQL sous Access, mais vous devrez pour cela passer par la
porte de derrire Voici comment ouvrir un diteur (basique au demeurant)
dans lequel vous saisirez votre code SQL :

1. Ouvrez votre base de donnes et cliquez sur longlet


Crer pour afficher le ruban en haut de lcran.

2. Cliquez sur Cration de requte dans la section


Requtes.

La bote de dialogue Afficher la table apparat.

3. Slectionnez la table LOTO. Cliquez sur le bouton


Ajouter, puis sur Fermer pour fermer la bote de
dialogue.
Vous devriez voir safficher ce qui est reprsent sur la
Figure 4.11.

Une image de la table LOTO et de ses attributs apparat


dans la partie suprieure de la zone de travail, et une grille
Requte par exemple apparat dessous. Access attend que
vous saisissiez une requte en utilisant cette grille (vous
pourriez le faire, cest sr, mais cela ne vous apprendrait pas
utiliser SQL dans lenvironnement dAccess).

4. Cliquez sur longlet Accueil puis sur licne Affichage


dans langle gauche du ruban

Un menu apparat, qui contient les diffrents modes


auxquels vous pouvez accder, comme sur la Figure 4.12.

Lun de ces modes est la vue SQL.

FIGURE 4.11 Lcran Requte une fois la table LOTO slectionne.


FIGURE 4.12 Les modes de la base de donnes disponibles en mode Requte.

5. Cliquez sur Mode SQL pour afficher longlet de la


requte en SQL.

Comme vous le voyez sur la Figure 4.13, longlet de la


requte en SQL fait lhypothse (trs rationnelle) que vous
souhaitez rcuprer des informations de la table LOTO, si
bien quil a crit la premire partie de la requte pour vous.
Il ne sait pas exactement ce que vous souhaitez rcuprer,
si bien quil naffiche que ce dont il est certain.

Voici ce quil a crit pour vous :


FIGURE 4.13 La vue SQL de longlet Objet.

SELECT
FROM POUVOIR ;

6. Rajoutez un astrisque (*) la fin de la premire ligne


et ajoutez une clause WHERE aprs la ligne FROM.

Si vous avez dj saisi quelques donnes dans la table


LOTO, vous pourriez les rcuprer de cette manire :

SELECT *
FROM LOTO
WHERE Prenom = Max ;

Noubliez pas le point-virgule ( ;) qui termine la commande


SQL. Vous devez le reporter de sa position aprs LOTO la
fin de la ligne suivante.
7. Lorsque vous avez termin, cliquez sur licne figurant
une disquette.

Access vous demande de donner un nom votre nouvelle


requte.

8. Attribuez un nom votre instruction et cliquez OK.


Votre requte est sauvegarde et pourra tre excute tout moment.

Crer une table


Pour crer une table de base de donnes en SQL (du moins avec un SGBD
qui limplante pleinement), il vous suffit de saisir les mmes informations
que celles que vous avez spcifies en utilisant loutil RAD. La diffrence
est que loutil RAD vous aide en affichant une bote de dialogue du style
Cration de table et vous interdit dentrer des noms de champs, des types et
des longueurs qui ne sont pas valides.
SQL ne vous aide pas beaucoup. Vous devez savoir lavance exactement
ce que vous faites, car il vous faudra saisir la totalit de linstruction
CREATE TABLE avant que SQL ne commence la contrler pour vrifier
si elle contient ou non des erreurs. Jusque-l, vous tes totalement seul.
Linstruction qui cre une table de suivi des propositions identique celle
que nous avons dfinie prcdemment adopte la syntaxe suivante :

CREATE TABLE LOTO_SQL (


NUMERO_PROPOSITION INTEGER PRIMARY KEY,
PRENOM CHAR (15),
NOM CHAR (20),
ADRESSE CHAR (30),
VILLE CHAR (25),
ETAT_PROVINCE CHAR (2),
CODE_POSTAL CHAR (10),
PAYS CHAR (30),
TELEPHONE CHAR (14),
RELATION CHAR (30),
PROPOSITION CHAR (50),
AFFAIRE_OEUVRE CHAR (1) );

Comme vous pouvez le constater, linformation que contient linstruction


SQL est essentiellement la mme que celle que vous avez saisie via loutil
RAD. Cependant, SQL prsente lavantage dtre un langage universel. La
mme syntaxe fonctionne sur tous les systmes de gestion de bases de
donnes.
Dans Access 2013, la cration dobjets dans une base de donnes tels que
les tables est un peu plus complexe. Vous ne pouvez pas simplement saisir
la commande CREATE (comme vous venez de le voir) dans longlet de la
requte en SQL. Cest parce que cet onglet ne sert que doutil de requte ;
vous devez procder quelques actions supplmentaires pour informer
Access que vous souhaitez saisir une requte de dfinition de donnes plutt
quune requte normale qui ne fait que demander des informations figurant
dans la base de donnes. Une autre complication : comme la cration de
table pourrait compromettre la scurit de la base de donnes, elle est
interdite par dfaut. Vous devez indiquer Access quil sagit dune base de
donnes de confiance avant quil accepte la requte de dfinition de
donnes.
1. Cliquez sur longlet Crer dans le ruban pour afficher
les icnes relatives la cration.

2. Cliquez sur le mode Cration dans la section Requtes.

Cela affiche la bote de dialogue Afficher la table, qui


contient pour lheure plusieurs tables systmes en plus de
LOTO.

3. Slectionnez LOTO et cliquez sur le bouton Ajouter.

Comme vous lavez vu dans lexemple prcdent, une image


de la table LOTO et de ses attributs apparat dans la moiti
suprieure de lcran.

4. Cliquez sur le bouton Clone dans la bote de dialogue


Afficher la table.
5. Cliquez sur longlet Accueil, puis sur licne Affichage
gauche du ruban, et slectionnez Mode SQL dans la
liste droulante qui apparat.

Comme dans lexemple prcdent, Access vous a aid en


rajoutant SELECT FROM LOTO dans lditeur SQL. Cette
fois, vous nen voulez pas.

6. Supprimez SELECT FROM LOTO et saisissez la place la


requte de dfinition de donnes prsente plus tt,
comme suit :

CREATE TABLE LOTO_SQL (


NUMERO_PROPOSITION INTEGER PRIMARY KEY,
PRENOM CHAR (15),
NOM CHAR (20),
ADRESSE CHAR (30),
VILLE CHAR (25),
ETAT_PROVINCE CHAR (2),
CODE_POSTAL CHAR (10),
PAYS CHAR (30),
TELEPHONE CHAR (14),
RELATION CHAR (30),
PROPOSITION CHAR (50),
AFFAIRE_OEUVRE CHAR (1) );

cet instant, votre cran devrait ressembler la Figure 4.14.


FIGURE 4.14 La requte de dfinition de donnes pour crer une table.

7. Aprs avoir cliqu sur longlet Crer dans le ruban,


cliquez sur le point dexclamation de licne Excuter.

Ce faisant, vous excutez la requte, ce qui cre la table


LOTO_SQL (comme sur la Figure 4.15).

Vous devriez voir apparatre LOTO_SQL sous Tous les objets


Access dans la colonne figurant sur le ct gauche de la
page. Dans ce cas, vous avez de la chance. Ou alors, vous ne
voyez pas la table dans la liste Tous les objets Access. Si
cest le cas, continuez de lire.
FIGURE 4.15 Cration de la table LOTO_SQL.

Access 2013 fait de gros efforts pour vous protger contre


des hackers mal intentionns et des utilisateurs
imprudents. Comme excuter une requte de dfinition de
donnes peut constituer un danger pour la base de
donnes, Access interdit par dfaut lexcution dune telle
requte. Si vous rencontrez cet obstacle, LOTO_SQL
napparatra pas dans la colonne sur la gauche de la fentre
car la requte naura pas t excute.

la place, vous verrez apparatre ce message dans la barre


de messages qui se trouve sous le ruban :

Alerte Scurit: Du contenu dans la base de


donnes a
t dsactiv.
Si vous voyez ce message, suivez ces tapes :

8. Cliquez sur longlet Ficher, et dans le menu qui Figure


sur le ct gauche de lcran, slectionnez Options.

La bote de dialogue Options apparat.

9. Slectionnez Centre de gestion de la confidentialit


dans la base de donnes Options Access.

10.Cliquez sur le bouton Paramtres du centre de gestion


de la confidentialit lorsquil apparat.

11.Slectionnez Barre de messages dans le menu sur la


gauche, puis spcifiez Afficher la barre de messages en
cliquant son bouton sil nest pas dj slectionn.

12.Cliquez pour revenir en arrire, l o vous avez tent


dexcuter la requte de dfinition de donnes qui cre
la table LOTO_SQL.

13.Excutez la requte.
Tous les efforts que vous consacrez lapprentissage de SQL seront payants
long terme, car SQL est parti pour durer. Le temps pass devenir un
expert dun outil RAD est beaucoup moins rentable. Aussi sophistiqu que
soit un outil RAD, vous pouvez tre certain quil sera dpass par une
nouvelle technologie dans les cinq annes venir. Si vous pensez pouvoir
amortir le cot de votre formation dans ce dlai, parfait ! Formez-vous.
Sinon, il serait sage de vous en tenir SQL. Et la mme remarque vaut pour
lensemble de votre environnement de travail.

Crer un index
Les index sont trs importants dans les bases de donnes. Ils servent de
pointeurs dans des tables qui contiennent des donnes intressantes. Si vous
utilisez un index, vous pouvez accder directement un enregistrement
particulier sans avoir balayer squentiellement la table, enregistrement
par enregistrement, la recherche de celui que vous cherchez. Sans index, il
vous faudrait peut-tre attendre des annes et non des secondes pour
extraire une information dune trs grosse table. Des annes, cest peut-tre
beaucoup. Mais un temps suffisant pour que vous finissiez par vous lasser et
abandonner la recherche, cela cest certain.
Dune manire surprenante, le standard SQL ne propose aucune instruction
pour crer un index. Les diteurs de SGBD doivent donc crire eux-mmes
cette fonctionnalit. Et comme les implmentations ne sont pas
standardises, elles diffrent les unes des autres. La plupart des diteurs
proposent la cration dun index sous la forme dune instruction CREATE
INDEX.
Mme si deux diteurs utilisent les mmes mots, cela ne signifie pas pour
autant que ces deux commandes agissent de la mme manire. Vous devrez
probablement spcifier des clauses spcifiques limplmentation. tudiez
donc attentivement la documentation de votre SGBD pour lucider ce point.

Modifier la structure dune table


Vous pouvez utiliser linstruction ALTER TABLE pour modifier la
structure dune table qui existe dj. Contrairement loutil RAD qui
affiche la structure de cette table, SQL vous oblige la connatre lavance
pour la modifier. Cest videmment moins commode. Par contre,
lutilisation de SQL est gnralement la mthode la mieux adapte si vous
voulez inclure les instructions qui modifient la table dans un programme
dapplication.
Pour ajouter un second champ adresse la table LOTO_SQL, utilisez
linstruction DDL suivante :

ALTER TABLE LOTO_SQL


ADD COLUMN ADDRESS_2 CHAR (30);

Vous navez pas besoin dtre un technogourou du SQL pour comprendre ce


quelle veut dire. Cette instruction modifie une table appele LOTO_SQL
en y ajoutant une colonne. La colonne sappelle ADRESSE_2, elle est de
type CHAR (cest donc une chane) et sa longueur est de 30 caractres. Cet
exemple vous montre quil est trs facile de modifier une table laide de
commandes DDL.
Le standard SQL fournit cette instruction pour ajouter une colonne. Il
propose symtriquement une instruction vous permettant den supprimer
une :

ALTER TABLE LOTO_SQL


DROP COLUMN ADDRESS_2;

Supprimer une table


Il est trs facile de supprimer des tables dont vous navez plus besoin et qui
encombrent votre disque dur :

DROP TABLE LOTO_SQL;

Comment cela pourrait-il tre plus simple ? Si vous supprimez une table,
vous dtruisez aussi toutes ses donnes et ses mtadonnes. Il nen reste
rien. Cela fonctionne bien, sauf si une autre table de la base de donnes fait
rfrence celle que vous essayez de supprimer. Cela sappelle une
contrainte dintgrit rfrentielle. Dans ce cas, SQL vous produira un
message plutt que de supprimer la table.

Supprimer un index
Si vous supprimez une table en utilisant linstruction DROP TABLE, vous
supprimez aussi les index qui y sont associs. Cependant, il peut arriver que
vous souhaitiez conserver une table mais supprimer un de ses index. Le
standard SQL ne dfinit pas dinstruction du genre DROP INDEX. Par
contre, vous la trouverez dans la plupart des implmentations. Cette
commande se rvle fort utile quand votre systme ralentit, que les
utilisateurs commencent rclamer de nouveaux ordinateurs plus puissants,
et que vous dcouvrez que vos tables ne sont pas indexes de la meilleure
manire.

De la portabilit
Toute implmentation de SQL que vous pourrez utiliser disposera trs
certainement dextensions qui assurent des fonctionnalits qui ne sont pas
mentionnes dans le standard SQL. Certaines de ces fonctionnalits feront
probablement leur apparition dans la prochaine version du standard.
Dautres sont totalement spcifiques certaines implmentations et le
resteront vraisemblablement.
Ces extensions facilitent la cration dapplications, si bien quil est tentant
de les utiliser. Mais noubliez pas quy recourir prsente aussi des
inconvnients. Si vous voulez un jour migrer votre application vers une
autre implmentation, vous devrez rcrire les sections de votre code dans
lesquelles vous faites rfrence aux extensions que la nouvelle
implmentation ne reconnat pas. Pensez-y avant de faire appel aux
extensions incluses dans votre SGBD actuel. Si elles vous font gagner du
temps court terme, elles peuvent aussi vous en faire perdre plus long
terme.
Plus vous en apprendrez sur les particularits de votre systme, mieux vous
serez mme de prendre les bonnes dcisions. Par exemple, pour aboutir
la conclusion quil existe une autre solution un problme x que de passer
par des extensions de votre SGBD.
Chapitre 5
Crer une base de donnes
relationnelle multitable
DANS CE CHAPITRE :
Dcider de ce quil faut inclure dans une base de donnes.

Dterminer les relations entre les donnes.

Lier des tables laide de cls.

Prserver lintgrit des donnes ds la conception.

Normaliser une base de donnes.

D
ans ce chapitre, je vous prsente un exemple de base de donnes qui
comporte plusieurs tables. La premire tape de la conception dune
telle base consiste dcider de ce quil faut y inclure et de ce quil faut
en exclure. Les tapes suivantes visent tablir des relations entre les
donnes et configurer les tables en consquence. Je vous explique aussi
comment utiliser les cls, qui permettent daccder rapidement des
enregistrements spcifiques ainsi qu des index.
Une base ne doit pas simplement contenir vos donnes. Elle doit aussi les
protger contre toute forme de corruption. Dans la dernire partie de ce
chapitre, je vous expliquerai comment prserver lintgrit de vos donnes.
La normalisation tant une des principales mthodes que vous pouvez
utiliser cette fin, je vous prsenterai les diverses formes normales et les
types de problmes quelles peuvent permettre de rsoudre.

Concevoir la base de donnes


Suivez les tapes suivantes pour concevoir la base (je reviendrai en dtail
sur chacune des tapes aprs les avoir toutes nonces) :

1. Identifiez les objets que vous souhaitez stocker dans


votre base de donnes.

2. Dterminez parmi ces objets ceux qui devraient tre


des tables et ceux qui devraient tre des colonnes dans
ces tables.

3. Dfinissez les tables conformment la manire dont


vous avez besoin dorganiser les objets.

Vous pourriez ventuellement assigner une ou plusieurs


colonnes le rle de cl. Les cls permettent de localiser
rapidement dans une table la ligne qui vous intresse.
Les sections suivantes reviennent dans le dtail sur chacune de ces tapes.

tape 1 : Identifier les objets


La premire tape de la conception dune base de donnes consiste
dcider de ce quil est important dintgrer au modle. Traitez chaque
aspect de la question sous forme dun objet. tablissez une liste de tous les
objets auxquels vous pouvez penser. Nessayez pas encore didentifier les
relations qui peuvent lier ces entits entre elles. Pour linstant, essayez
simplement de dresser une liste exhaustive.
Il est important de pouvoir bnficier de laide de personnes qui
connaissent bien le systme que vous allez tenter de modliser. Vous
obtiendrez de prcieuses informations en les incitant parler entre elles et
en les interrogeant lors dune sance de brainstorming. En travaillant de
manire collective, vous dvelopperez probablement une collection
dobjets plus complte et plus prcise quen restant dans votre coin.
Une fois que vous disposez dun ensemble dobjets qui vous semble
raisonnablement complet, vous pouvez passer ltape suivante : dcider
comment ces objets seront relis entre eux. Certains de ces objets sont des
entits majeures, totalement indispensables pour fournir les rsultats que
vous escomptez. Dautres sont subordonns ces entits principales. Enfin,
certains objets nont peut-tre finalement rien faire dans votre modle et
devront tre limins avant de venir polluer la base de donnes.

tape 2 : Identifier les tables et les


colonnes
Les entits majeures se transforment en tables. Chacune possde un
ensemble dattributs quil faut convertir en colonnes de la table. Par
exemple, nombreuses sont les bases de donnes dentreprise qui contiennent
une table CLIENTS pour conserver la trace du nom et de ladresse des
clients (plus videmment dautres informations utiles). Chaque attribut dun
client, tel que son nom, sa rue, sa ville, son code postal et son adresse
Internet, est transform en une colonne de la table CLIENTS.
Il nexiste pas de rgles gnrales vous aidant identifier les objets qui
devraient tre des tables et dcider quels attributs ces tables doivent
possder. Cest vous dy rflchir. Vous associerez un attribut telle table
pour une certaine raison, et tel autre attribut telle autre table pour une
raison diffrente. Basez votre dcision sur ce que vous savez en respectant
deux objectifs :
Les informations que vous souhaitez pouvoir extraire de la
base de donnes.

Comment vous comptez utiliser les informations.

Lors de la conception de la structure des tables de votre base de donnes, il


est extrmement important de prendre en considration lavis des futurs
utilisateurs ainsi que celui des personnes qui prendront des dcisions sur la
base des informations quelle contiendra. Si la structure raisonnable
laquelle vous arrivez ne correspond pas la manire dont les gens vont
exploiter linformation, lutilisation de votre systme se rvlera frustrante
et pourra mme dboucher sur des prises de dcision errones. De telles
consquences sont inacceptables !
Prenons un exemple pour illustrer le processus intellectuel qui dbouche sur
la cration dune base dote de plusieurs tables. Supposons que vous venez
de crer VetLab, un laboratoire de microbiologie qui teste des spcimens
que vous font parvenir des vtrinaires. Il est vident que vous allez devoir
conserver la trace de nombreuses informations, et notamment :
Les clients.

Les tests que vous effectuez.

Les employs.

Les commandes.

Les rsultats.

Chacune de ces entits dispose dattributs. Chaque client a un nom, une


adresse et dautres informations sont ncessaires pour grer les contacts.
Chaque test a un nom et un cot. Chaque employ a des coordonnes ainsi
quun intitul de poste et un salaire. Pour chaque commande, vous devez
savoir qui la passe, quand elle a t passe et sur quel test elle portait.
Pour chaque test, vous devez disposer dun numro dordre, savoir ce quil
a donn, et si les rsultats taient prliminaires ou dfinitifs.

tape 3 : Dfinir les tables


Vous devez maintenant dfinir une table par entit et une colonne par
attribut. Le Tableau 5.1 prsente les tables de VetLab.

TABLEAU 5.1 Les tables de VetLab.

Table Colonnes

CLIENTS Nom du client


Adresse 1
Adresse 2
Ville
Etat
Code postal
Tlphone
Fax
Contact

TESTS Nom du test


Prix standard

EMPLOYES Nom de lemploy


Adresse 1
Adresse 2
Ville
Etat
Code postal
Tlphone personnel
Code bureau
Date dembauche
Classification
Salari horaire ou salari ou commissionn

COMMANDES Numro de commande


Nom du client
Test
Responsable commercial
Date de commande

RESULTATS Numro
Numro de commande
Rsultat
Date de production
Prliminaire ou dfinitif

Vous pouvez crer ces tables laide dun outil RAD ou dinstructions DDL
de SQL, de la manire suivante :

CREATE TABLSE CLIENTS (


NOM_CLIENT CHARACTER (30) NOT NULL,

ADRESSE_1 CHARACTER (30),


ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30) ) ;
CREATE TABLE TESTS (
NOM_TEST CHARACTER (30) NOT NULL,
PRIX_STANDARD CHARACTER (30) ) ;
CREATE TABLE EMPLOYES (
NOM_EMPLOYE CHARACTER (30) NOT NULL,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE_PERSO CHARACTER (13),
CODE_BUREAU CHARACTER (4),
DATE_EMBAUCHE DATE,
CLASSIFICATION CHARACTER (10),

HEUR_SAL_COM CHARACTER (1) ) ;


CREATE TABLE COMMANDES (
NUMERO_COMMANDE INTEGER NOT NULL,
NOM_CLIENT CHARACTER (30),
TEST_COMMANDE CHARACTER (30),
COMMERCIAL CHARACTER (30),
DATE_COMMANDE DATE ) ;
CREATE TABLE RESULTATS (
NUMERO_RESULTAT INTEGER NOT NULL,
NUMERO_COMMANDE INTEGER,
RESULTAT CHARACTER(50),
DATE_PRODUCTION DATE,
PRELIMINAIRE_FINAL CHARACTER (1) ) ;

Ces tables sont relies entre elles par les attributs (colonnes) quelles
partagent, comme suit :
La table CLIENTS est lie la table COMMANDES par la
colonne NOM_CLIENT.

La table TESTS est lie la table COMMANDES par la


colonne NOM_TEST(TEST_COMMANDE).

La table EMPLOYES est lie la table COMMANDES par la


colonne NOM_EMPLOYE(COMMERCIAL).

La table RESULTATS est lie la table COMMANDES par la


colonne NUMERO_COMMANDE.

Pour quune table occupe vraiment un rle dans une base de donnes
relationnelle, il convient de la relier une autre table par une colonne
commune. La Figure 5.1 illustre les relations entre nos tables.
Les liens qui figurent sur la Figure 5.1 illustrent quatre relations un
plusieurs. Les losanges indiquent le lien de cardinalit entre chaque
extrmit dune relation. Le chiffre 1 correspond au ct un des
relations, et la lettre N au ct plusieurs .
Un client peut passer plusieurs commandes, mais chaque
commande est effectue par un et un seul client.

Chaque test peut figurer dans plusieurs commandes, mais


chaque commande correspond un et un seul test.

Chaque commande est enregistre par un et un seul


employ (ou commercial), mais chaque commercial peut
enregistrer plusieurs commandes (cest prfrable).

FIGURE 5.1 Les tables de la base de donnes de VetLab.

Chaque commande peut dboucher sur plusieurs


rsultats prliminaires et sur un rsultat final, mais chaque
rsultat nest associ qu une et une seule commande.
Comme vous pouvez le constater sur la figure, lattribut qui lie une table
une autre peut porter un nom diffrent dans ces tables. Cependant les deux
attributs doivent avoir le mme type de donnes.

Domaines, jeux de caractres,


interclassements et translations
Bien que les tables soient les constituants principaux dune base de
donnes, celle-ci comporte dautres lments. Dans le Chapitre 1, jai
dfini le domaine dune colonne dune table comme tant lensemble des
valeurs que peut prendre cette colonne. Une partie importante de la
conception consiste dfinir clairement des domaines de toutes les
colonnes laide de contraintes.
Les gens qui parlent anglais ne sont pas les seuls utiliser des bases de
donnes. Il est possible dutiliser des langages dont le jeu de caractres est
diffrent de celui de langlais. SQL vous permet de spcifier le jeu de
caractres que vous souhaitez utiliser. En fait, vous pouvez mme spcifier
un jeu de caractres diffrent pour chaque colonne dune table. SQL est lun
des trs rares langages offrir une telle souplesse.
Un interclassement, ou squence dinterclassement, est un ensemble de
rgles qui spcifient comment les chanes qui utilisent un certain jeu de
caractres doivent tre compares entre elles. Chaque jeu de caractres est
dot dun interclassement par dfaut. Dans le jeu de caractres ASCII, A est
avant B et B est avant C. Une comparaison entre deux chanes ASCII se
basera donc sur le fait que A est infrieur B qui est infrieur C. SQL
vous permet dassocier diffrents interclassements un jeu de caractres.
L encore, il est lun des rares langages capables de cela. Cest une raison
supplmentaire pour aimer SQL.
Dans une base, vous encodez parfois des donnes laide dun jeu de
caractres, mais il peut arriver que vous souhaitiez les traiter dans un autre
jeu de caractres. Par exemple, vous disposez peut-tre de donnes qui
utilisent le jeu de caractres allemand, mais votre imprimante ne gre pas
les caractres spcifiques cette langue. Une traduction est une fonction de
SQL qui vous permet de traduire des chanes de caractres dun jeu de
caractres un autre. Par exemple, la traduction pourrait convertir un
caractre spcifique sous forme de deux lettres, comme le germanique en
ue ASCII. Il est aussi possible de transformer des caractres minuscules en
majuscules. Vous pouvez mme convertir un alphabet dans un autre, comme
de larabe ou de lhbreu en ASCII.

Amliorer les performances laide


des cls
Une bonne rgle appliquer ds la conception spcifie que chaque ligne
dune table doit pouvoir se distinguer de toutes les autres lignes de cette
table, cest--dire quelle doit tre unique. Cette rgle peut tre transgresse
aux tables que vous gnrez loccasion pour rpondre occasionnellement
un besoin spcifique, comme par exemple produire des statistiques sur la
base de critres prcis. Mais elle doit sappliquer toutes les tables que
vous comptez utiliser des fins diverses.
Une cl est un attribut ou une combinaison dattributs qui identifie de
manire unique une ligne dans une table. Pour accder une certaine ligne,
il faut que vous disposiez dun procd permettant de la distinguer des
autres. Du fait quelles sont uniques, les cls constituent un excellent
mcanisme daccs.
Une cl ne doit jamais avoir une valeur nulle (cest--dire vide ou non
dfinie). En effet, si vous utilisiez des cls nulles, deux lignes qui
contiendraient des valeurs nulles dans les champs de la cl ne pourraient
plus se distinguer lune de lautre.
Dans mon exemple de laboratoire vtrinaire, vous pouvez assigner
certaines colonnes le rle de cl. NOM_CLIENT ferait une bonne cl dans
la table CLIENTS. Elle permettrait en effet de distinguer chaque client.
NOM_TEST et NOM_EMPLOYE seraient de bonnes cls pour les tables
TESTS et EMPLOYES. NUMERO_ COMMANDE et NUMERO_RESULTAT
reprsenteraient de bonnes cls pour les tables COMMANDES et
RESULTATS. Dans chaque cas, vrifiez que vous entrez une valeur unique
pour chaque ligne.
Il existe deux sortes de cls : les cls primaires et les cls trangres. Les
cls dont je viens de parler sont des cls primaires. Ces cls garantissent
lunicit. Je vais parler des cls trangres dans la section suivante.

Cls primaires
Une cl primaire est une colonne dont les valeurs identifient chaque ligne
de la table dune manire unique. Pour introduire cette notion dans la base
de donnes VetLab, vous pouvez spcifier une cl primaire au moment o
vous crez une table. Dans lexemple suivant, une seule colonne suffit (en
supposant que tous les clients de VetLab portent des noms diffrents) :

CREATE TABLE CLIENTS (


NOM_CLIENT CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
) ;

La contrainte PRIMARY KEY se substitue la contrainte NOT NULL qui


figurait dans la dfinition prcdente de la table CLIENTS. Elle implique
dailleurs la contrainte NOT NULL, car une cl primaire ne peut jamais
prendre une valeur nulle.
Bien que la plupart des SGBD autorisent la cration de tables sans cl
primaire, toutes les tables dune base devraient en possder une. Pour
appliquer ce concept, remplacez la contrainte NOT NULL dans toutes vos
tables. Dans notre exemple, les tables TESTS, EMPLOYES,
COMMANDES et RESULTATS vont recevoir une contrainte PRIMARY
KEY, comme dans lexemple suivant :

CREATE TABLE TESTS (


NOM_TEST CHARACTER (30) PRIMARY KEY,
PRIX_STANDARD CHARACTER (30) ) ;

Il arrive parfois quaucune colonne ne suffise elle seule garantir


lunicit. Vous devez alors utiliser une cl composite. Il sagit dune
combinaison de colonnes qui, toutes ensemble, assurent cette unicit.
Supposez que certains des clients de VetLab soient des chanes ayant des
cabinets vtrinaires dans plusieurs villes. NOM_CLIENT nest alors plus
suffisant pour distinguer deux bureaux dun mme client. Vous pouvez alors
rgler le problme en dfinissant une cl composite de la manire suivante :

CREATE TABLE CLIENTS (


NOM_CLIENT CHARACTER (30) NOT NULL,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25) NOT NULL,
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30),
CONSTRAINT BUREAU PRIMARY KEY
(NOM_CLIENT, VILLE)
) ;

Cls trangres
Une cl trangre est une colonne, ou un groupe de colonnes, dans une table
qui correspond (ou rfrence) une cl primaire dans une autre table. Une
cl trangre na pas tre unique elle-mme, mais elle doit identifier de
manire unique la ou les colonnes quelle rfrence dans lautre table.
Si la colonne NOM_CLIENT est une cl primaire dans la table CLIENTS,
chaque ligne de cette table doit prendre une valeur unique dans la colonne
NOM_CLIENT. NOM_CLIENT est une cl trangre dans la table
COMMANDES. Cette cl trangre correspond la cl primaire de la table
CLIENTS, mais elle na pas tre unique dans la table COMMANDES. Et
cest tant mieux pour vous Si chacun de vos clients vous passait une
commande puis svanouissait dans la nature, votre laboratoire ne ferait pas
long feu. Si tout va bien, de nombreuses lignes de la table COMMANDES
vont correspondre chaque ligne de la table CLIENTS, ce qui signifiera
que presque tous vos clients sont fidles votre laboratoire.
La dfinition suivante de la table COMMANDES vous montre comment
vous pouvez utiliser le concept de cl trangre dans linstruction
CREATE :

CREATE TABLE COMMANDES (


NUMERO_COMMANDE INTEGER PRIMARY KEY,
NOM_CLIENT CHARACTER (30),

TEST_COMMANDE CHARACTER (30),


COMMERCIAL CHARACTER (30),
DATE_COMMANDE DATE,
CONSTRAINT NOM_CE FOREIGN KEY (NOM_CLIENT)
REFERENCES CLIENTS (NOM_CLIENT),
CONSTRAINT TEST_CE FOREIGN KEY (TEST_COMMANDE)
REFERENCES TESTS (NOM_TEST),
CONSTRAINT SALES_CE FOREIGN KEY (COMMERCIAL)
REFERENCES EMPLOYES (NOM_EMPLOYE)
) ;

Dans cet exemple, les cls trangres de la table COMMANDES lient


celle-ci aux cls primaires des tables CLIENTS, TESTS et EMPLOYES.

Travailler avec des index


La spcification SQL ne mentionne pas les index, mais cette omission ne
signifie pas pour autant que les index soient peu utiliss ni quils soient en
option dans un systme de gestion de bases de donnes. Toutes les
implmentations de SQL grent les index, mais dune manire qui leur est
propre. Dans le Chapitre 4, je vous ai montr comment vous pouviez crer
un index en utilisant Microsoft Access, un outil de dveloppement rapide
dapplications (RAD). Vous devrez vous rfrer la documentation de
votre systme de gestion de bases de donnes (SGBD) pour comprendre
comment il implmente les index.

Quest-ce quun index ?


Les donnes que contient une table apparaissent gnralement dans lordre
dans lequel vous les avez saisies. Cependant, cet ordre ne correspond pas
toujours celui dans lequel vous comptez traiter les donnes. Par exemple,
supposons que vous vouliez afficher votre table CLIENTS dans lordre de
NOM_ CLIENT. Lordinateur doit dabord trier la table dans cet ordre. Plus
la table est grande, plus ce tri prend de temps. Que se passera-t-il si votre
table contient un million de lignes ? Il nest pas rare que le cas se prsente.
Mme les meilleurs algorithmes de tri devront effectuer vingt millions de
comparaisons et des millions dinterversions pour trier la table. Mme sur
un ordinateur trs rapide, vous allez trouver le temps bien long.
Les index vous permettent de gagner du temps. Un index est une table
subsidiaire qui est lie une table de donnes. Pour chaque ligne de cette
dernire, il existe une ligne correspondante dans la table dindex.
Cependant, lordre de ces lignes est diffrent dans lindex.
Le Tableau 5.2 vous montre un exemple de table de donnes.

TABLEAU 5.2 Table CLIENTS.

NOM_CLIENT ADRESSE_1 ADRESSE_2 VILLE ETAT

Clinique Butternut 5, Butternut Hudson NH


Animal Lane

Amber Veterinary, 470 Kolvir Circle Amber MI


Inc

Vets R Us 2300 Geoffrey Suite 230 Anaheim CA


Road

Docteur Doggie 32 Terry Terrace Nutley NJ

Centre questre Dpartement 7890 Paddock Gallup NM


vtrinaire Parkway

Institut 1002 Marine Key FL


ocanographique Drive West
J.C. Campbell, 2500 Maon Los CA
Vtrinaire Street Angeles

Ferme vers de 15 Bait Sedons AZ


Wenger Boulevard

Les lignes ne sont pas tries par ordre alphabtique selon NOM_CLIENT.
En fait, elles ne sont pas tries du tout. Elles sont simplement dans lordre
dans lequel quelquun les a saisies.
Un index pour la table CLIENTS peut ressembler au Tableau 5.3.

TABLEAU 5.3 Lindex par nom de client pour la table CLIENTS.

NOM_CLIENT Pointeur vers la table de donnes

Amber Veterinary, Inc 2

Clinique Butternut Animal 1

Docteur Doggie 4

Institut ocanographique 6

J.C. Campbell, Vtrinaire 7

Centre questre 5

Vets R Us 3

Ferme vers de Wenger 8

Lindex contient le champ sur lequel est bas lindex (ici NOM_ CLIENT)
et un pointeur vers la table des donnes. Ce pointeur donne le numro de la
ligne correspondante dans la table de donnes.

Pourquoi utiliser un index ?


Si je veux traiter une table dans lordre NOM_CLIENT, et que je dispose
dun index arrang selon cet ordre, je peux effectuer toutes mes oprations
presque aussi vite que si les donnes avaient t saisies en classant
alphabtiquement les noms des clients. Il est possible de parcourir lindex
squentiellement, et donc de rcuprer ainsi successivement chaque
pointeur vers la donne qui lui correspond dans la table.
Si vous utilisez un index, le temps pris pour traiter la table sera
proportionnel N, o N est le nombre denregistrements dans la table. Sans
index, ce temps sera proportionnel N lg N, o N est le logarithme
base 2 de N. La diffrence nest pas significative si la table est petite, mais
elle le devient ds lors que sa taille est volumineuse. Certaines oprations
ne peuvent tre envisages sans indexer les tables.
Supposons par exemple que vous disposiez dune table qui
contient 1 000 000 denregistrements (N = 1 000 000) et que traiter chaque
enregistrement prenne une milliseconde (un millime de seconde). Si vous
utilisez un index, le traitement de la table entire
demandera 1 000 secondes, soit peu prs 17 minutes. Sans index, ce
traitement prendra 1 000 000 x 20 millisecondes, soit 20 000 secondes,
cest--dire peu prs 5 heures et demie. Je pense que vous conviendrez du
fait que la diffrence est substantielle.

Tenir un index jour


Une fois que vous avez cr un index, vous devez le tenir jour. Fort
heureusement, votre SGBD assurera cette maintenance chaque fois que vous
modifierez la table de donnes associe. Ce travail prend un peu de temps,
mais cela en vaut la peine. Lorsque vous aurez cr un index et que votre
SGBD le maintiendra jour, cet index sera disponible tout instant pour
acclrer le traitement de donnes.
Le meilleur moment pour dfinir un index est celui o vous crez la table
laquelle il est associ. De cette manire, vous naurez pas souffrir de la
longue attente inhrente la cration dun index quand une table est dj
remplie de donnes. Essayez toujours de prvoir lavance vos besoins en
matire daccs aux donnes. Dfinissez alors un index pour chaque
possibilit.
Certains SGBD vous permettent de dsactiver la maintenance des index. Il
peut tre utile de le faire dans le contexte dapplications temps rel o cette
mise jour consomme trop de temps pour le peu de disponibilits dont vous
disposez ( Dsol, chef, il faut arrter le compte rebours de la navette
parce que les index ne sont pas jour ! ). Il arrive parfois que vous
puissiez programmer la mise jour des index des heures o la base est
peu sollicite.
Ne tombez pas dans le pige dajouter un index pour optimiser des
recherches auxquelles vous allez rarement procder. Grer un index prend
du temps, car cest une opration supplmentaire que lordinateur doit
accomplir chaque fois quil modifie le champ index, quil ajoute ou quil
supprime une ligne. Ne crez des index que pour des tables de taille
importante, et pour optimiser des recherches auxquelles vous comptez
procder souvent. Sinon, les performances de votre systme sen trouveront
dgrades.
Il peut arriver que vous ayez raliser un rapport annuel ou trimestriel dont
la production prendrait trop de temps si elle ne sappuyait pas sur un index
(qui ne vous sert dailleurs qu cette occasion). Crez cet index juste
auparavant, produisez le rapport, puis supprimez lindex de sorte quil ne
perturbe pas le travail du SGBD jusqu la prochaine demande de rapport.

Maintenir lintgrit
Une base de donnes nest utile que si vous tes certain que les donnes
quelle contient sont correctes. Par exemple, la prsence de donnes
errones dans une base de donnes mdicale, aronautique ou militaire peut
dboucher sur la mort dautrui. Le concepteur dune base de donnes
devrait tre en permanence certain quil est impossible des donnes
invalides de pntrer la base.
Certes, cet objectif nest pas toujours ralisable en totalit. Par contre, il est
toujours possible de sassurer (au moins) que les valeurs saisies sont
valides. Maintenir lintgrit des donnes signifie sentourer de toutes les
garanties pour que tout ce qui est entr dans la base satisfasse aux
contraintes qui ont t tablies auparavant. Si, par exemple, un certain
champ est du type Date, le SGBD devrait y rejeter toute tentative de saisie
dune valeur autre quune date valide.
Certains problmes ne peuvent pas tre stopps au niveau de la base de
donnes. Le programmeur de lapplication doit les intercepter avant quils
nendommagent la base de donnes. Toute personne charge de manipuler la
base de donnes doit bien tre consciente des dangers qui menacent
lintgrit de cette dernire et prendre les mesures qui simposent pour
dsactiver ces failles.
Lintgrit dune base de donnes peut relever de plusieurs types. Et de
nombreux problmes sont susceptibles daffecter cette intgrit. Dans les
sections suivantes, je traite de trois types dintgrit : lintgrit de
lentit, lintgrit du domaine et lintgrit rfrentielle. Nous verrons
galement quelques-unes des menaces qui planent sur cette intgrit.

Lintgrit de lentit
Chaque table dune base de donnes correspond une entit du monde rel.
Cette entit peut tre physique ou conceptuelle, mais, dune certaine
manire, son existence est indpendante de celle de la base. Lintgrit de
lentit dune table est assure quand la table est totalement cohrente avec
lentit quelle reprsente. Pour cela, la table doit disposer dune cl
primaire. Celle-ci identifie chaque ligne de la table. Sans cl primaire, vous
ne pouvez pas tre certain quune ligne rcupre soit la bonne.
Pour maintenir cette intgrit, vous devez spcifier que la colonne ou le
groupe de colonnes qui constitue la cl primaire est NOT NULL. De plus,
vous devez contraindre la cl primaire pour quelle soit UNIQUE.
Certaines implmentations de SQL vous permettent de mentionner cette
contrainte lors de la dclaration de la table. Dautres ne le permettent pas,
si bien que vous devez la spcifier aprs avoir spcifi comment ajouter,
modifier et supprimer des donnes dune table. La meilleure solution pour
vous assurer que votre cl primaire est la fois NOT NULL et UNIQUE
est de spcifier la contrainte PRIMARY KEY lorsque vous crez la table,
comme dans lexemple suivant :

CREATE TABLE CLIENTS(


NOM_CLIENT CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
) ;

Une autre solution consiste utiliser NOT NULL avec UNIQUE, comme
dans lexemple suivant :

CREATE TABLE CLIENTS (


NOM_CLIENT CHARACTER (30) NOT NULL,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),

CODE_POSTAL CHARACTER (10),


TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
) ;

Lintgrit du domaine
En gnral, vous ne pouvez pas garantir quune donne particulire de la
base de donnes sera correcte, mais vous pouvez du moins vous assurer de
sa validit. De nombreuses donnes ne peuvent prendre quun certain
nombre de valeurs. Si vous remarquez une entre qui ne prend pas une de
ces valeurs possibles, cest quelle est errone. Par exemple, les tats-Unis
possdent 50 tats plus le district de Columbia, Puerto Rico et quelques
autres possessions. Chacune de ces rgions est dsigne par un code deux
lettres reconnu par les services postaux. Si votre base de donnes contient
une colonne ETAT, vous pouvez assurer lintgrit du domaine en spcifiant
que toute entre dans la colonne ETAT doit tre lun de ces codes deux
lettres. Si quelquun saisit une valeur qui ne fait pas partie de cette liste, il
enfreint lintgrit des donnes. Si vous testez lintgrit de votre domaine,
vous pouvez refuser daccepter toute opration qui provoque ce genre de
brche.
Lintgrit du domaine peut tre menace si vous ajoutez une nouvelle
donne une table en utilisant lune des instructions INSERT ou UPDATE.
Vous pouvez spcifier le domaine dune colonne en utilisant linstruction
CREATE DOMAIN avant dutiliser cette colonne dans une instruction
CREATE TABLE, comme dans lexemple suivant :

CREATE DOMAIN LEAGUE_DOM CHAR (8)


CHECK (LEAGUE IN (Amricaine, Nationale));
CREATE TABLE TEAM (
TEAM_NAME CHARACTER (20) NOT NULL,
LEAGUE CHARACTER (8) NOT NULL
) ;

Le domaine de la colonne LIGUE contient seulement deux valeurs


valides : Amricaine et Nationale. Votre SGBD refusera de valider
la saisie ou de modifier une ligne de la table EQUIPES si la colonne
LIGUE ne prend pas lune de ces deux valeurs.

Lintgrit rfrentielle
Mme si lintgrit de lentit et du domaine de chaque table de votre
systme est assure, vous pouvez toujours tre confront des problmes
parce que les relations qui relient vos tables sont incohrentes. Dans la
plupart des bases de donnes bien conues, chaque table contient au moins
une colonne qui se rfre une colonne dans une autre table. Ces rfrences
sont importantes pour maintenir lintgrit de la base de donnes. Pour
autant, elles favorisent lapparition danomalies lors des modifications.
Les anomalies de modification sont des problmes qui se produisent quand
vous modifiez une donne dans une ligne dune table.

Les relations entre les tables ne sont gnralement pas bidirectionnelles.


Une table dpend normalement de lautre. Supposons par exemple que vous
disposiez dune base de donnes qui contient des tables CLIENTS et
COMMANDES. Vous pourriez saisir un client dans la table CLIENTS avant
quil ait pass une commande. Cependant, vous ne pouvez pas saisir une
commande dans COMMANDES tant que le client na pas t cr dans la
table CLIENTS. Ce type de relation est nomm relation parent-enfant, la
table CLIENTS tant la table parent et la table COMMANDES la table
enfant. Lenfant dpend du parent.
Gnralement, la cl primaire de la table parent est une colonne (ou un
groupe de colonnes) qui apparat dans la table enfant. lintrieur de cette
table enfant, elle (la colonne) ou il (le groupe de colonnes) est une cl
trangre. Une cl trangre peut prendre une valeur nulle et na pas tre
unique.
Les anomalies dans les modifications surviennent de plusieurs manires.
Par exemple, un client dmnage et vous voulez le retirer de votre base de
donnes. Sil a dj pass des commandes (enregistres) dans la table
COMMANDES, cette suppression va engendrer des problmes. En effet, il
existera alors des enregistrements dans la table COMMANDES (enfant)
pour lesquels il nexiste pas denregistrement dans la table CLIENTS
(parent). Des problmes de cette nature peuvent aussi survenir si vous
ajoutez un enregistrement une table enfant sans effectuer les ajouts
correspondants la table parent.
Les cls trangres de toute table enfant doivent reflter les modifications
apportes la cl primaire correspondante de la table parent, sans quoi il y
aura anomalie de modification.

Les suppressions en cascade utiliser


avec soin
Vous pouvez vous prmunir contre presque tous les problmes dintgrit
rfrentielle en contrlant avec soin le processus de mise jour. Dans
certains cas, vous devez rpercuter en cascade les suppressions de la table
parent dans ses tables enfants. Si vous supprimez une ligne de la table
parent, vous devez alors supprimer toutes les lignes de ses tables enfants
qui contiennent une cl trangre correspondant la cl primaire que vous
venez de supprimer dans la table parent. Prenons un exemple pour mieux
comprendre ce processus :

CREATE TABLE CLIENTS(


NOM_CLIENT CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25) NOT NULL,
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
) ;

CREATE TABLE TESTS (


NOM_TEST CHARACTER (30) PRIMARY KEY,
PRIX_STANDARD CHARACTER (30)
) ;

CREATE TABLE EMPLOYES (


NOM_EMPLOYE CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE_PERSO CHARACTER (13),
CODE_BUREAU CHARACTER (4),
DATE_EMBAUCHE DATE,
CLASSIFICATION CHARACTER (10),
HEUR_SAL_COM CHARACTER (1)
) ;

CREATE TABLE COMMANDES (


NUMERO_COMMANDE INTEGER PRIMARY KEY,
NOM_CLIENT CHARACTER (30),
TEST_COMMANDE CHARACTER (30),
COMMERCIAL CHARACTER (30),
DATE_COMMANDE DATE
CONSTRAINT NOM_CE FOREIGN KEY (NOM_CLIENT)
REFERENCES CLIENTS (NOM_CLIENT)
ON DELETE CASCADE,
CONSTRAINT TEST_CE FOREIGN KEY (TEST_COMMANDE)

REFERENCES TESTS (NOM_TEST)


ON DELETE CASCADE,
CONSTRAINT VENTES_CE FOREIGN KEY (COMMERCIAL)
REFERENCES EMPLOYES (NOM_EMPLOYE)
ON DELETE CASCADE
) ;

La contrainte NOM_CE dsigne NOM_CLIENT comme cl trangre qui


rfrence la colonne NOM_CLIENT dans la table CLIENTS. Si vous
supprimez une ligne dans la table CLIENTS, vous dtruisez alors
automatiquement toutes les lignes de la table COMMANDES dont la
colonne NOM_CLIENT contient la mme valeur que la colonne
quivalente de la table CLIENTS. La suppression se droule en cascade
depuis la table CLIENTS jusqu la table COMMANDES. Il en va de mme
pour les cls trangres dans la table COMMANDES qui se rfrent des
cls primaires dans les tables TESTS et EMPLOYES.

Dautres manire de contrler les


anomalies de mise jour
Vous pourriez prfrer cette suppression en cascade une autre solution, qui
consiste passer la valeur NULL dans les cls trangres dune table
enfant. Considrez la variante suivante de lexemple prcdent :

CREATE TABLE COMMANDES (


NUMERO_COMMANDE INTEGER PRIMARY KEY,
NOM_CLIENT CHARACTER (30),
TEST_COMMANDE CHARACTER (30),
COMMERCIAL CHARACTER (30),
DATE_COMMANDE DATE
CONSTRAINT NOM_CE FOREIGN KEY (NOM_CLIENT)
REFERENCES CLIENTS (NOM_CLIENT)
CONSTRAINT TEST_CE FOREIGN KEY (TEST_COMMANDE)
REFERENCES TESTS (NOM_TEST)
CONSTRAINT VENTES_CE FOREIGN KEY (COMMERCIAL)
REFERENCES EMPLOYES (NOM_EMPLOYE)
) ;

La contrainte VENTES_CE dsigne la colonne COMMERCIAL comme cl


trangre rfrenant la colonne NOM_EMPLOYE de la table EMPLOYES.
Si un commercial quitte la socit, vous supprimez sa ligne dans la table
EMPLOYES. Un nouvel employ prendra probablement la place de celui
qui vient de partir, mais pour linstant la suppression du nom du commercial
de la table EMPLOYES entrane le passage NULL de la colonne
COMMERCIAL des commandes quil traitait.
Il est aussi possible dempcher lintrusion de donnes invalides ou
inconsistantes dans une base en utilisant lune de ces mthodes :

Refusez dautoriser tout ajout dans une table enfant


tant quil nexiste pas de ligne correspondante dans la
table parent. Vous viterez ainsi lajout de lignes
orphelines dans la table enfant. De cette manire, vous
aiderez conserver des tables cohrentes.

Refusez que la cl primaire dune table puisse tre


modifie. De cette manire, vous naurez plus mettre
jour des cls trangres dans dautres tables qui dpendent
de cette cl primaire.

Le jour o vous avez pens que


tout tait fini
La seule chose dont on peut tre sr dans la vie relle, cest du changement.
Dans le monde des bases de donnes, cest pareil. Vous avez cr une base,
vous avez dfini vos tables, vos contraintes, vous avez rempli des lignes et
des lignes de donnes Et cest cet instant que lordre tombe den haut :
la structure doit tre change. Comment ajouter une nouvelle colonne une
table existante ? Comment en supprimer une qui est devenue inutile ? Ne
paniquez pas : SQL est l !

Ajouter une colonne une table existante


Supposons que votre socit dcide que chaque anniversaire dun membre
du personnel devra tre ft. Un coordinateur est nomm cet effet. Pour lui
permettre de planifier ces petites sauteries, vous devez ajouter une colonne
DATE_NAISSANCE la table EMPLOYES. Pas de problme ! Il vous
suffit de faire appel linstruction ALTER TABLE. Voici comment :

ALTER TABLE EMPLOYES


ADD COLUMN Date_Anniversaire AS DATE ;

Il ny a plus qu saisir la bonne date de naissance dans chaque ligne de la


table, et cest parti pour les agapes

Supprimer une colonne dune table


existante
Les affaires vont mal, et votre entreprise na plus les moyens doffrir une
petite fte ses personnels le jour de leur anniversaire. Plus de champagne,
plus de dates de naissance L encore, linstruction ALTER TABLE vous
permet de faire face cette douloureuse situation :

ALTER TABLE EMPLOYES


DROP COLUMN Date_Anniversaire ;

Au moins, vous en avez profit tant que les affaires marchaient bien !
Sources potentielles de problmes
Lintgrit de votre base de donnes est menace par toutes sortes de
problmes. Certains dentre eux ne se posent quavec des bases de donnes
qui contiennent plusieurs tables, tandis que dautres peuvent surgir mme
avec des bases de donnes ne comprenant quune seule table.

Mauvaise saisie
Les documents ou les fichiers que vous utilisez pour alimenter votre base de
donnes peuvent contenir des donnes errones (quil sagisse
dinformations valides mais qui ont t corrompues ou de valeurs
parfaitement indsirables). Des tests aux limites vous permettront de
vrifier que la donne ne menace pas lintgrit du domaine. Cependant, ce
type de test ne prvient pas tous les problmes. Les valeurs qui se trouvent
dans les limites autorises mais qui sont nanmoins errones ne seront pas
dtectes.

Erreur de loprateur
La donne saisir peut tre correcte, mais loprateur la transcrit mal. Ce
type derreur peut conduire aux mmes problmes que ceux poss par
lutilisation de donnes errones. L encore, un test aux limites peut
prvenir en partie cette erreur. Une meilleure solution serait quun second
oprateur valide les saisies du premier. Cependant, cest une solution
coteuse, car vous devrez doubler la fois vos effectifs et le temps de
saisie. Mais dans certaines circonstances ce sacrifice peut parfois vous
viter de perdre plus quil ne vous cote.

Panne mcanique
Si une panne mcanique survient, telle que le crash dun disque quand une
table est ouverte, les donnes qui se trouvent dans la table peuvent tre
dtruites. Votre seule solution est de raliser des sauvegardes frquentes.

Malveillance
Quelquun pourrait vouloir volontairement corrompre vos donnes. Votre
premire ligne de dfense sera de refuser laccs votre base quiconque
pourrait faire preuve de malveillance et de limiter les droits des autres
personnes au strict ncessaire. Votre seconde ligne de dfense sera de
stocker des sauvegardes en lieu sr. Testez rgulirement la scurit de
votre installation. Cela ne fait pas de mal dtre un peu paranoaque.

Redondance de donnes
La redondance de donnes est un problme connu du modle de base de
donnes hirarchique, mais il peut aussi affecter des bases de donnes
relationnelles. Cette redondance gaspille de lespace de stockage, ralentit
les traitements et peut corrompre srieusement les donnes. Si vous stockez
la mme donne dans deux tables diffrentes, une modification de la copie
de cette donne dans une table peut ne pas tre rpercute dans lautre. Il y
a alors incohrence puisquil nest pas toujours possible de dire quelle est
la bonne information. Il faut donc limiter autant que faire se peut la
redondance des donnes.
Il faut certes un peu de redondance, ne serait-ce que pour que la cl
primaire dune table serve de cl trangre dans une autre table, mais pas
trop. Lune des solutions les plus efficaces pour limiter la redondance est la
normalisation, qui consiste dcouper une table en plusieurs tables plus
simples.
Une fois que vous aurez limin la redondance de votre modle de donnes,
vous raliserez peut-tre que les performances sont insuffisantes. Les
oprateurs ont souvent recours la redondance pour acclrer les
traitements. Dans lexemple prcdent de la base de VetLab, la table
COMMANDES contient seulement le nom du client pour identifier la
source de chaque commande. Si vous prparez une commande, vous devez
effectuer la jointure des tables CLIENTS et COMMANDES afin dobtenir
ladresse du client. Si cette jointure vous semble prendre trop de temps,
vous pourriez stocker ladresse du client dans la table COMMANDES. La
redondance ainsi cre permet de ne plus recourir la jointure et acclre
donc la prparation dune commande. En contrepartie, lefficacit globale
du systme sera lgrement dgrade, et la mise jour des adresses des
clients sera plus dlicate.
Les utilisateurs conoivent souvent des bases de donnes avec un minimum
de redondance et un haut degr de normalisation. Lorsquils constatent que
les performances dapplications importantes sont mauvaises, ils dcident de
dnormaliser leurs bases et dy introduire slectivement une certaine
redondance. Le mot important est ici slectivement. Vous devez prendre des
mesures appropries pour que la redondance ne provoque pas plus de
problmes quelle nen rsout. Pour plus dinformations, voyez plus loin la
section consacre la normalisation.

Dpassement de la capacit du SGBD


Un systme de bases de donnes peut fonctionner parfaitement pendant des
annes. Puis des erreurs commencent se produire de temps autre. Et ces
problmes deviennent de plus en plus srieux. Cest peut-tre le signe que
vous approchez des limites de votre systme. Le nombre des lignes
contenues dans une table nest en aucun cas infini. De mme, il y a des
limites aux contraintes, au nombre de colonnes, et ainsi de suite. Comparez
la taille et le contenu de votre base de donnes aux spcifications de votre
SGBD. Si vous vous rapprochez du point de rupture, il va vous falloir
envisager une mise niveau vers un systme plus puissant. Une autre
solution pourrait consister archiver les donnes les plus anciennes (celles
qui ne sont plus exploites, celles qui servent uniquement conserver la
mmoire de vos activits et tablir des statistiques), puis les supprimer
de votre base.

Contraintes
Ci-avant dans ce chapitre, jai parl des contraintes comme de mcanismes
qui permettent de vous assurer que les donnes saisies dans une colonne
dune table appartiennent bien la plage de valeurs autorises. Une
contrainte est une rgle que le SGBD applique. Une fois la base de donnes
dfinie, vous pouvez inclure des contraintes (telles que NOT NULL) dans
la dfinition des tables. Il est alors de la responsabilit du SGBD
dinterdire toute transaction qui violerait une contrainte.
Il existe trois types de contraintes :

Une contrainte de colonne impose une condition une


colonne dans une table.

Une contrainte de tables applique une table tout


entire.
Une assertion est une contrainte qui porte sur plusieurs
tables.

Contraintes de colonne
Voici un exemple de contrainte de colonne dans une instruction DDL :

CREATE TABLE CLIENTS(


NOM_CLIENT CHARACTER (30) NOT NULL,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),

FAX CHARACTER (13),


CONTACT CHARACTER (30)
) ;

Linstruction applique la contrainte NOT NULL la colonne


NOM_CLIENT, ce qui signifie que cette colonne ne peut contenir une valeur
nulle. Vous pourriez aussi appliquer la contrainte UNIQUE. Elle spcifie
que chaque valeur de cette colonne doit tre unique dans toute la table. La
contrainte CHECK est particulirement utile parce quelle peut prendre
nimporte quelle expression valide en argument. Par exemple :

CREATE TABLE TESTS (


NOM_TEST CHARACTER (30) NOT NULL,
PRIX_STANDARD NUMERIC (6,2)
CHECK (PRIX_STANDARD >= 0.0
AND PRIX_STANDARD <= 200.0)
) ;
Le cot dun test de VetLab doit toujours tre suprieur ou gal zro. Et
aucun test ne doit coter plus de 200 euros. La clause CHECK refuse tout
montant qui nappartient pas la plage 0 <= PRIX_STANDARD
<= 200. Vous pourriez aussi spcifier cette contrainte de la manire
suivante :

CHECK (PRIX_STANDARD BETWEEN 0.0 AND 200.0)

Contraintes de table
La contrainte PRIMARY KEYspcifie que la colonne laquelle elle
sapplique est une cl primaire. Cette contrainte simpose donc la table
entire et est lquivalent dune combinaison des contraintes de colonnes
NOT NULL et UNIQUE. Vous pouvez spcifier cette contrainte dans une
instruction CREATE, comme dans lexemple suivant :

CREATE TABLE CLIENTS(


NOM_CLIENT CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
) ;

Les contraintes nommes, telles que NOM_CE dans lexemple donn dans
Les suppressions en cascade utiliser avec soin peuvent avoir
quelques fonctionnalits supplmentaires. Par exemple, supposons que vous
souhaitiez charger quelques centaines de prospects dans votre table
PROSPECT. Vous disposez dun fichier qui contient essentiellement des
prospects des tats-Unis, mais on trouve aussi quelques prospects
canadiens perdus dans le fichier. Normalement, vous souhaiteriez
restreindre votre table PROSPECT pour ny faire figurer que les prospects
amricains, mais vous ne voulez pas que le chargement soit interrompu
chaque fois quil tombe sur un canadien (les codes postaux canadiens
comprennent des lettres et des chiffres, mais les codes postaux amricains
ne contiennent que des chiffres). Vous pouvez choisir de ne pas activer de
contrainte sur CODE_POSTAL tant que le chargement nest pas termin, et
dactiver la contrainte ensuite.
Au dpart, votre table PROSPECT a t cre en utilisant cette commande
CREATE TABLE :

CREATE TABLE PROPECT (


NOM_CLIENT CHARACTER (30) PRIMARY KEY,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30)
CONSTAINT ZIP CHECK (CODE_POSTAL BETWEEN 0 AND
99999)
) ;

Avant le chargement, vous pouvez dsactiver la contrainte ZIP :

ALTER TABLE PROSPECT


CONSTRAINT ZIP NOT ENFORCED;

Une fois que le chargement est termin, vous pouvez ractiver la contrainte :

ALTER TABLE PROSPECT


CONSTRAINT ZIP ENFORCED;

cet instant, vous pouvez liminer les lignes qui ne rpondent pas la
contrainte avec :

DELETE FROM PROSPECT


WHERE CODE_POSTAL NOT BETWEEN 0 AND 99999 ;

Les assertions
Une assertion spcifie une restriction portant sur plusieurs tables.
Lexemple suivant utilise une condition de recherche qui extrait des valeurs
de deux tables pour crer une assertion :

CREATE TABLE COMMANDES (


NUMERO_COMMANDE INTEGER NOT NULL,
NOM_CLIENT CHARACTER (30),
TEST_COMMANDE CHARACTER (30),
COMMERCIAL CHARACTER (30),
DATE_COMMANDE DATE ) ;

CREATE TABLE RESULTATS (


NUMERO_RESULTAT INTEGER NOT NULL,
NUMERO_COMMANDE INTEGER,
RESULTAT CHARACTER(50),
DATE_PRODUCTION DATE,
PRELIMINAIRE_FINAL CHARACTER (1) ) ;

CREATE ASSERTION
CHECK (NOT EXISTS SELECT * FROM COMMANDES,
RESULTATS
WHERE COMMANDE.NUMERO_COMMANDE =
RESULTATS.NUMERO_COM-
MANDE
AND COMMANDES.DATE_COMMANDE >
RESULTATS.DATE_PRODUCTION)
;

Cette assertion vous garantit quaucun rsultat nest transmis si la


commande correspondante na pas t valide.
Normaliser la base de donnes
Certaines mthodes dorganisation des donnes sont meilleures que
dautres. Il y en a qui sont plus logiques. Dautres qui sont plus simples.
Certaines permettent dviter lapparition dincohrences quand vous
commencez utiliser la base.

Les anomalies de modification et


les formes normales
Nombre de problmes (appels anomalies de modification) sont capables
de pourrir une base de donnes que vous naurez pas correctement
structure. Pour les viter, vous pouvez normaliser la structure de la base de
donnes. La normalisation consiste gnralement dcouper une table en
deux tables plus simples.
Les anomalies de modification sont ainsi nommes parce quelles sont
gnres lors de lajout, de la modification ou de la suppression de donnes
dans une table.
Pour comprendre comment elles peuvent survenir, observez la Figure 5.2.
Votre socit commercialise des produits dentretien mnagers et dhygine
personnelle. Pour chaque produit, vous facturez le mme prix tous vos
clients. La table VENTES conserve la trace de toutes les transactions.
Supposez maintenant que la rfrence 1001 dmnage et ne soit donc plus
un de vos clients. Ce quil a achet par le pass ne vous intresse plus. Vous
voulez retirer sa ligne de la table. Mais en effectuant cette suppression,
vous nallez pas seulement oublier que le client 1001 a achet de la poudre
laver ; vous allez aussi oublier que cette poudre cote 12 euros. Cette
situation est appele anomalie de suppression. En supprimant un fait (le
client 1001 a achet de la poudre laver), vous allez en effacer un autre par
inadvertance (le prix de la poudre en question).
FIGURE 5.2 La table VENTES.

La mme table permet de montrer ce quest une anomalie dinsertion. Par


exemple, supposons que vous dsiriez ajouter un dodorant 2 euros
votre inventaire. Vous ne pouvez pas ajouter cette donne dans la table
VENTES, car personne encore na achet ce produit.
Le problme avec notre table VENTES est quelle traite de trop
dinformations en mme temps. Elle enregistre les produits que les clients
achtent et le prix de ces produits. Vous devez donc scinder la table en
deux, chaque nouvelle table soccupant dun thme ou dune ide, comme
sur la Figure 5.3.
La Figure 5.3 vous montre le rsultat de la division de la table VENTES en
deux nouvelles tables :
ACHAT_CLIENT traite de la seule ide dun achat dun
client.

PRIX_PRODUIT traite de la seule ide du prix dun produit.


FIGURE 5.3 La table VENTES est dcoupe en deux tables.

Vous pouvez maintenant supprimer la ligne qui concerne le client 1001 de


ACHAT_CLIENT sans perdre le prix de la poudre laver. Cette
information se trouve maintenant dans la table PRIX_PRODUIT. Il devient
aussi possible dajouter le dodorant PRIX_PRODUIT quil ait dj t
vendu ou non. Les informations relatives aux achats sont stockes ailleurs,
dans ACHAT_CLIENT.
Le processus qui consiste dcouper une table en plusieurs tables dont
chacune traite dun thme particulier est appel normalisation. Un processus
de normalisation qui rsout un problme ne rgle pas forcment les autres.
Pour les rsoudre tous, il vous faudra probablement dcouper encore les
tables jusqu ce que chacune ne soccupe plus que dune seule ide.
Chaque table devrait donc prendre en charge un et un seul thme principal.
Parfois, il est vritablement difficile de dterminer si une table traite dun
ou de plusieurs thmes.
Vous pouvez classer les tables en fonction du type danomalies de
modification auquel elles sont sujettes. Dans un document de 1970 qui
dcrit pour la premire fois le modle relationnel, E.F. Codd identifie trois
sources danomalies de modification et dfinit la premire, la deuxime et
la troisime forme normale (1NF, 2NF et 3NF) pour les prvenir. Dans les
annes suivantes, Codd et dautres chercheurs ont dcouvert dautres types
danomalies et ont spcifi de nouvelles formes normales pour les traiter.
La forme normale de Boyce-Codd (BCNF), la quatrime forme normale
(4NF) et la cinquime forme normale (5NF) offrent chacune un degr
suprieur de protection contre les anomalies de modification. Cependant, ce
nest quen 1981 quun article publi par R. Fagin dcrivit la forme normale
domaine/cl (DK/NF). Cette dernire forme normale permet de garantir
quune table sera toujours exempte danomalies de modification.
Les formes normales sont imbriques dans le sens o une table vrifiant la
deuxime forme normale (2NF) rpond obligatoirement la premire
(1NF). De mme, une table au niveau 3NF est automatiquement conforme
2NF, et ainsi de suite. Dans la plupart des applications pratiques, la
troisime forme normale est suffisante pour assurer un haut degr dintgrit
la base de donnes. Pour avoir une certitude absolue, la forme DK/NF
simpose.
Une fois que vous aurez normalis une base autant quil est possible, vous
pourrez procder des dnormalisations slectives pour amliorer les
performances. Faites alors attention aux types danomalies qui pourraient
survenir.

Premire forme normale


Pour respecter la premire forme normale, une table doit satisfaire aux
conditions suivantes :
La table a deux dimensions, avec des lignes et des
colonnes.

Chaque ligne contient des donnes qui se rapportent


une chose ou une portion dune chose.

Chaque colonne contient des donnes qui correspondent


un seul attribut de la chose dcrite.

Chaque cellule (intersection dune ligne et dune colonne)


ne doit contenir quune seule valeur.

Les entres dune colonne doivent toutes tre du mme


type. Par exemple, si lentre dune ligne de la colonne
contient le nom dun employ, toutes les autres lignes de la
colonne doivent contenir le nom dun employ.

Chaque colonne doit porter un nom unique.

Deux lignes ne peuvent tre identiques (et donc chaque


ligne doit tre unique).

Lordre des colonnes et lordre des lignes nont aucune


signification.

Une table (ou relation) conforme la premire forme normale est


immunise contre certaines anomalies de modification mais peut tre sujette
dautres. La table VENTES de la Figure 5.2 est en premire forme
normale et souffre danomalies de suppression et dinsertion. Par
consquent, la premire forme normale peut suffire certaines applications,
mais pas dautres.

Deuxime forme normale


Pour apprcier ce quest la deuxime forme normale, vous devez
apprhender le concept de dpendance fonctionnelle. Une dpendance
fonctionnelle est une relation entre attributs. Un attribut est
fonctionnellement dpendant dun autre si la valeur du second dtermine
celle du premier. Si vous connaissez la valeur du second attribut, vous
pouvez donc dterminer celle du premier.
Par exemple, supposons quune table dispose des attributs (colonnes)
PRIX_STANDARD, NOMBRE_TESTS et PRIX_STANDARD_TOTAL et
quils sont utiliss dans lquation suivante :

PRIX_STANDARD_TOTAL = PRIX_STANDARD *
NOMBRE_TESTS

PRIX_STANDARD_TOTAL dpend fonctionnellement de PRIX_STAN-


DARD et de NOMBRE_TESTS. Si vous connaissez les valeurs de PRIX_
STANDARD et de NOMBRE_TESTS, vous pouvez calculer PRIX_STAN-
DARD_TOTAL.
Toute table qui se trouve dans la premire forme normale doit avoir une cl
primaire unique. Cette cl peut tre forme partir dune ou de plusieurs
colonnes. Une cl qui porte sur plus dune colonne est dite cl composite.
Pour vrifier la deuxime forme normale (2NF), toutes les colonnes qui ne
servent pas composer la cl doivent dpendre de cette dernire. Ainsi,
toute relation en 1NF, et dont la cl correspond un unique attribut, est
automatiquement en 2NF. Si une relation est une cl composite, tous les
autres attributs doivent dpendre de ceux qui composent cette cl.
En dautres termes, si vous disposez dune table dans laquelle certains
attributs ne participant pas la cl ne dpendent pas de tous les composants
de ladite cl, dcoupez cette table en deux parties ou plus, et ce jusqu ce
que tous les attributs non cl de chaque table dpendent de ceux qui en
composent la cl primaire.
ce stade, un exemple permettra dy voir plus clair. Reprenons la table
VENTES de la Figure 5.2. Mais plutt que denregistrer une seule
commande par client, vous ajoutez une ligne chaque fois que le client achte
un article pour la premire fois. De plus, certains clients (dont CLIENT_ID
est compris entre 1001 et 1007) ont droit une rduction particulire. La
Figure 5.4 reprend quelques lignes de cette table.
Sur la Figure 5.4, CLIENT_ID nidentifie pas de manire unique une ligne
(deux lignes comportent la valeur 1001, et dans deux autres lignes il prend
la valeur 1010). Cependant, la combinaison de CLIENT_ID et de
PRODUIT identifie de manire unique une ligne. Les deux colonnes
forment une cl composite.

FIGURE 5.4 Dans la table VENTES, les colonnes CLIENT_ID et PRODUIT constituent une
cl composite.

Sans le fait que certains clients obtiennent une rduction particulire, la


table ne serait pas en deuxime forme normale. En effet, PRIX (un attribut
qui ne sert pas former la cl) ne dpendrait que dune partie de la cl
composite (PRODUIT). Du fait que certains clients ont droit une
rduction, PRIX peut varier en fonction des valeurs des colonnes
CLIENT_ID et PRODUIT. La table vrifie donc la deuxime forme
normale.
Troisime forme normale
Les tables de la deuxime forme normale sont toujours sujettes certains
types danomalies de modification. Ces anomalies sont engendres par des
dpendances transitives.
Une dpendance transitive se produit quand un attribut dpend dun
deuxime attribut qui dpend son tour dun troisime. Supprimer des
lignes dans une table qui possde ce genre de dpendance peut entraner une
perte dinformations. Une relation qui se trouve en troisime forme normale
est une relation qui se trouve en deuxime forme normale et ne contient
aucune dpendance transitive.
Reprenons la table VENTES de la Figure 5.2. Vous savez dj quelle est
en premire forme normale. Tant que vous nautorisez quune ligne par
CLIENT_ID, votre cl primaire na besoin que dun seul attribut, si bien
que la table est en deuxime forme normale. Cependant, la table est toujours
sujette des anomalies.
Que se passe-t-il si le 1010 nest pas satisfait de son dtergent et quil
demande tre rembours ? Vous devrez supprimer la troisime ligne de la
table. Vous avez maintenant un problme, car vous allez aussi perdre
linformation qui vous indique que le dtergent vaut 4 euros. Cest un
exemple de dpendance transitive : PRIX dpend de PRODUIT, qui lui-
mme dpend de la cl primaire CLIENT_ID.
Il vous faut dcouper la table VENTES en deux tables pour rsoudre le
problme de la dpendance transitive. Sur la Figure 5.3, les deux tables
ACHAT_CLIENT et PRIX_PRODUIT forment une base de donnes qui
vrifie la troisime forme normale.

La forme normale domaine/cl


(DKNF)
Une fois que vous avez pass une base de donnes en troisime forme
normale, vous avez limin presque toute possibilit de voir survenir une
anomalie de modification (mais pas encore toutes les possibilits). Les
formes normales au-del de la troisime sont dfinies pour liminer les
quelques risques restants. La forme normale Boyce-Codd (BCNF), la
quatrime forme normale (4NF) et la cinquime forme normale (5NF) sont
quelques-unes de ces formes supplmentaires. Chacune prvient
lapparition danomalies de modification dans un cas particulier, mais pas
dans tous. Cela, seule la forme normale domaine/cl (DKNF) vous le
garantit.
Une relation est dans une forme normale domaine/cl si chaque contrainte
de la relation est une consquence logique de la dfinition des cls et des
domaines. Dans ce schma, une contrainte correspond toute rgle assez
clairement nonce pour que vous puissiez vrifier quelle sapplique ou
non (en dautres termes, si elle peut tre value comme tant vraie ou
fausse). Une cl est un identifiant unique pour les lignes de la table. Un
domaine est un ensemble de valeurs autorises pour un attribut.
Considrez encore une fois la base de donnes de la Figure 5.2, qui est
en 1NF. Que devriez-vous faire pour la passer en DKNF ?

Table : VENTES (CLIENT_ID, PRODUIT, PRIX)


Cl : CLIENT_ID
Contraintes : 1. CLIENT_ID dtermine PRODUIT
2. PRODUIT dtermine PRIX
3. CLIENT_ID doit tre un entier > 1 000

Pour renforcer la troisime contrainte, vous pouvez modifier la dfinition


du domaine de CLIENT_ID afin dy inclure cette contrainte. Cette dernire
est alors la consquence logique de la dfinition du domaine de la colonne
CLIENT_ID. PRODUIT dpend de CLIENT_ID et CLIENT_ID est une cl,
si bien que la contrainte 1 est vrifie, et est de surcrot une consquence
logique de la dfinition de la cl. La contrainte 2 pose un problme. PRIX
dpend de (est une consquence logique de) PRODUIT qui nest pas une
cl. La solution consiste diviser la table VENTES en deux tables. Lune
de ces tables utilise CLIENT_ID pour cl tandis que lautre prend
PRODUIT pour cl. Cest la configuration de la Figure 5.3. La base de
donnes qui y est reprsente, en plus dtre en 3NF, est aussi conforme aux
spcifications DKNF.
Concevez vos bases de donnes pour quelles soient si possible en DKNF.
Il ne pourra alors plus survenir danomalies de modification. Si la structure
dune base de donnes vous interdit de vous conformer DKNF, vous
devrez intgrer des contrles de contraintes dans lapplication qui utilise la
base de donnes. En effet, la base de donnes ne garantit pas par elle-mme
que ces contraintes seront respectes.

La forme anormale
Adopter une forme anormale est parfois une bonne solution. En effet, si
vous poussez la normalisation trop loin, vous risquez de gnrer tellement
de tables que la base de donnes en deviendra totalement ingrable et
inefficace. De plus, les performances pourraient seffondrer au passage.
Une structure viable est souvent un peu dnormalise. En pratique, les bases
de donnes ne sont presque jamais totalement en DKNF. Pour autant, vous
devez tenter de normaliser le plus possible les bases de donnes que vous
concevez afin dliminer au maximum les risques de corruption des donnes
rsultant danomalies de modification.
Une fois la base de donnes normalise autant que faire se peut, revenez en
arrire. Si les performances ne sont pas satisfaisantes, rexaminez votre
travail de conception et voyez si une dnormalisation slective serait
mme damliorer ces performances sans sacrifier lintgrit. En ajoutant
avec grand soin une certaine dose de redondance dans des emplacements
stratgiques, et en acceptant une part de dnormalisation, vous pourrez
arriver une base de donnes qui sera la fois efficace et labri des
anomalies.
III
Enregistrer et extraire des
donnes

DANS CETTE PARTIE...

Grer des donnes.

Suivre le temps.

Traiter des valeurs.

Construire des requtes.

Visiter le contenu en ligne des Nuls sur


www.dummies.com/extras/sql.
Chapitre 6
Manipuler les donnes dune base
DANS CE CHAPITRE :
Utiliser des donnes.

Extraire dune table les donnes dont vous avez besoin.

Nafficher que les informations voulues partir dune ou plusieurs tables.

Mettre jour des informations dans des tables et des vues.

Ajouter une nouvelle ligne une table.

Modifier toutes ou certaines des donnes dune ligne.

Supprimer une ligne dans une table.

L
es Chapitres 3 et 4 vous ont appris combien il est indispensable de
donner votre base une bonne structure pour prserver lintgrit des
donnes quelle contient. Mais plus que la structure, ce sont les donnes
qui vous intressent. Vous voulez pouvoir les ajouter des tables, les
extraire et les afficher, les modifier, et enfin les supprimer.

En principe, la manipulation des donnes contenues dans une base est assez
simple. Il nest pas compliqu de comprendre comment ajouter des donnes
une table vous pouvez le faire ligne par ligne ou en une seule fois.
Modifier, supprimer ou extraire des lignes dune table na rien de difficile
en pratique. En fait, la vritable difficult est darriver slectionner les
lignes que vous voulez modifier, extraire ou supprimer. Extraire des
informations peut se rvler aussi compliqu que de rechercher une aiguille
dans une meule de foin, car les donnes que vous recherchez peuvent tre
noyes dans une base extrmement volumineuse. Fort heureusement, et pour
peu que vous sachiez formuler votre recherche, linstruction SQL SELECT,
lordinateur fera tout le travail votre place. Daccord. Dire quil est facile
de manipuler une base de donnes avec SQL, dajouter, de modifier, de
supprimer ou de retrouver des informations est peut-tre un peu exagr...
Commenons donc par un exemple rellement simple.

Extraire des donnes


La manipulation des donnes laquelle les utilisateurs procdent le plus
souvent est lextraction dinformations slectionnes dans une base. Vous
voulez par exemple rcuprer le contenu dune certaine ligne parmi les
milliers que comporte une table. Ou bien vous voulez trouver toutes les
lignes qui satisfont un critre ou une combinaison de critres. Il se peut
aussi que vous ayez besoin de rcuprer toutes les lignes dune table.
Linstruction SELECT effectue toutes ces tches votre place.

La forme la plus simple de linstruction SELECT est celle qui retourne


toutes les lignes dune table :

SELECT * FROM CLIENTS ;

Ltoile (*) est un caractre de substitution (un joker) qui dsigne tout. Dans
ce contexte, ltoile correspond tous les noms de colonnes de la table
CLIENTS. Il en rsulte que toutes les lignes de toutes les colonnes de cette
table vous sont retournes. En dautres termes, linstruction ci-dessus
renvoie la totalit de la table.
Les instructions SELECT peuvent tre bien plus complexes que celle
prsente dans lexemple prcdent. En fait, certaines instructions SELECT
sont si complexes quelles en sont virtuellement indchiffrables. Cette
complexit potentielle tient au fait que vous pouvez accoler de nombreuses
clauses modificatrices linstruction. Le Chapitre 10 prsente ces clauses
dans le dtail. Je vais ici brivement parler de la clause WHERE, qui est la
plus communment employe pour limiter le nombre de lignes retournes
par une instruction SELECT.

Une instruction SELECT accompagne de la clause WHERE adopte la


forme suivante :

SELECT liste_colonnes FROM nom_table


WHERE condition ;

Liste_colonnes spcifie quelles colonnes vous voulez dans la table.


Linstruction naffichera que ces colonnes. La clause FROM indique la table
do vous voulez extraire ces colonnes. La clause WHERE exclut toutes les
lignes qui ne rpondent pas vos conditions. Une condition peut tre simple
(par exemple, WHERE ETAT_CLIENT = CA) ou compose (par
exemple WHERE ETAT_CLIENT = CA AND STATUT =
Actif). Lexemple suivant montre quoi peut ressembler une requte
qui comprend une condition composite :

SELECT NOM_CLIENT, TELEPHONE_CLIENT FROM CLIENTS


WHERE ETAT_CLIENT = CA
AND STATUT = Actif ;

SQL ET LES OUTILS PROPRITAIRES

Les instructions SELECT ne constituent pas le seul moyen dextraire


des donnes dune base. Si vous utilisez un SGBD, ce dernier dispose
probablement doutils propritaires conus pour cet usage. Vous
pouvez utiliser ces outils (qui sont gnralement assez intuitifs) pour
ajouter, supprimer, modifier et extraire des donnes.

De nombreux front-end de SGBD vous permettent de choisir entre


utiliser ces outils propritaires ou utiliser SQL. Il arrive parfois que les
outils propritaires ne permettent pas dobtenir tout ce quil est
possible dexprimer en SQL. Si vous devez effectuer une opration que
ces outils ne supportent pas, il vous faudra utiliser SQL. Il est donc
particulirement utile de se familiariser avec ce langage, mme si
vous comptez utiliser un outil propritaire la plupart du temps. Pour
accomplir avec succs une opration trop complexe pour votre outil
propritaire, il faut que vous ayez les ides au clair sur le
fonctionnement de SQL et sur ce quil est capable de faire.
Linstruction retourne les noms et numros de tlphone de tous les clients
actifs qui vivent en Californie. Le mot cl AND signifie que vous ne voulez
rcuprer que les lignes qui vrifient les deux conditions que vous posez.

Crer des vues


La structure dune base conue en respectant les rgles du genre (dont
notamment une normalisation approprie, voir Chapitre 5) optimise
lintgrit des donnes. Pour autant, cette structure nest souvent pas la plus
adapte pour reprsenter visuellement les donnes quelle contient.
Plusieurs applications peuvent utiliser les mmes donnes, mais chacune les
affiche sa manire. Lune des fonctionnalits les plus puissantes de SQL
est la possibilit de gnrer des reprsentations des donnes les vues
dont la structure diffre de celle de la base. Les tables dont vous utilisez
les lignes et les colonnes dans une vue sont les tables de base. Le
Chapitre 3 traite des vues qui sont un des lments du langage de dfinition
des donnes (DDL). Dans cette section, jexplique quoi servent les vues
dans le contexte de la rcupration et de la manipulation des donnes.
Une instruction SELECT retourne toujours un rsultat sous la forme dune
table virtuelle. Une vue est une varit de table virtuelle. Vous pouvez
diffrencier une vue des autres varits de tables virtuelles, car sa
dfinition est mmorise dans les mtadonnes de la base, ce qui lui confre
une persistance que nont pas les autres tables virtuelles.
Vous pouvez manipuler une vue comme sil sagissait dune table normale.
La diffrence est que les donnes dune vue nont pas dexistence
indpendante. Elles proviennent en effet dune ou plusieurs tables (celles
qui ont justement servi dfinir la vue). Chaque application est donc
mme dappliquer son propre point de vue sur un ensemble de donnes.
Reprenons lexemple de la base de donnes dcrite au Chapitre 5. Cette
base contient cinq tables : CLIENTS, TESTS, EMPLOYES, COMMANDES
et RESULTATS. Supposons que le responsable du marketing pour les tats-
Unis dsire connatre les tats do proviennent les commandes. Une partie
de cette information se trouve dans la table CLIENTS et une autre dans la
table COMMANDES. Supposons maintenant que le responsable du contrle
qualit dsire comparer la date laquelle un test est command et celle
laquelle le rsultat final est produit. Cette comparaison requiert des donnes
des tables COMMANDES et RESULTATS. Pour rpondre aux besoins de
ces deux personnes, vous pouvez crer des vues qui contiennent les donnes
dont vous avez besoin dans chaque cas.

partir de tables
Pour le responsable du marketing, vous pouvez crer la vue reprsente
Figure 6.1.

FIGURE 6.1 La vue COM-MANDES_ PAR_ETAT pour le responsable marketing.

Linstruction suivante cre la vue souhaite :

CREATE VIEW COMMANDES_PAR_ETAT


(NOM_CLIENT, ETAT, NUMERO_COMMANDE)
AS SELECT CLIENTS.NOM_CLIENT, ETAT,
NUMERO_COMMANDE
FROM CLIENTS, COMMANDES
WHERE CLIENTS.NOM_CLIENT =
COMMANDES.NOM_CLIENT ;
La nouvelle vue dispose de trois colonnes, NOM_CLIENT, ETAT et
NUMERO_COMMANDE. NOM_CLIENT apparat la fois dans CLIENTS
et dans COMMANDES, et il sert de lien entre ces deux tables. La vue tire
linformation ETAT de la table CLIENTS et linformation NU-
MERO_COMMANDE de la table COMMANDES.
Dans lexemple prcdent, vous dclarez explicitement le nom des colonnes
de la nouvelle vue. Cette prcision nest pas ncessaire si les noms des
colonnes de la vue sont les mmes que ceux des colonnes auxquelles elles
correspondent dans les tables sources. Lexemple de la section suivante
prsente lutilisation dune instruction CREATE VIEW o les noms des
colonnes sont fournis de manire implicite.

Avec un critre de slection


Le responsable qualit a besoin dune vue diffrente de la prcdente. Elle
est dcrite Figure 6.2.

FIGURE 6.2 La vue RAPPORT_RE-TARD pour le responsable qualit.

Linstruction suivante cre la vue :


CREATE VIEW RAPPORT_RETARD
AS SELECT COMMANDES.NUMERO_COMMANDE,
DATE_COMMANDE,
DATE_RAPPORT
FROM COMMANDES, RESULTATS
WHERE COMMANDES.NUMERO_COMMANDE =
RESULTATS.NUME-
RO_COMMANDE
AND RESULTATS.PRELIMINAIRE_FINAL = F ;

Cette vue contient linformation DATE_COMMANDE en provenance de la


table COMMANDES, et les dates des rsultats dfinitifs fournis par la table
RESULTATS. Seules les lignes de la table RESULTATS dont la colonne
PRELIMINAIRE_FINAL contient la valeur F apparaissent dans la
vue. Notez en passant que la liste des colonnes spcifie dans la vue
COMMANDES_PAR_ETAT est facultative. La vue fonctionnerait
parfaitement sans cette liste.

Avec un attribut modifi


La clause SELECT des deux exemples prcdents ne contient que des
noms de colonnes. Cependant, vous pouvez aussi y inclure des expressions.
Supposons que le propritaire de VetLab fte lanniversaire de sa socit et
dsire le clbrer en offrant une rduction de 10 % tous ses clients. Il peut
crer une vue base sur les tables TESTS et COMMANDES en utilisant
linstruction suivante :

CREATE VUE_ANNIVERSAIRE
(NOM_CLIENT, TEST, DATE_COMMANDE,
PRIX_ANNIVERSAIRE)
AS SELECT NOM_CLIENT, TEST_COMMANDE,
DATE_COMMANDE,
PRIX_STANDARD * .9
FROM COMMANDES, TESTS
WHERE TEST_COMMANDE = NOM_TEST ;

La Figure 6.3 montre comment crer cette vue.

FIGURE 6.3 La vue cre pour afficher les prix anniversaire.

Vous pouvez crer une vue partir de plusieurs tables, comme dans les
exemples prcdents, ou partir dune seule table. Si vous navez pas
besoin de certaines colonnes ou lignes dune table, crez une vue qui les
limine. Cela vous vitera de modifier accidentellement le contenu dune
colonne sur laquelle vous ne souhaitez pas travailler.
Une autre bonne raison de crer des vues est dassurer la scurit des tables
sous-jacentes. Si vous voulez permettre la consultation de quelques
colonnes dune table tout en dissimulant les autres, vous pouvez crer une
vue ne contenant que les colonnes que vous souhaitez rendre publiques.
Vous navez plus alors qu autoriser largement laccs la vue tout en
restreignant fortement laccs la table sous-jacente. Cest un bon procd
pour la scuriser. Le Chapitre 14 explore la scurit des bases de donnes
et explique comment accorder et rvoquer des privilges.

Modifier les vues


peine cre, une table est en soi susceptible dtre remplie, dite,
modifie, vide... Les vues noffrent pas ncessairement les mmes
possibilits. Si vous ditez une vue, vous modifiez en ralit la table sous-
jacente. Voici quelques problmes potentiels que vous pouvez rencontrer
lorsque vous actualisez des vues :
Certaines vues prennent leurs donnes dans plusieurs
tables. Si vous modifiez une telle vue, comment savoir
laquelle des tables sous-jacentes sera modifie ?

Une vue peut inclure une expression dans une liste


SELECT. Du fait que les expressions ne correspondent pas
directement des lignes de vos tables, le SGBD ne sait pas
comment les mettre jour.

Supposons que vous ayez cr une vue en utilisant linstruction suivante :

CREATE VIEW COMP (NomEmploye, Paye)


AS SELECT NomEmploye, Salaire+Comm AS Paye
FROM EMPLOYES ;

Pouvez-vous mettre jour Paye en utilisant linstruction suivante ?

UPDATE COMP SET Paye = Paye + 100 ;

Cela naurait aucun sens car la table sous-jacente ne contient pas de colonne
Paye. Vous ne pouvez pas mettre jour quelque chose qui nexiste pas
dans la table sous-jacente.
Souvenez-vous de ceci chaque fois que vous utilisez une vue : vous ne
pouvez modifier une colonne de la vue que si elle correspond une colonne
dune table de base sous-jacente.

Ajouter de nouvelles donnes


Une table qui vient dtre cre (que ce soit laide dune instruction SQL
ou via un RAD) est un ensemble structur qui ne contient aucune
information. Une coquille vide, donc. Pour la rendre utile, il faut y stocker
des donnes, dont vous disposez peut-tre dj (ou non) sous une forme
numrique. Ces donnes peuvent apparatre sous lune des formes
suivantes :
Elles ne sont pas encore compiles sous une forme
numrique quelconque. Quelquun devra probablement
utiliser son clavier et son moniteur pour les saisir
manuellement, une par une. Vous pourriez aussi utiliser un
scanner ou un systme de reconnaissance vocale, mais ce
type de saisie est encore peu rpandu (et surtout dune
fiabilit insuffisante).

Elles existent dj sous une forme numrique mais


dans un format diffrent de celui utilis par les tables o
vous comptez les stocker. Vous devrez tout dabord les
convertir dans le format appropri puis les insrer dans la
base.

Elles sont dj compiles dans le bon format


numrique. Vous tes prt oprer le transfert vers une
nouvelle base de donnes.

Les sections qui suivent dcrivent les procdures dinsertion des donnes
dans une table en fonction de la forme quelles prennent. Selon le cas, vous
pourrez importer toutes vos donnes en une seule fois ou bien
enregistrement par enregistrement. Chaque enregistrement correspond une
ligne de la table.

Ajouter une ligne la fois


La plupart des SGBD permettent de saisir des donnes via un formulaire.
Cela vous permet de crer des crans qui contiennent des champs pour
chaque colonne dune table. Le libell des champs de saisie dans le
formulaire renseigne lutilisateur sur la colonne correspondante (si cest
crit Date de commande, tout le monde est cens comprendre quil faut
entrer ici la date de la commande en cours de traitement). Loprateur saisit
dans le formulaire toutes les donnes enregistrer dans une seule et mme
ligne. Une fois que le SGBD a accept cette nouvelle ligne, le systme
rafrachit le formulaire pour permettre la saisie dune nouvelle srie de
donnes. De cette manire, il est simple (quoique fastidieux) de remplir la
table ligne par ligne.
Un systme de formulaires est facile comprendre et moins sujet aux
erreurs de saisie que lutilisation par exemple de listes de valeurs spares
par des virgules (format csv). Le principal problme, cependant, est quil
nexiste aucun standard en ce domaine. Chaque SGBD propose sa propre
solution pour crer des formulaires. Pour autant, cette diversit ne pose pas
de problme loprateur, car les formulaires adoptent presque toujours le
mme aspect dun SGBD un autre. Cest le dveloppeur de lapplication
qui doit reprendre sa formation zro chaque fois quil change de SGBD,
pas loprateur. Un autre problme possible tient au fait que certaines
implmentations ne permettent pas de mettre en uvre dans les formulaires
tous les contrles de validation que vous souhaiteriez effectuer lors de la
saisie des donnes.
La meilleure solution pour maintenir lintgrit des donnes de la base
consiste en premier lieu limiter la saisie de donnes errones. Pour cela,
vous devez appliquer des contraintes sur les champs de saisie dun
formulaire. Vous serez ainsi certain que la base de donnes naccepte que
des valeurs du bon type et qui appartiennent aux bonnes plages de valeurs.
Bien entendu, ces contraintes ne peuvent pas permettre de prvenir toutes
les erreurs possibles et imaginables.
Si loutil de conception de formulaires de votre SGBD ne vous permet pas
dappliquer tous les contrles requis pour prserver lintgrit des donnes,
vous pouvez crer votre propre cran, stocker les donnes saisies dans des
variables, puis tester ces variables en utilisant du code applicatif. Une fois
que vous serez certain que les donnes saisies sont valides, vous pourrez
insrer la ligne en faisant appel la commande SQL INSERT.
Utilisez la commande SQL INSERT pour insrer les donnes dans une
ligne dune table :

INSERT INTO table_1 [(colonne_1, colonne_2, ...,


co-
lonne_n)]
VALUES (valeur_1, valeur_2, ..., valeur_n) ;
Comme le laissent entendre les crochets ([]), la liste des noms de colonnes
est optionnelle. La liste par dfaut correspond lensemble des colonnes de
la table (dans lordre o elles sont dfinies dans celle-ci). Si vous
fournissez les valeurs dans lordre des colonnes de la table, ces lments
seront enregistrs au bon endroit. Par contre, si les valeurs sont places
dans un ordre diffrent, vous devez explicitement indiquer quelle colonne
doit prendre quelle valeur.
Utilisez par exemple la syntaxe suivante pour saisir un enregistrement dans
la table CLIENTS :

INSERT INTO CLIENTS (CLIENT_ID, PRENOM, RUE,


VILLE, ETAT,
CODE_POSTAL,
TELEPHONE)
VALUES (:vclientid, David, Taylor, 235
Nutley
Ave.,
Nutley, NJ, 07110, (201) 555-1963) ;

Le premier lment de la liste VALUE, , vclientid, est une variable que


le code de votre programme incrmente chaque fois que vous ajoutez une
nouvelle ligne dans la table. De la sorte, vous tes certain que deux lignes
ne contiendront pas la mme valeur CLIENT_ID. Cette colonne est en effet
la cl primaire pour cette table, et chaque identifiant doit rester unique. Les
valeurs restantes sont de simples donnes (plutt que des variables
contenant ces donnes). Bien entendu, vous pourriez, si vous le souhaitiez,
stocker toutes ces donnes dans des variables. Les arguments du mot cl
VALUES peuvent en effet tre aussi bien des variables que des copies
explicites des donnes elles-mmes.

Ajouter des donnes des


colonnes choisies
Vous voulez parfois noter lexistence dun objet sans pour autant disposer
de toutes les informations qui le concernent. Vous pouvez alors insrer une
ligne pour cet objet sans renseigner toutes les colonnes de la table. Pour
vous assurer que la table soit en premire forme normale, cependant, vous
devrez fournir suffisamment de donnes pour que toutes les lignes restent
distinctes (pour plus dinformations sur la premire forme normale, voir le
Chapitre 5). Spcifier la cl primaire de la nouvelle ligne suffit satisfaire
cette condition. Les colonnes que vous ne renseignerez pas contiendront une
valeur nulle.
Voici un exemple de saisie partielle :

INSERT INTO CLIENTS (CLIENT_ID, PRENOM, NOM)


VALUES (:vclientid, Tyson, Taylor) ;

Vous ninsrez que le numro didentification unique du client, son nom et


son prnom.

Ajouter un bloc de lignes une


table
Alimenter une base de donnes ligne par ligne en utilisant des instructions
INSERT est particulirement astreignant (et mme carrment roboratif),
surtout si vous devez le faire toute la journe. Mme la plus labore des
interfaces graphiques ne vous vitera pas de sombrer dans lennui.
Clairement, il est toujours plus agrable de disposer dune solution fiable
permettant dautomatiser la saisie des donnes que dobliger quelquun
rester assis toute la journe devant son clavier et ses listings de donnes.
Automatiser la saisie est possible quand, par exemple, les donnes existent
dj sous une forme numrique (quelquun les a dj saisies manuellement).
Inutile de faire bgayer lhistoire. Un ordinateur est tout fait capable de
transfrer des donnes dun fichier un autre avec un minimum
dintervention humaine. Pour peu que vous connaissiez les caractristiques
de la donne source et le format de la table destination, vous pourrez (en
principe) automatiser le transfert.

Copier depuis un fichier de


donnes tranger
Supposons que vous soyez en train de crer une base de donnes pour une
nouvelle application. Certaines des donnes dont vous avez besoin existent
dj dans un fichier informatique. Il peut sagir dun fichier plein texte ou
bien dune table dans une base que gre un autre SGBD. Ces donnes sont
peut-tre en ASCII ou en EBCDIC, ou dans nimporte quel format
propritaire. Comment procder ?
Priez tout dabord pour que les donnes soient dans un format largement
utilis. Si cest le cas, il se peut quil existe un outil de conversion capable
den raliser la traduction dans un ou plusieurs autres formats courants.
Votre environnement de dveloppement sait probablement grer lun de ces
formats. Sur les ordinateurs personnels, Access, xBASE et MySQL sont les
plus utiliss. Si les donnes que vous souhaitez utiliser sont dans lun de ces
formats, la conversion sera un jeu denfant. Sinon, il vous faudra procder
en deux tapes.
En dernier ressort, vous pourrez toujours vous retourner vers des
professionnels de la conversion si le format de vos donnes est trop ancien,
propritaire, autant dire dfunt. Ces gens se sont spcialiss dans les
conversions et ils savent grer des centaines de formats dont personne ou
presque na jamais entendu parler. Donnez-leur une bande ou un disque qui
contient les donnes convertir, et ils vous les rendront dans le format de
votre choix.

Transfrer toutes les lignes entre des


tables
Importer des donnes depuis une table de votre base pour les combiner aux
donnes dune autre table est un problme bien moins dlicat. Cette
importation ne pose pas de difficults si la structure de la seconde table est
identique celle de la premire, cest--dire si chaque colonne de la
premire table dispose dune colonne correspondante dans la seconde, et si
les types de donnes de ces deux colonnes sont sinon identiques du moins
compatibles. Si tel est le cas, vous pouvez combiner les donnes des deux
tables en utilisant loprateur relationnel UNION. Le rsultat produit sera
une table virtuelle qui sera la somme des deux tables. Je traite des
oprateurs relationnels, dont UNION, au Chapitre 11.

Transfrer certaines colonnes et


certaines lignes entre des tables
La plupart du temps, les donnes de la table source nadoptent pas
exactement la structure de la table vers laquelle vous voulez les transfrer.
Il se peut que seules certaines colonnes se retrouvent dans la structure de la
table destination, et ce sont prcisment ces colonnes que vous voulez
transfrer. En combinant les oprateurs SELECT et UNION, il est possible
de spcifier les colonnes de la table source qui seront incluses dans la table
virtuelle rsultante. En utilisant des clauses WHERE dans les instructions
SELECT, vous pouvez conditionner le transfert des lignes certaines
conditions. Je traite dans le dtail de la clause WHERE au Chapitre 10.
Supposons que vous disposiez de deux tables, PROSPECTS et CLIENTS,
et que vous dsiriez connatre la liste des personnes qui apparaissent dans
les deux tables comme rsidant dans le Maine. Vous pouvez crer une table
virtuelle contenant les informations voulues en utilisant la commande
suivante :

SELECT NOM, PRENOM


FROM PROSPECTS
WHERE ETAT = ME
UNION
SELECT NOM, PRENOM
FROM CLIENTS
WHERE ETAT = ME ;

Voyons cela de plus prs :


Les instructions SELECT spcifient que les colonnes
incluses dans la table virtuelle rsultat sont NOM et
PRENOM.

Les clauses WHERE limitent les lignes incluses celles


dont la colonne ETAT contient la valeur ME.

La colonne ETAT nest pas incluse dans la table de


rsultat, mais elle est prsente dans les deux tables
sources.

Loprateur UNION combine les rsultats produits par


SELECT sur PROSPECTS avec les rsultats produits par
SELECT sur CLIENTS, supprime les lignes redondantes et
affiche le rsultat.

Une autre manire de copier les donnes dune table vers une autre consiste
imbriquer une instruction SELECT dans une instruction INSERT. Cette
mthode (une sous-slection prsente au chapitre 12) ne cre pas de table
virtuelle mais duplique les donnes slectionnes. Vous pouvez prendre
toutes les lignes de la table CLIENTS et les insrer dans la table
PROSPECTS. Bien entendu, cela ne marche que si les structures des deux
tables sont identiques. Si vous voulez par la suite placer dans la table
PROSPECTS les seuls clients qui vivent dans le Maine, une simple
instruction SELECT comportant une seule condition dans la clause WHERE
suffira rpondre la question :

INSERT INTO PROSPECT


SELECT * FROM CLIENTS
WHERE ETAT = ME ;

Bien que cette opration cre des donnes redondantes (vous stockez
dsormais des donnes relatives aux clients dans la table PROSPECTS et
dans la table CLIENTS), il peut savrer utile de leffectuer, car elle
permet damliorer les performances. Faites cependant attention la
redondance. Pour maintenir la cohrence des donnes, noubliez pas de
reproduire dans la seconde table toutes les oprations de suppression, de
modification ou dajout auxquelles vous procdez dans la premire. Un
autre problme potentiel est le risque de duplication des cls primaires. Si
un prospect prexistant possde une cl primaire (ProspectID) identique
celle dun client (ClientID) que vous tentez dajouter la table
PROSPECTS, lopration dinsertion chouera.

Modifier des donnes existantes


Dans ce monde, la seule chose permanente, cest le changement. Si vous
craignez la routine, il vous suffit dattendre un peu. Et puisque le
changement est la rgle, il en va de mme pour vos bases de donnes. Un
client change dadresse, le stock diminue (ce qui est heureux pour vous), le
classement du championnat de foot volue chaque semaine... Autant
dvnements qui ncessitent une actualisation de votre base de donnes.
Linstruction UPDATE de SQL permet de modifier les donnes dune table.
laide dune seule instruction UPDATE, vous pouvez actualiser une,
quelques-unes ou toutes les lignes dune table. Cette instruction sutilise de
la manire suivante :

UPDATE nom_table
SET colonne_1 = expression_1, colonne_2 =
expression_2,
..., colonne_n = expression_n
[WHERE predicats] ;

La clause WHERE est facultative. Elle sert spcifier les lignes quil faut
mettre jour. Si vous ne lutilisez pas, toutes les lignes de la table seront
modifies. La clause SET fournit les nouvelles valeurs affecter aux
colonnes que vous modifiez.
Prenez lexemple de la table CLIENTS du Tableau 6.1.

TABLEAU 6.1 La table CLIENTS

Nom Ville Indicatif Tlphone

Abe Abelson Springfield (714) 555-1111

Bill Bailey Decatur (714) 555-2222

Chuck Wood Philo (714) 555-3333

Don Stetson Philo (714) 555-4444

Dolph Stetson Philo (714) 555-5555


La liste des clients est parfois modifie les gens dmnagent, changent de
numro de tlphone, et ainsi de suite. Supposons quAbe Abelson quitte
Springfield pour habiter Kankakee (cest un joli nom, vous ne trouvez
pas ?). Vous pouvez mettre jour son enregistrement dans la table en
utilisant linstruction UPDATE suivante :

UPDATE CLIENTS
SET VILLE = Kankakee, TELEPHONE = 666-6666
WHERE NOM = Abe Abelson ;

Cette instruction cre les modifications reprises dans le tableau 6.2.

TABLEAU 6.2 La table CLIENTS aprs un UPDATE sur une ligne.

Nom Ville Indicatif Tlphone

Abe Abelson Kankakee (714) 555-1111

Bill Bailey Decatur (714) 555-2222

Chuck Wood Philo (714) 555-3333

Don Stetson Philo (714) 555-4444

Dolph Stetson Philo (714) 555-5555

Vous pouvez utiliser une instruction similaire pour modifier plusieurs


lignes. Supposons que la population de la localit Philo soit en train
dexploser. Du coup, la ville a dsormais besoin de son propre code local.
Vous pouvez appliquer une modification tous les clients qui vivent Philo
laide dune seule instruction UPDATE :

UPDATE CLIENTS
SET CODE LOCAL = (619)
WHERE VILLE = Philo ;

La table ressemble maintenant celle reprise dans le Tableau 6.3.


Il est encore plus facile de mettre jour en une seule fois toutes les lignes
de la table. Nul besoin dutiliser la clause WHERE pour limiter les effets
de linstruction. Supposons que la ville de

TABLEAU 6.3 La table CLIENTS aprs un UPDATE sur plusieurs lignes.

Nom Ville Indicatif Tlphone

Abe Abelson Kankakee (714) 666-6666

Bill Bailey Decatur (714) 555-2222

Chuck Wood Philo (619) 555-3333

Don Stetson Philo (619) 555-4444

Dolph Stetson Philo (619) 555-5555

Rantoul acquire une importance politique majeure au point dannexer


Kankakee, Decatur et Philo, ainsi que toutes les villes cites dans la base de
donnes. Vous pouvez mettre jour toutes les lignes de la manire suivante :

UPDATE CIENTS
SET VILLE = Rantoul ;

Le Tableau 6.4 vous montre le rsultat.

TABLEAU 6.4 La table CLIENTS aprs UPDATE de toutes les lignes.

Nom Ville Indicatif Tlphone

Abe Abelson Rantoul (714) 666-6666

Bill Bailey Rantoul (714) 555-2222

Chuck Wood Rantoul (619) 555-3333

Don Stetson Rantoul (619) 555-4444


Dolph Stetson Rantoul (619) 555-5555

La clause WHERE que vous utilisez pour identifier les lignes auxquelles
linstruction UDPATE sapplique peut contenir une sous-slection. Une
sous-slection vous permet de mettre jour des lignes dans une table en
fonction du contenu dune autre table.
Supposons par exemple que vous soyez un grossiste et que votre base de
donnes contienne une base VENDEURS enregistrant les noms de tous les
producteurs auxquels vous achetez vos produits. Vous pouvez aussi avoir
une table PRODUITS pour les noms de tous les produits que vous revendez
et les prix de chacun. La table VENDEURS possde les colonnes VEN-
DEUR_ID, VENDEUR_NOM, RUE, VILLE, ETAT et CODE_POSTAL. La
table PRODUITS contient PRODUIT_ID, PRODUIT_NOM,
VENDEUR_ID et PRIX_VENTE.
Lun de vos vendeurs, Cumulonimbus Corporation, dcide daugmenter le
prix de tous ses produits de 10 %. Pour maintenir votre marge, vous devez
remonter les prix auxquels vous vendez les produits de Cumulonimbus
de 10 %. Vous pouvez le faire en une seule instruction UPDATE :

UPDATE PRODUITS
SET PRIX_VENTE = (PRIX_VENTE * 1.1)
WHERE VENDEUR_ID IN
(SELECT VENDEUR_ID FROM VENDEURS
WHERE VENDEUR_NOM = Cumulonimbus
Corporation) ;

La sous-slection trouve le VENDEUR_ID de Cumulonimbus. Vous pouvez


alors utiliser le champ VENDEUR_ID de la table PRODUITS pour
rechercher toutes les lignes que vous devez mettre jour. Les prix de tous
les articles de Cumulonimbus seront augments de 10 %. Les autres tarifs ne
seront pas modifis. Je traite des sous-slections plus en dtail au
Chapitre 12.

Transfrer des donnes


En plus dINSERT et UPDATE, vous disposez dune instruction
supplmentaire pour ajouter des donnes une table ou une vue : MERGE.
Elle permet de fusionner des donnes partir dune table ou dune vue vers
une autre table ou vue. Lobjectif peut tre dajouter de nouvelles lignes ou
deffectuer une mise jour. MERGE est intressante pour prendre des
donnes qui existent dj dans une base pour les copier vers une nouvelle
destination.
Prenons comme exemple la base de donnes VetLab dcrite au Chapitre 5.
Supposons que, dans le personnel du laboratoire, se trouvent des
commerciaux chargs des ventes, dautres qui ont simplement traiter
celles-ci, ainsi que des employs des services gnraux. Les affaires de
votre filiale amricaine ont t bonnes lanne dernire, et vous voudriez
partager les fruits de la croissance avec votre personnel. Vous dcidez
dattribuer une prime de 100 euros aux commerciaux qui ont ralis au
moins une vente, et de 50 euros tous les autres. Vous commencez par crer
une table PRIMES. Vous y insrez ensuite un enregistrement pour chaque
employ qui apparat au moins une fois dans la table COMMANDES, en
leur affectant une prime par dfaut de 100 euros.
Vous voulez maintenant utiliser linstruction MERGE pour insrer de
nouveaux enregistrements concernant les autres employs. Le montant de
leur prime est donc de 50 euros. Voyons le code qui permet de crer la table
PRIMES et de la remplir :

CREATE TABLE PRIMES (


NOM_EMPLOYE CHARACTER (30) PRIMARY KEY,
PRIME NUMERIC DEFAULT 100 ) ;

INSERT INTO PRIMES (NOM_EMPLOYE)


(SELECT NOM_EMPLOYE FROM EMPLOYES, COMMANDES
WHERE EMPLOYES.NOM_EMPLOYE =
COMMANDES.COMMERCIAL
GROUP BY EMPLOYES.NOM_EMPLOYE) ;

Vous pouvez maintenant interroger la table PRIMES pour voir ce quelle


contient :

SELECT * FROM PRIMES ;


NOM_EMPLOYE PRIME
--------------- ----------
Brynna Jones 100
Chris Bancroft 100
Greg Bosser 100
Kyle Weeks 100

Il est ensuite facile de donner une prime de 50 euros au reste des employs :

MERGE INTO PRIMES


USING EMPLOYES
ON (PRIMES.NOM_EMPLOYE =
EMPLOYES.NOM_EMPLOYE)
WHEN NOT MATCHED THEN INSERT
(PRIMES.NOM_EMPLOYE, PRIMES.PRIME)
VALUES (EMPLOYES.NOM_EMPLOYE, 50) ;

Vous insrez ainsi dans la table PRIMES des enregistrements pour les
personnes de la table EMPLOYES qui ne sont pas dj mmorises dans
ladite table PRIMES. Ces agents se voient attribuer une prime de 50 euros.
Une requte sur la table PRIMES pourrait alors donner ceci :

SELECT * FROM PRIMES ;

NOM_EMPLOYE PRIME
--------------- ----------
Brynna Jones 100
Chris Bancroft 100
Greg Bosser 100
Kyle Weeks 100
Neth Doze 50
Matt Bak 50
Sam Saylor 50
Nic Foster 50
Les quatre premiers enregistrements, ceux qui ont t crs par linstruction
INSERT, sont classs dans lordre alphabtique des noms. Les quatre
autres, ajouts via linstruction MERGE, apparaissent dans lordre o ils
figurent dans la table EMPLOYES.

Supprimer des donnes obsoltes


Le temps passe, et votre table peut finir par contenir des donnes qui ne sont
plus utiles. Vous voudrez alors les supprimer, car elles occupent de la place
et prtent confusion. Vous pourriez les transfrer dans une table archive
que vous rendriez inaccessible. De la sorte, vous pourrez toujours les
rcuprer si le besoin sen fait sentir. Mais que vous dcidiez darchiver ou
non des donnes obsoltes, il faudra les supprimer de la base. SQL vous
permet deffacer des lignes de vos tables laide de linstruction DELETE.
Vous pouvez dtruire toutes les lignes dune table en utilisant une seule
instruction DELETE, ou limiter la suppression quelques lignes en ajoutant
une clause WHERE. La syntaxe que vous emploierez est semblable celle
de linstruction SELECT, ceci prs que vous ne spcifiez aucune colonne.
Si vous supprimez une ligne, vous supprimez lvidence toutes les
donnes que contiennent ses colonnes !
Par exemple, supposons que votre client David Taylor vienne juste de
dmnager Tahiti, si bien quil ne va plus jamais vous acheter quoi que ce
soit. Vous pouvez le retirer de votre table CLIENTS en utilisant linstruction
suivante :

DELETE FROM CLIENTS


WHERE PRENOM = David AND NOM = Taylor ;

En supposant quil nexiste quun seul client David Taylor, cette instruction
effectuera la suppression attendue. Si vous avez deux clients qui se
nomment David Taylor, vous devrez ajouter une clause WHERE (telle que
RUE ou TELEPHONE, ou CLIENT_ ID) pour tre bien certain que vous
supprimez le bon client. Sinon, tous les David Taylor de votre table seront
effacs, y compris ceux qui ne sont pas partis Tahiti...
Chapitre 7
Grer lhistorique des donnes
DANS CE CHAPITRE :
Dfinir des priodes.

Suivre la trace ce qui se passe certains instants.

Fournir un historique des modifications apportes aux donnes.

Savoir ce qui sest pass et quand lvnement a t enregistr.

A
vant SQL:2011, le standard SQL de lISO/IEC ne disposait daucun
mcanisme pour grer les donnes qui taient valides un instant donn
mais invalides un autre. Or, toute application qui a besoin de suivre
la trace ltat des donnes a besoin de cette fonctionnalit. Cela signifiait
donc que la charge de conserver une trace de ce qui tait valide un instant
donn retombait sur le programmeur de lapplication plutt que sur la base
de donnes. Autant dire que ctait la porte ouverte des applications
compliques, hors budget, en retard et infestes de bogues.
Une nouvelle syntaxe a t ajoute dans SQL:2011 pour permettre de grer
des donnes temporelles sans avoir intervenir dans le code qui gre les
donnes sans tenir compte de la temporalit. Cest un gros avantage pour
quiconque souhaite quune base de donnes SQL intgre la gestion des
temporalits.
Quest-ce que jentends par donnes temporelles ? LE standard
SQL:2011 de lISO/IEC nutilise pas ce terme, mais il est frquent dans la
communaut des bases de donnes. Dans SQL:2011, une donne temporelle
est une donne laquelle une ou plusieurs priodes de temps sont
associes, durant lesquelles la donne est cense tre valide. Autrement dit,
cela signifie quavec les donnes temporelles, vous pouvez dterminer si
une certaine donne est valide ou non.
Dans ce chapitre, je vous prsente le concept de priode, en le dfinissant
dune manire bien particulire. Vous dcouvrirez ensuite les diffrentes
temporalits et les effets quelles peuvent avoir sur la dfinition de cls
primaires et de contraintes dintgrit rfrentielle. Pour finir, je prsente la
manire dont des donnes trs complexes peuvent tre stockes et traites
dans des tables bitemporelles.

Comprendre les priodes dans


SQL:2011
Quoique les versions du standard SQL antrieures SQL:2011
comportaient les types de donnes TIME, TIMESTAMP, et INTERVAL,
aucun type de donnes ne recouvrait la notion de priode commenant un
certain instant et se terminant un autre. Une nouvelle manire dadresser
ce besoin est de dfinir un type de donnes PERIOD. Toutefois,
SQL:2011 ne procde pas ainsi. Introduire un nouveau type de donnes dans
SQL cette tape tardive de son dveloppement, ctait prendre le risque
de remettre en cause lcosystme qui stait dvelopp autour. Il aurait
fallu des interventions chirurgicales trs lourdes dans tous les produits de
bases de donnes du march pour ajouter un nouveau type de donnes.
En consquence, plutt que dajouter un type de donnes PERIOD,
SQL:2011 rsout le problme en ajoutant des dfinitions de priodes sous
la forme de mtadonnes aux tables. Une dfinition de priode est un
lment nomm dune table, qui identifie une paire de colonnes contenant le
moment initial et le moment final. Les commandes CREATE TABLE et
ALTER TABLE utiliss pour crer et modifier des tables ont t mises
jour pour supporter une nouvelle syntaxe permettant de crer ou dtruire de
telles priodes.
Une priode est dtermine par deux colonnes : une colonne de dbut et une
colonne de fin. Ces colonnes sont conventionnelles, tout comme les
colonnes de nimporte quel type de donnes temporel. Chacune porte un
nom unique. Comme mentionn plus tt, une dfinition de priode est un
lment nomm dune table. Elle se trouve dans le mme espace de noms
que les noms des colonnes, si bien quelle ne doit pas porter le nom dune
colonne.
SQL suit un modle ferm-ouvert pour les priodes, ce qui signifie quune
priode comprend un dbut mais pas de fin. Pour toute ligne de la table, la
fin dune priode doit tre suprieure son dbut. Cest une contrainte dont
le SGBD assure le respect.
Deux dimensions du temps sont prendre en compte lorsque vous
manipulez des donnes temporelles :

Le temps-valide est la priode durant laquelle une ligne


de la table reflte bien la ralit.

Le temps-transaction est la priode durant laquelle la


ligne est enregistre dans la base de donnes.

Le temps-valide et le temps-transaction dune ligne de la table nont pas


besoin dtre identiques. Par exemple, dans une base de donnes qui
enregistre la dure de validit dun contrat, linformation sur le contrat peut
tre insre avant que le contrat ne prenne effet (ce qui se fait dailleurs
gnralement).
Dans SQL:2011, des tables distinctes peuvent tre cres et maintenues
pour les deux types de temporalits, moins dutiliser une table
bitemporelle (il en sera question plus loin dans ce chapitre). Les
informations du temps-transaction sont conserves dans des tables qui
contiennent une priode temps-systme, signale par le mot-cl
SYSTEM_TIME. Quant aux informations du temps-valide, elles sont
maintenues dans des tables qui contiennent une priode de temps-
application. Vous pouvez donner nimporte quel nom une priode de
temps-application, pourvu que le nom ne soit pas dj utilis ailleurs. Vous
avez le droit de dfinir au plus une priode de temps-systme et une priode
de temps-application.
Quoique la gestion des donnes temporelles dans SQL a t introduite pour
la premire fois avec SQL:2011, les gens nont pas attendu quelle soit
intgre aux produits de bases de donnes pour se servir de donnes
temporelles. On utilisait classiquement deux tables, une pour le dbut et une
autre pour la fin de la priode. Le fait que SQL:2011 nintroduise pas de
type de donnes PERIOD, mais plutt des dfinitions de priode sous la
forme de mtadonnes, signifie que les tables utilises jusqualors peuvent
facilement tre rendues compatibles avec le nouveau mcanisme. La logique
qui permet de fournir des informations sur une priode peut tre retire des
applications, ce qui permet de les simplifier, den amliorer les
performances et den renforcer la fiabilit.

Travailler avec des tables de


priodes de temps-application
Prenons un exemple utilisant des tables de priodes de temps-application.
Considrons une entreprise qui veut conserver la trace temporelle des
dpartements par lesquels sont passs les employs durant leur contrat.
Lentreprise peut y parvenir en crant des tables de priodes de temps-
application pour les employs et les dpartements, de la manire suivante :

CREATE TABLE employe_atpt(


EmpID INTEGER,
EmpDebut DATE,
EmpFin DATE,

EmpDept VARCHAR(30),
PERIOD FOR EmpPeriode (EmpDebut, EmpFin)
);

La date et lheure de dbut (EmpDebut dans cet exemple) figurent dans la


priode, mais celles de fin (EmpFin dans cet exemple) ny figurent pas.
Cest cela, la smantique ferm-ouvert.
Je nai pas encore prcis de cl primaire, car cest un peu plus complexe
lorsque vous traitez des donnes classiques. Je vais en parler la fin de ce
chapitre.
Pour lheure, insrez quelques donnes dans la table pour voir quoi cela
ressemble :

INSERT INTO employe_atpt


VALUES (12345, DATE 2011-01-01, DATE 9999-12-
31,
Ventes);
La table qui en rsulte est reprsente dans le tableau 7.1.

TABLEAU 7.1 Une table priode de temps-application ne contenant quune ligne

EmpID EmpDebut EmpFin EmpDpt

12345 2011-01-01 9999-12-31 Ventes

La date de fin 9999-12-31 indique que le contrat de travail de lemploy


dans lentreprise ne sest pas encore termin. Pour plus de simplicit, je
nai pas fait figurer les heures, les minutes et les secondes, et encore moins
les fractions de seconde des exemples.
Supposons maintenant que, le 15 mars 2012, lemploy 12345 est
temporairement affect au dpartement Ingnierie jusquau 15 juillet 2012,
date laquelle il retournera au dpartement Ventes. Vous pouvez le
mentionner en utilisant la commande UPDATE suivante :

UPDATE employe_atpt
FOR PORTION OF EmpPeriode
FROM DATE 2012-03-15
TO DATE 2012-07-15
SET EmpDept = Ingnierie
WHERE EmpID = 12345;

Aprs la mise jour, la table contient trois lignes, comme dans le


tableau 7.2 :

TABLEAU 7.2 La table de priodes de temps-application aprs mise jour.

EmpID EmpDebut EmpFin EmpDpt

12345 2011-01-01 2012-03-15 Ventes

12345 2012-03-15 2012-07-15 Ignierie

12345 2012-07-15 9999-12-31 Ventes


En supposant que lemploy 12345 travaille toujours au dpartement
Ventes, la table rend compte fidlement de son appartenance depuis le jour
de lan 2011 jusqu linstant prsent.
Si vous pouvez insrer de nouvelles donnes dans la table et mettre jour
des donnes qui y figurent, vous devriez pouvoir en supprimer des donnes.
Toutefois, supprimer des donnes dune table de priodes de temps-
application peut savrer un peu plus complexe que supprimer des lignes
dans une table normale, cest--dire non temporelle. Par exemple,
supposons que lemploy 12345, plutt que dtre transfr au dpartement
Ingnierie le 15 mars 2012, quitte lentreprise et soit rembauch
le 15 juillet suivant. la base, la table des priodes de temps-application
ne contiendra quune ligne, comme dans le tableau 7.3.

TABLEAU 7.3 La table de priodes de temps-application avant une mise jour ou une
suppression.

EmpID EmpDebut EmpFin EmpDpt

12345 2011-01-01 9999-12-31 Ventes

Une commande DELETE va mettre jour la table pour indiquer la priode


durant laquelle lemploy 12345 est parti :

DELETE employe_atpt
FOR PORTION OF EmpPeriode
FROM DATE 2012-03-15
TO DATE 2012-07-15
WHERE EmpID = 12345;

La table qui en rsulte est reprise dans le tableau 7.4.

TABLEAU 7.4 La table de priodes de temps-application avant aprs une suppression.

EmpID EmpDebut EmpFin EmpDpt

12345 2011-01-01 2012-03-15 Ventes


12345 2012-07-15 9999-12-31 Ventes

La table reflte mentionne maintenant les priodes durant lesquelles


lemploy 12345 a t effectivement employ par lentreprise, si bien quon
note un vide durant la priode o il lavait quitte.
Vous aurez not quelque chose dintriguant avec les tables prsentes dans
cette section. Dans le listing dune table non temporelle des employs dune
entreprise, le numro didentifiant dun employ suffit pour servir de cl
primaire, car il identifie de manire unique un employ. Toutefois, une table
de priodes de temps-application peut contenir plusieurs lignes pour un
mme employ. En consquence, lidentifiant dun employ ne peut plus
tre utilis comme cl primaire. Les donnes temporelles doivent lui tre
associes.

Concevoir des cls primaires dans


une table de priodes de temps-
application
Dans les tables 7.2 et 7.4, il est clair que lidentifiant de lemploy
(EmpID) ne peut pas garantir lunicit. En effet, on peut trouver plusieurs
lignes avec le mme EmpID. Pour garantir quaucune ligne nest duplique,
le dbut (EmpDebut) et la fin (EmpFin) de la priode doivent figurer
dans la cl primaire. Toutefois, il ne suffit pas de les y inclure. Jetez un il
sur le tableau 7.5, qui prsente un cas o lemploy 12345 a t transfr au
dpartement Ingnierie durant quelques mois, avant de rejoindre son
dpartement dorigine.

TABLEAU 7.5 Une situation que vous souhaiterez viter.

EmpID EmpDebut EmpFin EmpDpt

1245 2011-01-01 9999-12-31 Ventes

1245 2012-03-15 2012-07-15 Ingnierie


Les deux lignes de la table sont garanties dtre uniques du fait que la cl
primaire comprend EmpDebut et EmpFin, mais notez que les deux priodes
se chevauchent. Il semble que lemploy 12345 fasse partie des deux
dpartements Ventes et Ingnierie du 15 mars 2012 au 15 juillet 2012. Dans
quelques entreprises, cela peut tre possible, mais cela ajoute la
complexit et peut corrompre les donnes. Dans la plupart des entreprises,
on veillera au respect dune contrainte imposant quun employ ne puisse
faire partie que dun dpartement la fois. Vous pouvez ajouter une telle
contrainte la table avec une commande ALTER TABLE telle que la
suivante :

ALTER TABLE employe_atpt


ADD PRIMARY KEY (EmpID, EmpPeriode WITHOUT
OVERLAPS);

Il existe une meilleure manire de parvenir au rsultat que de crer la table


avant dy ajouter la contrainte de cl primaire. En effet, vous pouvez inclure
la contrainte de cl primaire dans linstruction CREATE initiale. Cela
pourrait ressembler :

CREATE TABLE employe_atpt


EmpID INTEGER NOT NULL,
EmpDebut DATE NOT NULL,
EmpFin DATE NOT NULL,
EmpDept VARCHAR(30),
PERIOD FOR EmpPeriode (EmpDebut,
EmpFin)
PRIMARY KEY (EmpID, EmpPeriode WITHOUT
OVER-
LAPS)
);

Dornavant, les lignes dont les priodes se chevauchent sont interdites. Tant
que jy tais, jai ajout des contraintes NOT NULL tous les lments de
la cl primaire. Une valeur nulle affecte lun quelconque de ces champs
sera une source derreurs maintenant. Normalement, le SGBD devrait sen
occuper, mais pourquoi prendre le risque ?
Appliquer des contraintes
rfrentielles une table de
priodes de temps-application
Toute base de donnes cense contenir plus quune simple liste va
probablement requrir plus dune table. Si tel est le cas, les relations entre
les tables doivent tre dfinies, et des contraintes dintgrit rfrentielles
mises en place.
Dans lexemple de ce chapitre, vous disposez dune table de priodes de
temps-application. Il existe une relation dun plusieurs entre la table des
dpartements et la table des employs, car un dpartement peut comprendre
plusieurs employs, mais un employ ne peut appartenir qu un seul
dpartement. Cela signifie que vous devez rajouter une cl trangre la
table des employs, qui rfrence la cl primaire de la table des
dpartements. Ceci lesprit, crez de nouveau la table des employs, cette
fois en utilisant une commande CREATE plus complexe. Crez la table des
dpartements de la mme manire.

CREATE TABLE employe_atpt (


EmpID INTEGER NOT NULL,
EmpDebut DATE NOT NULL,
EmpFin DATE NOT NULL,
EmpNom VARACHAR (30),
EmpDept VARCHAR (30),
PERIOD FOR EmpPeriode (EmpDebut, EmpFin)
PRIMARY KEY (EmpID, EmpPeriode WITHOUT OVERLAPS)
FOREIGN KEY (EmpDept, PERIOD EmpPeriode)
REFERENCES dept_atpt (DeptID, PERIOD DeptPeriode)
);

CREATE TABLE dept_atpt (


DeptID VARCHAR (30) NOT NULL,
Manager VARCHAR (40) NOT NULL,
DeptDebut DATE NOT NULL,
DeptFin DATE NOT NULL,
PERIOD FOR DeptDuree (DeptDebut, DeptFin),
PRIMARY KEY (DeptID, DeptDuree WITHOUT OVERLAPS)
);

Faire des requtes sur une table de


priodes de temps-application
Maintenant, des informations dtailles peuvent tre extraites de la base de
donnes en utilisant des commandes SELECT qui exploitent les priodes.
Par exemple, vous pourriez souhaiter rcuprer la liste de tous les employs
qui travaillent actuellement dans lentreprise. Avant SQL:2011, vous deviez
crire une commande ressemblant cela :

SELECT *
FROM employe_atpt
WHERE EmpDebut <= CURRENT_DATE()
AND EmpFin > CURRENT_DATE();

Avec la nouvelle syntaxe, vous pouvez obtenir le mme rsultat plus


facilement, comme suit :

SELECT *
FROM employe_atpt
WHERE EmpPeriode CONTAINS CURRENT_DATE();

Vous pouvez aussi rcuprer la liste des employs qui ont travaill dans
lentreprise sur une priode donne, comme suit :

SELECT *
FROM employe_atpt
WHERE EmpPeriode OVERLAPS
PERIOD (DATE (2012-01-01), DATE (2012-09-
16));
Hormis CONTAINS et OVERLAPS, vous pouvez utiliser dautres
prdicats comme EQUALS, PRECEDES, SUCCEEDS, IMMEDIATLY
PRECEDES, et IMMEDIATLY SUCCEEDS.
Ces prdicats fonctionnent ainsi :
Si une priode EQUALS une autre, alors elles sont
strictement identiques.

Si une priode PRECEEDS une autre, alors elle se droule


avant.

Si une priode SUCCEEDS une autre, alors elle se droule


aprs.

Si une priode IMMEDIATLY PRECEEDS une autre, alors


elle se droule juste avant et y est contige.

Si une priode IMMEDIATLY SUCCEEDS une autre, alors


elle se droule juste aprs et y est contigu.

Travailler avec des tables de


versions systmes
Les tables de versions systmes servent dautres usages que les tables de
priodes de temps-application, et fonctionnent en consquence
diffremment. Les tables de priodes de temps-application vous permettent
de dfinir des priodes et de traiter les donnes associes un instant
donn. Les tables de versions systmes sont conues pour crer un
historique de lajout, de la modification ou de la suppression de donnes de
la base de donnes. Par exemple, il est important pour une banque de savoir
exactement quand un retrait ou un dpt a t effectu, et cette information
doit tre conserve durant un certain temps prvu par la loi. De mme, des
traders ont besoin de conserver la trace de la date de leurs achats et de
leurs ventes. On trouve bien dautres cas citer, o il est important de
conserver la trace dun vnement, la fraction de seconde prs.
Les applications telles que les logiciels de banque ou de trading ont des
exigences strictes :
Toute opration de mise jour ou de suppression doit
sauvegarder ltat original de la ligne avant de le modifier.

Le systme, plutt que les utilisateurs, maintient le dbut


et la fin des priodes dans les lignes.

Les lignes qui ont fait lobjet dune mise jour ou dune
suppression restent dans la table et sont ds lors qualifies
de lignes historiques. Les utilisateurs ne peuvent pas
modifier le contenu de ces lignes ou les priodes qui leur
sont associes. Seul le systme le peut. Il le fait lors dune
mise jour de colonnes qui ne correspondent pas des
priodes dans la table, ou lorsquune ligne est supprime.

Ces contraintes garantissent que lhistorique des donnes


ne peut tre altr, ce qui permet de rpondre aux
exigences des auditeurs et aux rgles des autorits de
rgulation.

Les tables de versions systmes se distinguent des tables de priodes de


temps-application sur plusieurs points dans la commande CREATE qui
permet de crer les unes et les autres :
Alors dans une table de priodes de temps-application,
lutilisateur peut nommer la priode comme il lentend, elle
doit tre toujours nomme SYSTEM_TIME dans une table
de versions systmes.

La commande CREATE doit comprendre les mots-cls


WITH SYSTEM VERSIONING. Quoique SQL:2011 permette
que le type de donnes du dbut et de la fin de la priode
soit du type DATE ou du type TIMESTAMP, vous prfrez
toujours utiliser TIMESTAMP, car cela vous procure bien
plus de prcision que celle du jour. Bien entendu, le type
adopt pour le dbut dune priode doit tre identique
celui de la fin.

Pour illustrer lutilisation des tables de versions systmes, je vais prolonger


lexemple des employs et des dpartements. Vous pouvez crer une table
de versions systmes avec le code suivant :

CREATE TABLE employe_sys (


EmpID INTEGER,
Sys_Debut TIMESTAMP(12) GENERATED ALWAYS AS ROW
START,
Sys_Fin TIMESTAMP(12) GENERATED ALWAYS AS ROW
END,
EmpNom VARCHAR(30),
PERIOD FOR SYSTEM_TIME (SysDebut, SysFin)
) WITH SYSTEM VERSIONING;

Une ligne dans une table de versions systmes est considre tre une ligne
courante du systme si sa priode de temps-systme comprend linstant
prsent. Autrement, elle est considre comme une ligne historique.
Les tables de versions systmes sont trs semblables aux tables de priodes
de temps-application sur de nombreux points, mais elles en diffrent sur
dautres. En particulier :
Les utilisateurs ne peuvent affecter ou modifier les valeurs
des colonnes Sys_Debut et Sys_Fin. Ces valeurs sont
affectes et modifies automatiquement par le SGBD.
Cette situation est impose par les mots-cls GENERATED
ALWAYS.

Lorsque vous utilisez la commande INSERT pour ajouter


quelque chose dans une table de versions systmes, la
valeur de la colonne Sys_Debut prend automatiquement
pour valeur linstant de la transaction. La valeur affecte
la colonne Sys_Fin est la plus grande valeur du type de
donnes de cette colonne.

Dans les tables de versions systmes, les commandes


UPDATE et DELETE agissent sur les lignes courantes. Les
utilisateurs ne peuvent pas modifier ou supprimer des
lignes historiques.

Les utilisateurs ne peuvent pas modifier le dbut ou la fin


de la priode de temps-systme des lignes, quelles soient
courantes ou historiques.

Lorsque vous utilisez une commande UPDATE ou DELETE


sur une ligne courante, une ligne historique est
automatiquement insre.

Une commande de mise jour sur une table de versions


systmes insre dabord une copie de lancienne ligne, la fin
de sa priode de temps-systme devenant linstant de la
transaction. Cela indique que la ligne a cess dtre une
ligne courante. Ensuite le SGBD procde la mise jour,
tout en passant le dbut de la priode de temps-systme
linstant de la transaction. La ligne mise jour est
dornavant une ligne courante. Les dclencheurs UPDATE
des lignes vont tre activs, mais ce ne sera pas le cas des
dclencheurs INSERT quoique des lignes historiques aient
t insres.

Une commande DELETE sur une table de versions systmes ne supprime


pas physiquement les lignes concernes. Elle modifie leur fin de priode de
temps-systme en y affectant linstant courant du systme. Cela indique que
ces lignes ont cess dtre courantes. Elles sont dornavant des lignes
historiques. Lorsque vous effectuez une commande DELETE, les
dclencheurs DELETE des lignes concernes sont activs.

Concevoir des cls primaires pour


une table de versions systmes
Il est bien plus facile de dsigner les cls primaires dans des tables de
versions systmes que dans des tables de priodes de temps-application. En
effet, vous navez pas vous proccuper des priodes. Dans les tables de
versions systmes, les lignes historiques ne peuvent pas tre modifies.
Leur unicit tait vrifie lorsquelles taient des lignes courantes. Mais
comme elles ne peuvent plus tre modifies, il nest plus ncessaire de sen
assurer.
Si vous ajoutez une contrainte de cl primaire une table de versions
systmes laide dune commande ALTER, elle ne sappliquera quaux
lignes courantes, si bien que vous naurez donc pas y faire figurer des
informations relatives aux priodes dans la commande. Par exemple :

ALTER TABLE employe_sys


ADD PRIMARY KEY (EmpID);

Cela fait laffaire. Simple et efficace.

Appliquer des contraintes


dintgrit rfrentielles une
table de versions systmes
Il est tout aussi simple dajouter des contraintes dintgrit rfrentielles
des tables de versions systmes, pour les mmes raisons. Voici un exemple :

ALTER TABLE employe_sys


ADD FOREIGN KEY (EmpDept)
REFERENCES dept_sys (DeptID);
Seules les lignes courantes tant affectes, vous navez pas mentionner les
colonnes de dbut et de fin de priode.

Faire des requtes sur une table de


versions systmes
La plupart des requtes sur des tables de versions systmes cherchent
savoir quelles donnes sont valides un instant donn ou sur une priode
donne. Pour le permettre, SQL:2011 fournit de nouvelles syntaxes. Utilisez
la syntaxe SYSTEM_TIME AS OF pour demander linformation valide
un instant donn. Par exemple, supposons que vous souhaitiez savoir qui a
t employ par lentreprise le 15 juillet 2013. Vous pourriez former la
requte suivante :

SELECT EmpID, EmpNom, Sys_Debut, Sys_Fin


FROM employe_sys FOR SYSTEM_TIME AS OF
TIMESTAMP 2013-07-15 00:00:00;

Cette commande retourne toutes les lignes dont le dbut de priode est gal
ou antrieur linstant spcifi, et dont la fin de priode y est gale ou
postrieure.
Pour savoir ce qui tait valide sur une priode donne, vous pouvez utiliser
une commande similaire, laide de la syntaxe approprie. Voici un
exemple :

SELECT EmpID, EmpNom, Sys_Debut, Sys_Fin


FROM employe_sys FOR SYSTEM_TIME FROM
TIMESTAMP 2013-07-01 00:00:00 TO
TIMESTAMP 2013-08-01 00:00:00;

La requte vous retourne toutes les lignes dbutant au premier instant


indiqu, jusquau second, mais sans linclure. Vous pourriez autrement
utiliser ceci :

SELECT EmpID, EmpNom, Sys_Debut, Sys_Fin


FROM employe_sys FOR SYSTEM_TIME BETWEEN
TIMESTAMP 2013-07-01 00:00:00 AND
TIMESTAMP 2013-07-31 24:59:59;

La requte vous retourne toutes les lignes dbutant au premier instant


indiqu, jusquau second, en lincluant cette fois.
Si une requte sur une table de versions systmes ne spcifie pas dinstant,
son comportement pas dfaut est de vous retourner toutes les lignes
courantes du systme. Le code pourrait ressembler ceci :

SELECT EmpID, EmpNom, Sys_Debut, Sys_Fin


FROM employe_sys;

Si vous souhaitez rcuprer toutes les lignes dune table de versions


systmes, historiques et courantes, vous pouvez le faire en utilisant la
syntaxe suivante :

SELECT EmpID, EmpNom, Sys_Debut, Sys_Fin


FROM employe_sys FOR SYSTEM_TIME FROM
TIMESTAMP 2013-07-01 00:00:00 TO
TIMESTAMP 9999-12-31 24:59:59;

Tracer encore plus les donnes avec


des tables bitemporelles
Parfois, vous souhaitez savoir quand un vnement sest pass dans le
monde rel et quand il a t enregistr dans la base de donnes. Dans ce
cas, vous pourriez utiliser une table qui est la fois une table de versions
systmes et une table de priodes de temps-application. Une telle table est
qualifie de bitemporelle.
Il existe toute une varit de cas o une table bitemporelle peut savrer
utile. Par exemple, supposons que lun de vos employs dmnage et change
alors dtat, passant de lOregon Washington. Vous devez tenir compte du
fait que les charges sur son salaire vont changer la date officielle de son
nouvel tablissement. Toutefois, il nest pas certain que la modification sera
apporte dans la base de donnes ce jour mme. Il faut donc enregistrer les
deux instants, et une table bitemporelle fera cela parfaitement. La table de
priodes de temps-application conserve les priodes auxquelles le
dmnagement a t connu de la base de donnes, et la table de priodes de
temps-application conserve les priodes auxquelles il a pris lgalement
effet. Voici un exemple de cration dune telle table :

CREATE TABLE employe_bt (


EmpID INTEGER,
EmpDebut DATE,
EmpFin DATE,
EmpDept Integer
PERIOD FOR EmpPeriode (EmpDebut, EmpFin),
Sys_Debut TIMESTAMP (12) GENERATED ALWAYS
AS ROW START,
Sys_Fin TIMESTAMP (12) GENERATED ALWAYS
AS ROW END,
EmpNom VARCHAR (30),
EmpRue VARCHAR (40),
EmpVille VARCHAR (30),
EmpEtatProvince VARCHAR (2),
EmpCodePostal VARCHAR (10),
PERIOD FOR SYSTEM_TIME (Sys_Debut, Sys_Fin),

PRIMARY KEY (EmpID, EPeriode WITHOUT OVERLAPS),


FOREIGN KEY (EDept, PERIOD EPeriode)
REFERENCES Dept (DeptID, PERIOD DPeriode)
) WITH SYSTEM VERSIONING;

Les tables bitemporelles servent la fois de tables de versions systmes et


de tables de priodes de temps-application. Lutilisateur fournit des valeurs
pour les colonnes de dbut et de fin de priode. Une commande INSERT
dans une telle table passe automatiquement la priode de temps-systme la
date et lheure de la transaction. La valeur de la colonne de fin de la
priode de temps-systme prend automatiquement la plus grande valeur
possible pour son type de donnes.
Les commandes UPDATE et DELETE fonctionnent comme si la table tait
une table de priodes de temps-application. De mme que dans le cas dune
table de versions systmes, ces commandes naffectent que les lignes
courantes, une ligne historique tant automatiquement insre chaque fois.
Une requte sur une table bitemporelle peut spcifier une priode de temps-
systme, une priode de temps-application, voire les deux. Voici un
exemple dutilisation simultane :

SELECT EmpID
FROM employe_bt FOR SYSTEM TIME AS OF
TIMESTAMP 2013-07-15 00:00:00
WHERE EmpID = 314159 AND
EmpPeriode CONTAINS DATE 2013-06-20
00:00:00;
Chapitre 8
Spcifier des valeurs
DANS CE CHAPITRE :
Utiliser des variables pour liminer du code redondant.

Extraire une information frquemment utilise dun champ dune table.

Combiner des valeurs lmentaires pour former des expressions complexes

J
insiste tout au long de ce livre sur limportance du rle de la structure
dune base de donnes dans le maintien de lintgrit de cette dernire.
Cependant, vous ne devez jamais oublier que la chose la plus importante
est la donne elle-mme. En effet, les valeurs que contiennent les cellules
qui forment les intersections des lignes et des colonnes de la base de
donnes sont la matire sur laquelle vous travaillez.
Vous pouvez reprsenter les valeurs de diverses manires. Vous pouvez les
reprsenter directement ou les driver de fonctions et dexpressions. Ce
chapitre dcrit les diverses formes de valeurs ainsi que les fonctions et les
expressions.
Les fonctions examinent des donnes et calculent une valeur en fonction de
ces dernires. Les expressions sont des combinaisons de donnes que SQL
value pour produire une seule valeur.

Valeurs
SQL reconnat diffrents types de valeurs :
Les valeurs de lignes.

Les valeurs littrales.


Les variables.

Les variables spciales.

Les rfrences des colonnes.

LES ATOMES NE SONT PAS INDIVISIBLES NON PLUS

Au XIXe sicle, les scientifiques croyaient quun atome tait le plus


petit composant irrductible de la matire. Cest pourquoi ils
lappelrent atome, qui vient du mot grec atomos qui veut dire
indivisible. Aujourdhui, les scientifiques savent que les atomes ne
sont pas indivisibles. Ils sont forms de protons, de neutrons et
dlectrons. leur tour, les protons et les neutrons sont faits de
quarks, de gluons et de quarks virtuels. Et peut-tre bien que ces
choses elles-mmes ne sont pas indivisibles. Qui sait ?

La valeur dun champ dune table est qualifie datomique, mme si de


nombreux champs ne sont pas indivisibles. Une valeur DATE est
compose dun mois, dune anne et dun jour. Une valeur TIMESTAMP
est compose dune heure, de minutes, de secondes, et ainsi de suite.
Une valeur REAL ou FLOAT est constitue dun exposant et dune
mantisse. Une valeur CHAR est forme de composants auxquels vous
pouvez accder en utilisant SUBSTRING. Par consquent, qualifier les
champs dune base de donnes datomiques est un abus de langage si
lon se reporte la dfinition du terme, savoir : le plus petit morceau
de matire inscable.

Les valeurs de lignes


Les valeurs les plus visibles dans une base sont les valeurs de lignes des
tables. Ce sont les donnes que chaque ligne dune table contient. Une ligne
est gnralement compose de plusieurs lments, car chaque colonne de la
ligne contient une valeur. Un champ est lintersection dune seule colonne et
dune seule ligne. Un champ contient une valeur scalaire (ou atomique).
Une valeur scalaire ou atomique nest compose que delle-mme.

Les valeurs littrales


En SQL, une valeur est reprsente par une variable ou une constante.
Contrairement la valeur dune constante (qui ne change jamais), la valeur
dune variable peut varier avec le temps. Comme quoi la logique du
langage est parfois imparable.
Un type important de constante est la valeur littrale. Vous pouvez la
considrer comme une valeur WYSIWYG, car What You See Is What You
Get (ce que vous voyez correspond exactement ce que vous obtenez).
Autrement dit, la reprsentation est la valeur elle-mme.
SQL dispose de nombreux types de donnes et donc de nombreux types de
littraux. Le Tableau 8.1 prsente quelques exemples de littraux de
diffrents types.

TABLEAU 8.1 Des littraux de diffrents types.

Type de donnes Exemple de valeur littrale

BIGINT 8589934592

INTEGER 186282

SMALLINT 186

NUMERIC 186282.42

DECIMAL 186282.42

REAL 6.02257E-23

DOUBLE PRECISION 3.1415926535897E00


FLOAT 6.02257E-23

CHARACTER (15) GRECE

Note : Contient quinze


caractres au total dont des
espaces.

VARCHAR (CHARACTER grecque


VARYING

NATIONAL CHARACTER (15) ELLAS 1

Note : Contient quinze


caractres au total dont des
espaces.

NATIONAL CHARACTER lepton2


VARYING

CHARACTER LARGE OBJECT (une chane de caractres


(CLOB) rellement trs longue)

BINARY(4) 010011000111000011110001110010
10

VARBINARY(4) (BINARY 0100110001110000


VARYING(4))

BINARY LARGE OBJECT(512) (une chane de uns et de zros


(BLOB(512)) rellement trs longue)

DATE DATE 1969-07-20

TIME (2) TIME 13.41.32.50

TIMESTAMP (0)
TIMESTAMP 1998-05-17-
13.03.16.000000

TIME WITH TIMEZONE (4) TIME 13.41.32.5000-08.00

TIMESTAMP WITH TIMEZONE (0) TIMESTAMP 1998-05-17-


13.03.16.0000+02.00

INTERVAL DAY INTERVAL 7 DAY

Remarquez que les littraux de type non numrique sont entours


dapostrophes. Ces dlimiteurs permettent dviter toute confusion, mais
posent parfois des problmes.
Que se passe-t-il si une chane de caractres contient elle-mme une
apostrophe ? Vous devez alors doubler cette apostrophe pour montrer que
lun des deux signes fait partie de la chane et nen marque donc pas la fin.
Pour dire par exemple Lvaporation de leau, il vous faut
crire Lvaporation de leau .

Les variables
Les littraux et autres types de constantes sont fort utiles, mais ils ne
remplacent pas les variables. Dans bien des cas, se passer des variables
revient simposer une importante, et inutile, surcharge de travail. Une
variable dsigne tout simplement une quantit dont la valeur peut changer.
Lexemple suivant devrait vous en dmontrer lutilit.
Supposons que vous soyez le distributeur dun produit vendu plusieurs
classes de clients. Vous accordez le meilleur prix aux clients qui achtent
des volumes importants, un prix un peu moins bon ceux qui achtent des
quantits moyennes, les personnes qui nachtent quen faible quantit
payant videmment plein tarif. Vous voulez donc indexer vos prix sur les
quantits achetes. Pour votre produit F-117A, vous dcidez de
facturer 1,4 fois le prix dachat aux gros clients (classe C). Vous
facturez 1,5 fois ce prix aux moyens acheteurs (classe B). Enfin, vous
facturez 1,6 fois vos cots aux petits clients (classe A).
Vous stockez les prix dachat de vos produits et les tarifs auxquels vous les
revendez dans une table que vous nommez TARIFS. Pour mettre en place
votre nouvelle structure de prix, vous allez excuter les commandes SQL
suivantes :

UPDATE TARIFS
SET PRIX = COUT * 1.4
WHERE PRODUIT = F-117A
AND CLASSE = C ;
UPDATE TARIFS
SET PRIX = COUT * 1.5
WHERE PRODUIT = F-117A
AND CLASSE = B ;
UPDATE TARIFS
SET PRIX = COUT * 1.6
WHERE PRODUIT = F-117A
AND CLASSE = A ;

Ce code rpond exactement vos besoins. Mais que se passe-t-il si un


comptiteur agressif veut manger vos parts de march ? Vous allez devoir
rduire vos marges. Il vous faut alors saisir une commande telle que celle-
ci :

UPDATE TARIFS
SET PRIX = COUT * 1.25
WHERE PRODUIT = F-117A
AND CLASSE = C ;
UPDATE TARIFS
SET PRIX = COUT * 1.35
WHERE PRODUIT = F-117A
AND CLASSE = B ;
UPDATE TARIFS
SET PRIX = COUT * 1.45
WHERE PRODUIT = F-117A
AND CLASSE = A ;

Si votre march est trs volatile, vous devrez souvent rcrire votre code
SQL. Cela peut devenir rapidement fastidieux, en particulier si les prix
figurent plusieurs endroits dans votre code. Pour rsoudre ce problme, il
suffit de remplacer les littraux (tels que 1,45) par des variables (telles
que coefficientA). Vous pourriez alors procder vos mises jour de
la manire suivante :

UPDATE TARIFS
SET PRIX = COST * :coefficientC
WHERE PRODUIT = F-117A
AND CLASSE = C ;
UPDATE TARIFS
SET PRIX = COST * :coefficientB
WHERE PRODUIT = F-117A
AND CLASSE = B ;
UPDATE TARIFS
SET PRIX = COST * :coefficientA
WHERE PRODUIT = F-117A
AND CLASSE = A ;

Dornavant, chaque fois que les conditions du march vous contraindront


modifier vos prix, vous naurez qu modifier les valeurs des variables
coefficientA, coefficientB et coefficientC.
Vous verrez que les variables que vous utilisez de cette manire sont parfois
nommes paramtres ou encore variables htes. Les variables sont
appeles paramtres si elles figurent dans un module de code crit en SQL,
et variables htes si elles figurent dans du code SQL intgr.
Le SQL intgr correspond aux instructions SQL qui sont intgres dans le
code dune application crite dans un langage hte. Une autre solution
consiste utiliser un module de langage SQL pour crire tout un module de
code SQL que lapplication appellera. Le choix entre lune et lautre de ces
mthodes dpend de votre implmentation.

Variables spciales
Si lutilisateur dune machine client se connecte une base de donnes
hberge par un serveur, cette connexion est nomme session. Si
lutilisateur se connecte plusieurs bases de donnes, la session associe
la connexion la plus rcente est considre comme tant la session
courante. Les sessions prcdentes sont dites dormantes. SQL dfinit
plusieurs variables spciales qui se rvlent fort utiles sur un systme
multiutilisateur. Elles conservent en effet la trace des diffrents utilisateurs.
Voyons cela de plus prs :
SESSION_USER : La variable spciale SESSION_USER
contient une valeur gale lidentifiant de lutilisateur de la
session SQL courante. Si vous crivez un programme qui
supervise la base de donnes, vous pouvez interroger
SESSION_USER pour savoir qui est en train dexcuter des
instructions SQL.

CURRENT_USER : Un module SQL peut disposer dun


identificateur dautorisation pour un utilisateur donn.
Cette valeur est stocke dans CURRENT_USER. Si le
module na pas didentifiant de ce type, la valeur de
CURRENT_USER est celle de SESSION_USER.

SYSTEM_USER : La variable SYSTEM_USER contient


lidentifiant dun utilisateur du systme dexploitation. Cet
identifiant est ventuellement diffrent de celui qui Figure
dans un module SQL. Un utilisateur peut se connecter au
systme sous le nom de LARRY, mais dclarer sappeler
RESPONSABLE dans un module. La valeur de
SESSION_USER est alors RESPONSABLE. Si lutilisateur ne
fait aucune rfrence explicite lidentificateur du module,
et si CURRENT_USER contient aussi RESPONSABLE, alors la
valeur de SYSTEM_USER est LARRY.

Les variables SESSION_USER, SYSTEM_USER et CURRENT_USER


servent suivre la trace les accs au systme. Vous pouvez tenir un
journal de bord en stockant priodiquement les valeurs de ces variables
dans une table. Par exemple :

INSERT INTO LOGUTIL (SNAPSHOT)


VALUES (Utilisateur || SYSTEM_USER ||
avec ID || SESSION_USER ||
activ || CURRENT_TIMESTAMP) ;

Cette instruction produit lentre suivante :

Utilisateur LARRY avec ID RESPONSABLE activ


2006-05-
17-14.18.00

Rfrences de colonnes
Les colonnes contiennent une valeur pour chaque ligne dune table. Les
instructions SQL se rfrent souvent ces valeurs. Une rfrence complte
une colonne se compose du nom de la table, dun point et du nom de la
colonne (comme dans TARIFS. PRODUIT). Regardez lexemple
suivant :

SELECT TARIFS.COUT
FROM TARIFS
WHERE TARIFS.PRODUIT = F-117A ;

TARIFS. PRODUIT est une rfrence de colonne. Elle contient la valeur


F117-A. TARIFS. COUT est aussi une rfrence de colonne, mais
vous ne connatrez sa valeur que lorsque linstruction SELECT aura t
excute.
Seule la rfrence des colonnes qui se trouvent dans la table courante a
vritablement un sens. Vous pouvez donc gnralement omettre de
mentionner le nom de cette table. Ainsi, linstruction suivante quivaut la
prcdente :

SELECT COUT
FROM TARIFS
WHERE PRODUIT = F-117A ;

Il peut cependant arriver que vous ayez manipuler plusieurs tables. Il


arrive que deux tables de la base de donnes contiennent des colonnes
portant le mme nom. Si tel est le cas, vous devez utiliser des noms de
colonnes totalement qualifis pour les discriminer.
Par exemple, supposons que votre socit dispose de bureaux Kingston et
Jefferson et que vous griez une liste des employs pour chaque site. Vous
nommez EMP_KINGSTON la table des employs de Kingston et
EMP_JEFFERSON celle des employs de Jefferson. Vous voulez
rcuprer la liste des personnels dont les noms apparaissent dans ces deux
tables. Linstruction SELECT suivante vous donne le rsultat voulu :

SELECT EMP_KINGSTON.NOM, EMP_ KINGSTON.PRENOM


FROM EMP_ KINGSTON, EMP_JEFFERSON
WHERE EMP_ KINGSTON.EMP_ID =
EMP_JEFFERSON.EMP_ID ;

Puisque lidentifiant dun employ est unique quel que soit le site o il
travaille, vous pouvez utiliser cette cl comme lien entre les deux tables. La
requte ne retourne que les noms des employs qui margent aussi bien
Kingston qu Jefferson.

Les expressions de valeur


Une expression est simple ou complexe. Elle peut contenir des valeurs
littrales, des noms de colonnes, des paramtres, des variables htes, des
sous-requtes, des connecteurs logiques et des oprateurs arithmtiques.
Mais quel que soit son degr de complexit, une expression doit pouvoir se
rduire une seule valeur.
Cest pourquoi les expressions SQL sont aussi nommes expressions de
valeur. Il est possible de combiner plusieurs expressions de valeur pour
nen former quune seule, du moment quelles se rduisent des valeurs
dont les types sont compatibles.
SQL dispose de cinq expressions de valeur :
Lexpression de valeur chane.
Lexpression de valeur numrique.

Lexpression de valeur date/heure.

Lexpression de valeur intervalle.

Lexpression de valeur conditionnelle.

Les expressions de valeur chane


La plus simple des expressions de valeur chane est une chane de
caractres. Mais cette expression peut aussi tre la rfrence une colonne,
une fonction densemble, une sous-requte scalaire, une expression CASE,
une expression CAST ou une expression de valeur chane complexe. Je
traite des expressions CAST et CASE au Chapitre 9 et des sous-requtes
au Chapitre 12.
Un seul oprateur est disponible pour les expressions de valeur de chane :
la concatnation. Vous pouvez concatner nimporte laquelle des
expressions mentionnes au dbut de cette section pour crer une expression
de chane plus complexe. Une paire de lignes verticales (||) reprsente
cet oprateur de concatnation. Le tableau suivant propose quelques
exemples dexpression de valeur de chane :

Cette expression Produit


Beurre || sal Beurre sal
Haricots || || verts Haricots verts
PRENOM || || NOM Andr Dupont
B1100111 || B01010011
B110011101010011
|| Machin Machin
Machin || Machin
Ma || || ch || || in Machin

Comme vous pouvez le constater, si vous concatnez une chane une autre
de longueur nulle, le rsultat est identique la chane dorigine.
Les expressions de valeur
numrique
Les expressions de valeur numrique vous permettent dappliquer les
oprateurs daddition, de soustraction, de multiplication et de division des
types de donnes numriques. Lexpression doit pouvoir se rduire une
valeur numrique. Les lments qui la composent peuvent tre de diffrents
types, mais tous doivent tre numriques. La nature du rsultat dpend des
types de donnes des lments qui constituent lexpression. Le standard
SQL ne spcifie pas strictement le type produit par une combinaison de
valeurs numriques. Tout dpend de votre plate-forme. Consultez la
documentation fournie avec celle-ci pour en apprendre plus sur cette
question.
Voici quelques exemples dexpressions de valeur numrique :
27

49 + 83

5 * (12 3)

PROTEINE + GRAISSE + HYDRATECARBONE

LONGUEUR/5280

COUT * : coefficientA

Les expressions de valeur


date/heure
Les expressions de valeur date/heure permettent deffectuer des oprations
sur des dates et des heures. Ces expressions peuvent tre composes
dlments de types DATE, TIME, TIMESTAMP ou INTERVAL. Le
rsultat dune expression de valeur date/heure est toujours de type
date/heure (DATE, TIME ou TIMESTAMP). Par exemple, lexpression
suivante donne la date quil sera dans une semaine :
CURRENT_DATE + INTERVAL 7 DAY

Les heures sont au format UTC (Universal Time Coordinated), cest--dire


quelles sont exprimes relativement au mridien de Greenwich. Mais vous
pouvez aussi spcifier un dcalage afin de vous ajuster un fuseau horaire
de votre choix. La syntaxe qui suit exprime lheure locale de votre systme :

TIME 22.55.00 AT LOCAL

Jetez un coup dil sur cette autre syntaxe, plus longue :

TIME 22.55.00 AT TIME ZONE INTERVAL -08.00


HOUR TO
MINUTE

Cette expression dfinit lheure comme tant celle de Portland dans


lOregon, qui est infrieure de 8 heures celle du mridien de Greenwich.

Les expressions de valeur


intervalle
Si vous faites la diffrence entre deux valeurs de type date/ heure, vous
obtenez un intervalle. Notez bien que SQL ne vous permet pas dajouter
deux valeurs de type date/heure (cela naurait pas de sens). Si vous ajoutez
ou soustrayez deux intervalles, vous obtenez un nouvel intervalle. Il est
aussi possible de multiplier ou diviser des intervalles entre eux.
Souvenez-vous que SQL dispose de deux types dintervalles : anne-mois
et jour-heure. Pour lever toute ambigut, vous devez spcifier quel type
vous utilisez dans une expression. Par exemple, lexpression suivante utilise
un intervalle anne-mois pour calculer lge thorique de votre retraite :

(ANNIVERSAIRE_60 DATE_COURANTE) YEAR TO MONTH

Lexemple ci-dessous produit un intervalle de 40 jours :

INTERVAL 17 DAY + INTERVAL 23 DAY


Lexemple qui suit fournit une approximation du nombre de mois durant
lesquels une mre de cinq enfants est reste enceinte :

INTERVAL 9 MONTH * 5

Les intervalles peuvent tre ngatifs aussi bien que positifs. Ils peuvent
galement consister en des expressions de valeur ou des combinaisons
dexpressions de valeurs qui se rduisent des intervalles.

Les expressions de valeur


conditionnelle
Comme son nom lindique, la valeur dune expression de valeur
conditionnelle dpend dune condition. Les expressions de valeur
conditionnelle CASE, NULLIF et COALESCE sont bien plus complexes
que les autres types dexpressions. En fait, elles sont si complexes que je
nai pas assez de place pour en parler ici. Je les traite en dtail au
Chapitre 9.

Les fonctions
Une fonction est une opration simple ou modrment complexe que les
commandes usuelles de SQL ne savent pas effectuer, mais qui peut se
rvler fort utile. SQL fournit des fonctions qui effectuent des tches que le
code de lapplication crite dans le langage hte (celui dans lequel vos
instructions SQL sont incorpores) devrait autrement effectuer. SQL dispose
de deux catgories principales de fonctions : les fonctions densemble et
les fonctions de valeurs.

Utiliser les fonctions densemble


Les fonctions densemble sappliquent des ensembles de lignes plutt
qu une ligne unique. Elles renvoient telle ou telle caractristique du jeu de
lignes courant. Un tel ensemble peut contenir des lignes de la table, ou
encore des parties de lignes isoles par une clause WHERE (je traite en
dtail de la clause WHERE au Chapitre 10). Les programmeurs appellent
quelquefois les fonctions densemble fonctions dagrgat, car ces fonctions
extraient des informations de plusieurs lignes, les traitent dune quelconque
manire et retournent une seule information. Cette rponse est le fruit de
lagrgation des donnes que contiennent les lignes.
Pour illustrer lutilisation des fonctions densemble, observez le
Tableau 8.2. Il sagit dun tableau nutritionnel, les valeurs tant fournies
pour 100 grammes daliments.
Une table nomme ALIMENTS contient les informations prsentes dans le
Tableau 8.2. Les champs vides contiennent la valeur NULL. Les fonctions
densemble COUNT, AVG, MAX, MIN et SUM vont vous fournir des
informations intressantes sur cette table.

COUNT
La fonction COUNT vous indique combien de lignes comporte la table, ou
combien de lignes de la table rpondent certains critres. Lutilisation la
plus triviale de la fonction est la suivante :

TABLEAU 8.2 Valeurs nutritives pour 100 g daliments.

Aliment Calories Protines Graisse Hydrate


(g) (g) carbon (g)

Amandes grilles 627 18,6 57,7 19,6

Asperge 20 2,2 0,2 3,6

Banane crue 85 1,1 0,2 22,2

Boeuf, hamburger 219 27,4 11,3


maigre

Poulet, plat allg 166 31,6 3,4

Opossum, rti 221 30,2 10,2

Porc, jambon 394 21,9 33,3


Haricots 111 7,6 0,5 19,8

Soda 39 10,0

Pain, blanc 269 8,7 3,2 50,4

Pain, bl entier 243 10,5 3,0 47,7

Brocolis 26 3,1 0,3 4,5

Beurre 716 0,6 81,0 0,4

Bonbons 367 0,5 93,1

Huile darachide 421 5,7 10,4 81,0

SELECT COUNT (*)


FROM ALIMENTS ;

Cette instruction vous retourne comme valeur 15, car elle dnombre toutes
les lignes de la table ALIMENTS. Lexemple suivant produit le mme
rsultat :

SELECT COUNT (CALORIES)


FROM ALIMENTS ;

Comme chaque ligne de la table comporte une entre dans la colonne


CALORIES, la fonction retourne nouveau 15. Mais si la colonne avait
contenu des valeurs nulles, la fonction ne les aurait pas prises en compte.
Linstruction suivante retourne une valeur de 11, car 4 des 15 lignes de la
table contiennent une valeur non dfinie dans la colonne
HYDRATECARBONE :

SELECT COUNT (HYDRATECARBONE)


FROM ALIMENTS ;

Un champ dune table peut contenir une valeur nulle pour diverses raisons.
Le plus souvent, cette valeur nest pas encore connue. moins quelle nait
pas encore t saisie. Si la valeur vaut zro, il arrive que loprateur charg
de la saisie ne renseigne pas le champ. Ce nest pas une bonne habitude, car
le zro est une valeur bien dfinie, que vous pouvez utiliser dans vos
calculs. La valeur nulle nest pas dfinie, si bien que SQL nen fait rien. Les
phrases Le soda ne contient pas de graisse et Je ne sais pas combien
de graisse contient le soda ne sont pas du tout quivalentes !
Vous pouvez aussi utiliser la fonction COUNT en combinaison avec la
clause DISTINCT pour dterminer combien de valeurs distinctes existent
dans une colonne. Par exemple :

SELECT COUNT (DISTINCT GRAISSE)


FROM ALIMENTS ;

La rponse que retourne cette instruction est 12. Vous pouvez voir que 100 g
dasperges contiennent autant de graisse que100 g de bananes (0,2 g), et
que 100 g de haricots contiennent autant de graisse que 100 g de bonbons
sucrs (0,5 g). La table ne contient donc que 12 valeurs distinctes de
graisse.

AVG
La fonction calcule et retourne la moyenne des valeurs de la colonne
spcifie. Bien entendu, vous ne pouvez utiliser la fonction AVG que sur
des colonnes qui contiennent des valeurs numriques, comme par exemple
dans :

SELECT AVG (GRAISSE)


FROM ALIMENTS ;

Le rsultat est 15,37. Ce nombre est grand cause de la prsence du beurre


dans la table. Vous vous demandez peut-tre quelle valeur produirait
linstruction si vous ne teniez pas compte de cet aliment. Pour le savoir,
utilisez une clause WHERE de la manire suivante :

SELECT AVG (GRAISSE)


FROM ALIMENTS
WHERE ALIMENT <> Beurre ;
La valeur moyenne tombe 10,32 g pour 100 g daliment.

MAX
La fonction MAX vous retourne la valeur maximale trouve dans la colonne
spcifie. Linstruction suivante renvoie 81 (la teneur en graisse de 100 g de
beurre) :

SELECT MAX (GRAISSE)


FROM ALIMENTS ;

MIN
La fonction MIN vous retourne la valeur minimale qui se trouve dans une
colonne. Linstruction suivante renvoie 0,4, car la fonction ne traite pas les
valeurs nulles comme des zros :

SELECT MIN (CARBOHYDRATE)


FROM ALIMENTS ;

SUM
La fonction SUM vous retourne la somme de toutes les valeurs dune
colonne. Linstruction suivante renvoie 3 924, ce qui correspond au total
des calories des 15 aliments :

SELECT SUM (CALORIES)


FROM ALIMENTS ;

Les fonctions de valeurs


Beaucoup doprations peuvent tre appliques dans des contextes
diffrents. Comme vous avez besoin dutiliser frquemment ces oprations,
vous pouvez les incorporer dans du code SQL sous la forme de fonctions de
valeurs. SQL ne dispose que de peu de fonctions de valeurs si on le
compare des SGBD tels quAccess ou FoxPro, mais ce sont probablement
les seules dont vous vous servirez rgulirement. SQL utilise les trois types
de fonctions de valeurs suivants :
Les fonctions de valeur chane.

Les fonctions de valeur numrique.

Les fonctions de valeur date/heure.

Les fonctions de valeur intervalle

Les fonctions de valeur chane


Les fonctions de valeur chane reoivent une chane de caractres en entre
et produisent une autre chane de caractres en sortie. SQL dispose de six
fonctions de ce type :
SUBSTRING

SUBSTRING SIMILAR

SUBSTRING_REGEX

TRANSLSATE_REGEX

OVERLAY

UPPER

LOWER

TRIM

TRANSLATE

CONVERT

SUBSTRING
Utilisez la fonction SUBSTRING pour extraire une partie dune chane
source. La chane extraite est du mme type que la chane source. Par
exemple, si la chane source est du type CHARACTER VARYING, il en ira
de mme pour la sous-chane.
La syntaxe de SUBSTRING est la suivante :

SUBSTRING (valeur_chane FROM dbut [FOR


longueur])

La clause qui Figure entre crochets ([]) est optionnelle. La chane extraite
de valeur_chane commence au caractre repr par dbut et se
prolonge sur longueur caractres. Si la clause FOR nest pas mentionne,
lextraction se poursuit jusqu la fin de la chane source. Par exemple :

SUBSTRING (Pain, bl entier FROM 7 FOR 6)

La chane extraite est bl en. Elle commence au septime caractre et


prend six caractres. SUBSTRING ne semble pas a priori tre une fonction
trs intressante. Si jai une valeur littrale Pain, bl entier, je nai pas
besoin dune fonction pour savoir quoi correspondent les six caractres
partir du septime. Cependant, SUBSTRING est une fonction trs utile, car
la valeur quelle manipule na pas besoin dtre un littral. Il peut sagir de
nimporte quelle expression qui correspond une chane. Ainsi, il est
parfaitement possible dutiliser une variable qui se nomme
objetaliment et qui prend des valeurs diffrentes selon le contexte.
Lexpression suivante permettrait dextraire une chane
dobjetaliment, et ce quelle que soit la valeur chane courante
reprsente par cette variable :

SUBSTRING (:objetaliment FROM 7 FOR 6)

Toutes les fonctions de valeur se ressemblent, en ce sens quelles peuvent


manipuler des expressions ou des valeurs littrales.
Vous devez faire attention quelques petites choses quand vous utilisez la
fonction SUBSTRING. Vrifiez que la sous-chane que vous dcrivez est
bien incluse dans la chane source. Si vous demandez une extraction partir
du septime caractre, mais que la chane source nen comporte que quatre,
la fonction vous retournera une valeur nulle. Par consquent, vous devez
toujours avoir une ide relativement prcise de la forme de vos donnes
avant dappliquer SUBSTRING. Ne spcifiez pas non plus de valeurs
ngatives, car la fin dune chane ne peut prcder son dbut.
Si une colonne est de type VARCHAR, vous ne savez pas a priori quelle est
sa longueur pour une ligne donne. Mais labsence de cette information ne
pose pas de problme la fonction SUBSTRING. Si la longueur que vous
spcifiez est trop importante, SUBSTRING vous renverra tout ce quelle a
pu trouver. Elle ne retournera pas une erreur.
Par exemple, supposons que vous utilisiez linstruction :

SELECT * FROM ALIMENTS


WHERE SUBSTRING (ALIMENT FROM 7 FOR 12) =
bl ;

Cette instruction retourne la ligne qui correspond dans la table ALIMENTS


au pain au bl entier, alors mme que la colonne ALIMENT contient une
valeur dont la longueur est infrieure 18 caractres (pain, bl).
Si un oprande (une valeur partir de laquelle un oprateur drive une
autre valeur) de SUBSTRING contient une valeur nulle, la fonction
retournera une valeur nulle.

SUBSTRING SIMILAR
Cette fonction est triadique (cela signifie quelle opre sur trois
paramtres). Ces trois paramtres sont une chane de caractre source, une
chane de motif (string pattern) et un caractre dchappement. Elle utilise
ensuite les motifs correspondants (en fonction des expressions rgulires
bases sur POSIX) pour extraire et retourner une chane rsultat dans la
chane de caractre source.
Deux instances du caractre dchappement, chacune suivie dun guillemet,
servent dcomposer la chane de motif en trois parties. En voici un
exemple :
Supposez que la chane de caractre source S soit : Il y a quatre-vingt-sept
ans, nos pres ont fond sur ce continent une nouvelle nation. Supposez
ensuite que la chane de motif R soit quatre /sept/annes, o la barre
oblique est le caractre dchappement.
Alors

SUBSTRING S SIMILAR TO R ;

retourne un rsultat qui correspond au milieu de la chane de motif sept


dans notre exemple.

SUBSTRING_REGEX
SUBSTRING_REGEX recherche une chane de motif dexpression
rgulire XQuery et retourne une occurrence de la sous-chane
correspondante.
Conformment au standard international ISO/IEC JTC 1/SC 32, la syntaxe
de lexpression rgulire dune sous-chane est la suivante :

SUBSTRING_REGEX <left paren>


<XQuery pattern> [ FLAG <XQuery option flag>
]
IN <regex subject string>
[ FROM <start position> ]
[ USING <char length units> ]
[ OCCURRENCE <regex occurrence> ]
{ GROUP <regex capture group> ] <right paren>

<XQuery pattern> est lexpression de chane de caractre dont la


valeur est une expression rgulire XQuery.
<XQuery option flag> est une chane de caractre optionnelle
correspondant largument $flags de la fonction [XQuery F & O]
fn : match.
<regex subject string> est la chane de caractre recherche qui
devrait correspondre au <Xquery pattern>.
<start position> est une valeur numrique exacte optionnelle
lchelle 0 qui indique la position du caractre o doit commencer la
recherche (sa valeur par dfaut est 1).
<char length units> est CHARACTERS ou OCTETS, indiquant
lunit dans laquelle <start position> est mesure. (Sa valeur par
dfaut est CHARACTERS).
<regex occurrence> est une valeur numrique exacte optionnelle
lchelle 0, qui indique quelle occurrence dune correspondance est
demande (Sa valeur par dfaut est 1).

<regex capture group> est une valeur numrique exacte


optionnelle lchelle 0 qui indique le groupe de capture dune
correspondance souhaite. (Sa valeur par dfaut est 0, ce qui indique
loccurrence entire).
Voici quelques exemples dutilisation de SUBSTRING_REGEX :

SUBSTRING_REGEX (\p{L}* IN Just do


it.)=Just
SUBSTRING_REGEX (\p{L}* IN Just do it. FROM
2)= ust
SUBSTRING_REGEX (\p{L}* IN Just do it.
OCCURRENCE 2)
= do
SUBSTRING_REGEX ( (do) (\p{L}* IN Just do it.
GROUP
2) = it

TRANSLATE_REGEX
TRANSLATE_REGEX recherche une chane de motif dexpression
rgulire XQuery et retourne la chane avec lune ou toutes les occurrences
de lexpression rgulire XQuery remplace par une chane de
remplacement XQuery.
Conformment au standard international ISO/IEC JTC 1/SC 32, la syntaxe
dune translitration regex est la suivante :

TRANSLATE_REGEX <left paren>


<XQuery pattern> [ FLAG <XQuery option flag> ]
IN <regex subject string>
[ WITH <regex replacement string> ]
[ FROM <start position> ]
[ USING <char length units> ]
[ OCCURRENCE <regex transliteration occurrence> ]
<right
paren>

<regex transliteration occurrence> : :=


<regex occurrence>
| ALL

O :
<regex replacement string> est une chane de
caractre dont la valeur convient lutilisation de
largument $replacement de la fonction [XQuery
F & O] fn : replace. Sa valeur par dfaut est la chane
zro de longueur.

<regex transliteration occurrence> est soit le mot


cl ALL soit une valeur numrique exacte lchelle 0,
indiquant quelle occurrence de la correspondance
recherche (par dfaut ALL).

Voici quelques exemples avec une chane sans remplacement :

TRANSLATE_REGEX (i IN Bill did sit.) = Bll


dd st.
TRANSLATE_REGEX (i IN Bill did sit.
OCCURRENCE ALL) =
Bll dd st.
TRANSLATE_REGEX (i IN Bill did sit. FROM 5) =
Bill
dd st.
TRANSLATE_REGEX (i IN Bill did sit.
Occurrence 2) =
Bill dd sit.

Voici quelques exemples avec une chane de remplacement :

TRANSLATE_REGEX (i IN Bill did sit. WITH a)


= Ball
dad sat.
TRANSLATE_REGEX (i IN Bill did sit. WITH a
OCCUR-
RENCE ALL)= Ball dad
sat.
TRANSLATE_REGEX (i IN Bill did sit. WITH a
OCCUR-
RENCE 2) = Bill dad
sit.
TRANSLATE_REGEX (i IN Bill did sit. WITH a
FROM 5)
= Bill dad sat.

OVERLAY
OVERLAY remplace une sous-chane donne dune chane (spcifie par
une position de dpart numrique donne et par une longueur donne) par
une chane de remplacement. Quand la longueur spcifie de la sous-chane
est zro, on ne supprime rien dans la chane originale. Mais la chane de
remplacement est insre dans la chane originale en commenant la
position de dpart spcifie.
UPPER
La fonction UPPER convertit une chane de caractres en majuscules,
comme lillustrent les exemples du tableau suivant :

Cette instruction Retourne


UPPER (e. e. cummings) E. E. CUMMINGS
UPPER (Isaac Newton, Ph.D) ISAAC NEWTON, PH.D.

La fonction UPPER naffecte pas les chanes qui sont dj en majuscules.

LOWER
La fonction LOWER convertit une chane de caractres en minuscules,
comme lillustrent les exemples du tableau suivant :

Cette instruction Retourne


LOWER (TAXES) taxes
LOWER (E. E. Cummings) e. e. cummings

La fonction LOWER naffecte pas les chanes qui sont dj en minuscules.

TRIM
La fonction TRIM supprime les blancs (ou dautres caractre) qui se
trouvent au dbut ou la fin dune chane. Voici quelques exemples
dutilisation de TRIM :

Cette instruction Retourne


TRIM (LEADING FROM sens ) sens
TRIM (TRAILING FROM sens ) sens
TRIM (BOTH FROM sens ) sens
TRIM (BOTH s from sens) en
Le caractre par dfaut supprim est lespace. La syntaxe suivante est donc
lgale :

TRIM (BOTH FRsOM sens )

Vous obtenez le mme rsultat quavec le troisime exemple de la table.

TRANSLATE et CONVERT
Les fonctions TRANSLATE et CONVERT prennent une chane source dans
un jeu de caractres et la convertissent en une chane dans un autre jeu de
caractres. Par exemple, vous pourriez convertir une chane de langlais en
kanji ou de lhbreu en franais. Les fonctions de conversion qui spcifient
ces transformations dpendent de limplmentation. Reportez-vous votre
propre systme pour plus de dtails.
Si traduire dun langage dans un autre tait aussi simple que dinvoquer la
fonction SQL TRANSLATE, ce serait formidable. Malheureusement, ce
nest pas aussi facile. TRANSLATE se contente de convertir le jeu de
caractres dune chane. Par exemple, cette fonction peut convertir
Ellas en Ellas, mais elle ne peut pas traduire Ellas en
Grce.

Les fonctions de valeur numrique


Les fonctions de valeur numrique prennent des donnes de diffrents types
en entre, mais elles gnrent toujours une valeur numrique en sortie. SQL
dispose de quinze de ces fonctions :
Position (POSITION)

Fonction doccurrences regex (OCCURRENCES_REGEX)

Position regex (POSITION_REGEX)

Extraction (EXTRACT)

Longueur (CHAR_LENGTH, CHARACTER_LENGTH, OCTET_


LENGTH)
Cardinalit (CARDINALITY)

Valeur absolue (ABS)

Modulo (MOD)

Logarithme naturel (LN)

Exponentielle (EXP)

Puissance (POWER)

Racine carre (SQRT)

Valeur approche basse (FLOOR)

Valeur approche haute (CEIL, CEILING)

Fonction dintervalle (WIDTH_BUCKET)

POSITION
POSITION recherche la chane cible spcifie dans une chane source et
retourne la position du premier caractre de la cible. Pour une chane de
caractres, la syntaxe est la suivante :

POSITION (cible IN source [USING char length


units])

Vous pouvez spcifier une unit de longueur autre que CHARACTER, mais
cest rare. Si vous utilisez des caractres Unicode selon le type le caractre
peut tre de 8, 16, ou 32 bits de long. Si le caractre est de 16 ou 32 bits de
long, vous pouvez explicitement spcifier 8 bits avec USING OCTETS.
Pour une chane binaire, la syntaxe est la suivante

POSITION (cible IN source)

Si la valeur de la cible est gale une sous-chane de longueur identique


des octets contigus dans la chane source, alors le rsultat est suprieur au
nombre doctets qui prcde le dbut du premier comme sous-chane.
Le tableau suivant prsente quelques exemples :

Cette instruction Retourne


POSITION (P IN Pain, bl entier) 1
POSITION (Pai IN Pain, bl entier) 1
POSITION (b IN Pain, bl entier) 7
POSITION (bli IN Pain, bl entier) 0
POSITION ( IN Pain, bl entier) 1
POSITION (01001001 IN 2
001100010100100100100110

Si la fonction ne trouve pas la chane cible, elle retourne la valeur zro. Si


la chane cible est vide (comme dans le dernier exemple de caractre),
POSITION retourne toujours un. Si nimporte lequel des deux oprandes
de la fonction est une valeur nulle, la fonction retourne une valeur nulle.

OCCURRENCES_REGEX
OCCURRENCES_REGEX est une fonction numrique qui retourne le
nombre de correspondances dune expression rgulire dans une chane. Sa
syntaxe est la suivante :

OCCURRENCES_REGEX <left paren>


<XQuery pattern> [ FLAG <XQuery option flag> ]

IN <regex subject string>


[ FROM <start position> ]
[ USING <char length units> ] <right paren>

En voici quelques exemples :

OCCURRENCES_REGEX ( i IN Bill did sit. ) = 3


OCCURRENCES_REGEX ( i IN Bill did sit. FROM
5) = 2
OCCURRENCES_REGEX ( I IN Bill did sit. ) = 0

POSITION_REGEX
POSITION_REGEX est une fonction numrique qui retourne la position
de dpart dune correspondance ou en plus la fin dune correspondance
dune expression rgulire dans une chane. En voici la syntaxe :

POSITION_REGEX <left paren> [ <regex position


start or
after> ]
<XQuery pattern> [ FLAG <XQuery option flag> ]
IN <regex subject string>
[ FROM <start position> ]
[ USING <char length units> ]
[ OCCURRENCE <regex occurrence> ]
[ GROUP <regex capture group> ] <right paren>

<regex position start or after> : := START |


AFTER

Et quelques exemples :

POSITION_REGEX ( i IN Bill did sit. ) = 2


POSITION_REGEX ( START i IN Bill did sit. ) =
2
POSITION_REGEX ( AFTER i IN Bill did sit. ) =
3
POSITION_REGEX ( i IN Bill did sit. FROM 5) =
7
POSITION_REGEX ( i IN Bill did sit.
OCCURRENCE 2 ) =
7
POSITION_REGEX ( I IN Bill did sit. ) = 0

EXTRACT
La fonction EXTRACT extrait un champ dune date/heure ou dun
intervalle. Par exemple, linstruction suivante retourne 08 :

EXTRACT (MONTH FROM DATE 2000-08-20)

CHARACTER_LENGTH
La fonction CHARACTER_LENGTH donne le nombre de caractres dans
une chane de caractres. Par exemple, linstruction suivante retourne 13 :

CHARACTER_LENGTH (Opossum, rti)

Comme je lai fait remarquer plus haut au sujet de la fonction SUBSTRING,


cette fonction nest pas particulirement utile si ses arguments sont des
littraux tels que Opossum, rti. Je peux tout aussi bien crire 13 que
CHARACTER_LENGTH (Opossum, rti). En fait, cette fonction
ne se rvle intressante que si vous lui transmettez une variable en
argument.

OCTET_LENGTH
Dans la terminologie informatique, un octet est une suite de huit bits.
Presque tous les ordinateurs utilisent des octets pour reprsenter les
caractres alphanumriques simples. Mais des langues plus complexes
(comme le chinois) ncessitent 16 bits pour coder leurs signes. La fonction
OCTET_LENGTH compte et retourne le nombre doctets dans une chane.
Sil sagit dune suite de bits, la fonction renvoie la quantit doctets
ncessaire pour stocker tous ces bits. Si cest une chane crite en franais
(un octet par caractre), la fonction retourne le nombre de caractres
quelle contient. Si la chane est crite en chinois, elle retourne deux fois le
nombre de caractres que contient la chane. La chane suivante :

OCTET_LENGTH (Haricots) renvoie


8

donne comme rsultat 11, car chaque caractre peut tre cod sur un seul
octet.
Certains jeux de caractres utilisent un nombre doctets diffrent selon les
caractres. En particulier, quelques jeux de caractres, qui sont des
mlanges de caractres kanji et latins, se servent de caractres
dchappement pour basculer entre les deux alphabets. Par exemple, une
chane forme de kanji et de latin pourrait contenir 30 caractres et
requrir 30 octets si tous les caractres sont latins, 62 octets sils sont tous
kanji (60 octets plus les symboles dchappement de dbut et de fin)
et 150 octets si cest une alternance de caractres latins et kanji (car chaque
caractre kanji requiert deux octets, plus un octet pour les caractres
dchappement de dbut et de fin). La fonction OCTET_LENGTH renvoie le
nombre doctets dont vous avez besoin pour stocker la chane.

CARDINALITY
La cardinalit est le nombre dlments dun ensemble. Elle concerne donc
les collections (tableaux, ensembles, etc.) dans lesquelles chaque lment
est une valeur possdant un certain type de donne. En voici un exemple
dutilisation :

CARDINALITY (EquipeFoot)

Cette fonction devrait normalement renvoyer 11, moins quune expulsion


nait dj eu lieu... Un tableau est une collection ordonne dlments. Un
ensemble multiple est une collection non ordonne dlments. Dans le cas
dune quipe de football, dont la composition varie chaque match et o de
surcrot un mme joueur peut occuper des postes diffrents, les ensembles
multiples sont mieux adapts que les tableaux.

ARRAY_MAX_CARDINALITY
La fonction CARDINALITY retourne le nombre dlments dans le tableau
ou lensemble multiple spcifi, ce qui ne vous indique pas le maximum de
cardinalit qui tait attribu au tableau. Or cette information peut vous tre
utile dans de nombreux cas. Cest pourquoi SQL:2011 a ajout une nouvelle
fonction AR-RAY_MAX_CARDINALITY. Comme vous pouvez le
supposer, elle retourne la cardinalit maximale du tableau spcifi. Il ny a
pas encore de cardinalit maximale pour les ensembles multiples.

TRIM_ARRAY
La fonction TRIM supprime le premier ou dernier caractre dune chane,
alors que la fonction TRIM_ARRAY supprime les derniers lments dun
tableau.
Pour supprimer les trois derniers lments du tableau ALIMENT, utilisez la
syntaxe suivante :

TRIM_ARRAY (ALIMENT, 3)

ABS
La fonction ABS retourne la valeur absolue dune expression numrique.
Exemple :

ABS (-273)

renvoie 273.

MOD
La fonction MOD retourne le reste de la division entire de deux
expressions numriques. Exemple :

MOD (3, 2)

renvoie 1 (modulo de 3 divis par 2).

LN
La fonction LN retourne le logarithme naturel dune expression numrique.
Exemple :

LN (9)
renvoie quelque chose comme 2,197224577. Le nombre de chiffres
dcimaux dpend de limplmentation.

EXP
La fonction EXP retourne lexponentielle dune expression numrique
(cest--dire la base des logarithmes naturels, e, la puissance spcifie
par lexpression). Exemple :

EXP (2)

renvoie quelque chose comme 7,389056. Le nombre de chiffres dcimaux


dpend de limplmentation.

POWER
La fonction POWER retourne la valeur de la premire expression
numrique leve la puissance indique par la seconde.
Exemple :

POWER (2, 8)

renvoie 256, soit 2 lev la puissance 8 (cest le plus grand entier


enregistrable dans un octet).

SQRT
La fonction SQRT retourne la racine carre de lexpression numrique.
Exemple :

SQRT (4)

renvoie 2, la racine carre de 4.

FLOOR
La fonction FLOOR retourne la plus grande valeur entire immdiatement
infrieure celle de lexpression numrique.
Exemple :

FLOOR (3.141592)

renvoie 3.0.

CEIL ou CEILING
La fonction CEIL (ou CEILING) retourne la plus petite valeur entire
immdiatement suprieure celle de lexpression numrique. Exemple :

CEIL (3.141592)

renvoie 4.0.

WIDTH_BUCKET
La fonction WIDTH_BUCKET, qui est utilise dans le traitement
dapplication en ligne (OLAP), comporte quatre arguments. Elle renvoie un
nombre compris entre 0 et la valeur de largument final plus 1. Elle affecte
le premier argument un partage rgulier de lintervalle dfini par le
deuxime et le troisime argument. Si le premier argument nappartient pas
cet intervalle, la fonction retourne 0 (plus petit que la limite infrieure) ou
le dernier argument plus 1 (plus grand que la limite suprieure). Exemple :

WIDTH_BUCKET (PI, 0, 9, 5)

PI est une constante prdfinie de SQL dont la valeur est 3,141592. Cette
instruction partage lintervalle allant de zro neuf en cinq segments gaux
(chacun reprsente donc une longueur de deux units). La valeur de PI se
trouve dans le second godet (entre deux et quatre). La fonction renvoie
donc la valeur 2.

Fonctions de valeur date/heure


SQL dispose de trois fonctions qui retournent des informations sur la date
courante, lheure courante ou les deux. CUR-RENT_DATE renvoie la date
systme, CURRENT_TIME donne lheure courante, et
CURRENT_TIMESTAMP retourne la date et lheure courantes.
CURRENT_DATE naccepte aucun argument. Par contre,
CURRENT_TIME et CURRENT_TIMESTAMP prennent un argument.
Celui-ci spcifie la prcision des secondes. Les types de donnes
date/heure sont dcrits au Chapitre 2. Le concept de prcision y est aussi
prcis.
Le tableau suivant prsente quelques exemples dutilisation de ces
fonctions :

Cette instruction Retourne


CURRENT_DATE 2006-12-31
CURRENT_TIME (1) 08 : 36 : 57.3
CURRENT_TIMESTAMP (2) 2006 12 31 08 : 36 : 57.38

La date que CURRENT_DATE retourne est de type DATE et non


CHARACTER. Lheure fournie par CURRENT_TIME est de type TIME,
tandis que la combinaison date/heure donne par CURRENT_TI-
MESTAMP est de type TIMESTAMP. Comme SQL rcupre ces
informations en interrogeant lhorloge de votre ordinateur, elles sont
toujours correctes pour le fuseau horaire dans lequel celui-ci se trouve.
Si vous voulez traiter les dates et les heures sous la forme de chanes de
caractres afin dutiliser les fonctions qui manipulent ces dernires, vous
pouvez procder une conversion de type en utilisant lexpression CAST
dcrite au Chapitre 9.

Fonctions de valeur intervalle


Une fonction de valeur intervalle nomme ABS a t introduite dans
SQL:1999. Elle est similaire la fonction de valeur numrique ABS, mais
elle opre sur des donnes de type intervalle et non de type numrique. ABS
prend un seul oprande et retourne un intervalle de prcision identique qui
ne comporte pas de valeur ngative. En voici un exemple :

ABS ( TIME 11:31:00 TIME 12:31:00 )


Le rsultat est

INTERVAL +1:00:00 HOUR TO SECOND


Chapitre 9
Expressions SQL avances
DANS CE CHAPITRE :
Utiliser des expressions conditionnelles CASE.

Convertir des donnes dun type dans un autre.

Gagner du temps de saisie en utilisant des expressions.

A
u Chapitre 2, SQL est dcrit comme un sous-langage de donnes. En
fait, sa seule fonction consiste manipuler des donnes dans une base.
SQL manque des nombreuses fonctionnalits dun langage procdural
conventionnel. Il en rsulte que les dveloppeurs doivent passer sans cesse
de SQL un autre langage pour contrler le flux de lexcution. Ces
incessants va-et-vient ralentissent le dveloppement et affectent les
performances lors de lexcution. Les problmes de performances lis aux
limitations de SQL ont conduit ses concepteurs lui ajouter des
fonctionnalits supplmentaires lors de chaque sortie dune nouvelle
version du standard. Lune des fonctionnalits rcentes de SQL,
lexpression CASE, permet de construire des structures conditionnelles.
Une autre fonctionnalit, lexpression CAST, facilite la conversion des
donnes dune table dun type vers un autre (cest ce que lon appelle le
transtypage). Une troisime fonctionnalit, lvaluation simultane de
plusieurs valeurs, permet de traiter une liste de valeurs l o vous ne
pouviez auparavant nen traiter quune seule. Par exemple, si votre liste de
valeurs est une srie de colonnes dune table, vous pouvez maintenant leur
appliquer une opration en une fois en utilisant une syntaxe fort simple.

Les expressions conditionnelles


CASE
Chaque langage informatique digne de ce nom comporte une expression
conditionnelle. En fait, la plupart des langages en ont plusieurs. La plus
courante des expressions conditionnelles est sans doute la structure IF...
THEN... ELSE... ENDIF. Si la condition qui suit le mot cl IF est
vrifie, le bloc de commandes qui suit le mot cl THEN est excut. Si
cette condition nest pas vrifie, cest le bloc de commandes qui suit ELSE
qui est excut. Le mot cl ENDIF signale la fin de la structure. Cette
structure permet de grer des dcisions une ou deux issues. Elle nest pas
adapte aux dcisions plus complexes.
La plupart des langages complets ont une instruction du genre CASE qui
gre lexcution de plusieurs tches partir dautant de conditions.

SQL diffre des autres langages en ce sens que CASE est une expression et
non une instruction. En tant que telle, CASE est simplement un lment
dune instruction et non une instruction en soi. Avec SQL, vous pouvez
placer une expression CASE quasiment partout o une valeur peut tre
utilise. Lors de lexcution, lexpression CASE est remplace par une
valeur. Linstruction CASE que vous trouvez dans les autres langages nest
pas value une valeur, mais elle excute un bloc dinstructions.
Vous pouvez utiliser lexpression CASE comme suit :
Utiliser lexpression avec des critres de recherche.
CASE recherche les lignes dune table pour lesquelles les
critres spcifis sont vrifis. Si CASE trouve une ligne
pour laquelle ces critres sont valus comme tant vrais,
linstruction qui contient lexpression CASE est applique
cette ligne.

Utiliser lexpression CASE pour comparer un champ


dune table la valeur spcifie. Le rsultat de
linstruction qui contient lexpression CASE dpend de la
valeur que contient le champ.
Les sections qui suivent, Utiliser CASE avec des critres de recherche
et Utiliser CASE avec des valeurs , vous permettront de mieux
apprhender ces concepts. Vous trouverez tout dabord deux exemples
dutilisation de CASE avec des critres de recherche. Un de ces exemples
recherche des valeurs dans une table et les modifie en fonction dune
certaine condition. La seconde section propose deux exemples dutilisation
de la forme de CASE avec des valeurs.

Utiliser CASE avec des critres de


recherche
Une utilisation intressante de lexpression CASE est la recherche dans une
table de lignes qui vrifient un critre de recherche. Si vous utilisez CASE
de cette manire, lexpression adoptera la syntaxe suivante :

CASE
WHEN critere1 THEN resultat1

WHEN critere2 THEN resultat2


...
WHEN criteren THEN resultatn
ELSE resultatx
END

CASE examine la premire des lignes qualifies (la premire ligne qui
rpond au critre de la clause WHERE sil y en a une) pour valuer le
critere1. Si cette condition est vrifie, lexpression CASE prend la
valeur result1. Sinon, lexpression CASE value le critere2. Sil
est vrifi, lexpression CASE prend la valeur result2, et ainsi de suite.
Si aucun des critres nest vrifi, lexpression CASE prend la valeur
resultatx. La clause ELSE est optionnelle. Si lexpression na pas de
clause ELSE et quaucun des critres nest vrifi, elle prend la valeur
nulle. Une fois linstruction SQL qui contient lexpression CASE applique
la premire ligne qualifie de la table, elle traite la ligne suivante, et ce
jusqu ce que la table soit entirement parcourue.

Modifier des valeurs en fonction de


critre
Vous pouvez utiliser une expression CASE dans une instruction SQL la
place de nimporte quelle valeur. Par exemple, CASE peut tre incorpore
dans une instruction UPDATE pour effectuer plusieurs modifications dans
une table en fonction dun certain critre. Considrez lexemple suivant :

UPDATE ALIMENTS
SET EVALGRAISSE = CASE
WHEN GRAISSE < 1
THEN trs allg
WHEN GRAISSE < 5
THEN allg
WHEN GRAISSE < 20
THEN modrment allg
WHEN GRAISSE < 50
THEN trs gras
ELSE attaque cardiaque
END;

Cette instruction value les conditions WHEN dans lordre jusqu ce que
lune soit vrifie, aprs quoi elle ignore les autres conditions.
Le Tableau 8.2 du Chapitre 8 reprsente une table nutritionnelle
pour 100 grammes de divers aliments. Une base de donnes qui contiendrait
ces informations peut recevoir une colonne EVALGRAISSE qui donnerait
au consommateur un aperu rapide du taux de matire graisseuse de chaque
aliment. Si vous appliquez linstruction UPDATE la table ALIMENTS du
Chapitre 8, elle attribuera aux asperges une valeur trs allge et au poulet
une valeur allge. Les autres aliments seront classs dans la catgorie
haut risque attaque cardiaque.
Eviter des conditions qui gnrent des
erreurs
Lexpression CASE permet aussi dviter des exceptions en contrlant des
conditions susceptibles de provoquer des erreurs.
Prenons pour exemple le salaire de commerciaux. Les entreprises qui paient
leurs commerciaux la commission rmunrent souvent leurs nouveaux
employs en leur versant un salaire qui anticipe sur lvolution de leurs
rsultats. Dans lexemple suivant, les nouveaux commerciaux reoivent un
fixe qui diminue lorsque la commission augmente.

UPDATE COMP_VENTES
SET COMP = COMMISSION + CASE
WHEN COMMISSION <> 0
THEN FIXE / COMMISSION
WHEN COMMISSION = 0
THEN FIXE
END;

Si la commission dun commercial vaut zro (il dbute), la structure utilise


dans lexemple permet dviter une opration de division par zro, ce qui
engendrerait une erreur. Si la commission du commercial nest pas nulle,
son salaire total est gal la commission plus le fixe, celui-ci tant calcul
proportionnellement la commission.
Toutes les expressions THEN dune structure CASE doivent tre du mme
type : toutes numriques, toutes des chanes de caractres ou toutes des
dates. Le rsultat de lexpression CASE possde alors ce mme type.

Utiliser CASE avec des valeurs


Vous pouvez utiliser une forme plus compacte de lexpression CASE si
vous voulez comparer une valeur test une srie dautres valeurs. Cette
variante se rvle utile au sein dune instruction SELECT ou UPDATE
dans le cas dune table contenant un nombre limit de valeurs possibles
dans une colonne, et que vous voulez associer un certain rsultat chacune
de ces valeurs. Si vous utilisez CASE de cette manire, lexpression
adoptera la syntaxe suivante :

CASE valeurt
WHEN valeur1 THEN resultat1

WHEN valeur2 THEN resultat2


...
WHEN valeurn THEN resultatn
ELSE resultatx
END

Si la valeur test (valeurt) est gale valeur1, lexpression prend la


valeur resultat1. Si valeurt nest pas gale valeur1, mais
gale valeur2, lexpression prend la valeur resultat2. Le test se
poursuit jusqu ce quune correspondance soit trouve. Si aucune des
valeurs de comparaison nest gale la valeur test, lexpression prend la
valeur resultatx. Si la clause optionnelle ELSE nest pas prsente, et
si aucune des comparaisons ne russit, lexpression prend la valeur nulle.
Pour comprendre comment fonctionne cette forme de CASE, prenons
lexemple dune table qui contient les noms et les grades de divers
officiers. Vous voulez dresser la liste des noms prcds de labrviation
correcte de leur grade. Linstruction suivante effectue ce travail :

SELECT CASE GRADE


WHEN gnral THEN Gn.
WHEN colonel THEN Col.
WHEN lieutenant-colonel THEN Lt. Col.

WHEN major THEN Maj.
WHEN capitaine THEN Capt.
WHEN premier lieutenant THEN 1er Lt.
WHEN second lieutenant THEN 2d Lt.
ELSE NULL
END;
NOM
FROM OFFICIERS ;

Le rsultat pourrait se prsenter ainsi :

Capt. Lestocade
Col. Durand
Gn. Napolon
Maj. Dsastre
Delabase

Comme le grade du soldat Delabase nest pas mentionn dans lexpression


CASE, la clause ELSE laisse vide ce renseignement. Prenons un autre
exemple. Supposez que le capitaine Lestocade soit promu au rang de major.
Vous voulez donc mettre jour la base de donnes OFFICIERS pour en
tenir compte. La variable nom_officier a pour valeur Lestocade et la
variable nouveau_ grade contient un entier (4) qui correspond au
nouveau grade de Lestocade, conformment au tableau suivant :

nouveau_grade Grade
1 gnral
2 colonel
3 lieutenant-colonel
4 major
5 capitaine
6 premier lieutenant
7 second lieutenant
8 NULL

Vous pouvez enregistrer la promotion en utilisant le code SQL suivant :

UPDATE OFFICIERS
SET GRADE = CASE :nouveau_grade
WHEN 1 THEN gnral
WHEN 2 THEN colonel
WHEN 3 THEN lieutenant-
colonel
WHEN 4 THEN major
WHEN 5 THEN capitaine
WHEN 6 THEN premier
lieutenant
WHEN 7 THEN second lieutenant
WHEN 8 THEN NULL
END
WHERE LAST_NAME = :nom_officier ;

Lutilisation de CASE avec des valeurs peut aussi prendre une syntaxe
alternative :

CASE
WHEN valeurt = valeur1 THEN resultat1
WHEN valeurt = valeur2 THEN resultat2
...
WHEN valeurt = valeurn THEN resultatn
ELSE resultatx
END

Un cas particulier : NULLIF


Les champs dune base de donnes contiennent des valeurs bien dfinies, du
moins si elles sont dtermines. En gnral, si la valeur dun champ est
inconnue, il possde la valeur nulle (NULL). Sous SQL, vous pouvez
utiliser une expression CASE pour changer le contenu dun champ en une
valeur nulle. La nullit indique que vous ne connaissez plus la valeur de ce
champ.
Supposez par exemple que vous tes lheureux propritaire dune
compagnie arienne base aux tats-Unis qui propose des vols entre la
Californie du Sud et ltat de Washington. Jusqu tout rcemment, les vols
sarrtaient laroport international de San Jos pour faire le plein.
Malheureusement, on vous a retir lautorisation datterrir San Jos. Vous
devez dsormais faire escale pour remplir vos avions de krosne soit
laroport de San Francisco, soit celui dOakland. Pour linstant, vous ne
savez pas quels sont les vols qui vont sarrter dans ces aroports. Mais
vous savez quaucun dentre eux ne sarrtera plus San Jos. Votre base de
donnes VOLS contient des informations importantes sur chacune de vos
routes ariennes. Vous allez donc mettre jour cette base en y supprimant
toute rfrence San Jos. Lexemple suivant propose une manire de
procder :

UPDATE VOLS
SET ESCALE_KEROSENE =CASE
WHEN ESCALE_KEROSENE
= San
Jos
THEN NULL
ELSE ESCALE_KEROSENE
END ;

Comme ce genre de situation se reproduit couramment, SQL propose une


notation abrge pour effectuer ce type de travail. Lexemple prcdent
pourrait se prsenter ainsi en utilisant cette notation abrge :

UPDATE VOLS
SET ESCALE_KEROSENE = NULLIF(ESCALE_KEROSENE,
San
Jos);

Vous pouvez lire cette expression comme mettre jour la base de donnes
VOLS en passant la colonne ESCALE_KEROSENE null, si la valeur de
ESCALE_KEROSENE est San Jos ; autrement, ne rien faire .
NULLIF se rvle encore plus pratique si vous convertissez des donnes
que vous aviez accumules pour les utiliser avec un langage de
programmation standard tel que COBOL ou Fortran. Les langages de
programmation standard ne connaissent pas la valeur null. Cest pourquoi
ils traduisent le concept d inconnu laide de valeurs spciales. Par
exemple, une valeur -1 peut reprsenter la valeur inconnue pour
SALAIRE et la chane de caractres *** peut figurer une valeur
inconnue ou indterminable de CODE_TRAVAIL. Si vous voulez transcrire
ces tats dans une base de donnes compatible SQL, vous devrez les
convertir en valeurs nulles. Lexemple suivant effectue cette conversion
pour la table EMPLOYES o se trouvent quelques salaires dont le montant
est inconnu :

UPDATE EMPLOYES
SET SALAIRE = CASE SALAIRE
WHEN -1 THEN NULL
ELSE SALAIRE
END;

La forme abrge de NULLIF est encore plus simple :

UPDATE EMPLOYES
SET SALAIRE =NULLIF (SALAIRE, -1) ;

Un autre cas particulier de CASE :


COALESCE
COALESCE, comme NULLIF, est une forme abrge particulire de
lexpression CASE. Elle traite une liste de valeurs qui peuvent tre ou ne
pas tre nulles. Voici comment elle fonctionne :
Si une seule des valeurs de la liste nest pas nulle,
lexpression COALESCE prend cette valeur.

Si plus dune valeur de la liste nest pas nulle,


lexpression retourne la premire valeur non nulle de cette
liste.

Si toutes les valeurs de la liste sont nulles, lexpression


prend la valeur nulle.
Une expression CASE correspondant cette dmarche prendrait la forme
suivante :

CASE
WHEN valeur1 IS NOT NULL
THEN valeur1
WHEN valeur2 IS NOT NULL
THEN valeur2
...
WHEN valeurn IS NOT NULL
THEN valeurn
ELSE NULL
END

La forme abrge COALESCE donnera ce qui suit :

COALESCE (valeur1, valeur2.... valeurn)

Vous utiliserez probablement lexpression COALESCE aprs avoir effectu


une opration OUTERJOIN (elle est aborde au Chapitre 10). Dans ce cas,
COALESCE peut vous viter de saisir une grande quantit de texte.

Conversions de types de donnes


(CAST)
Le Chapitre 2 traite de tous les types de donnes que SQL reconnat et
supporte. Dans lidal, chaque colonne dune table de base de donnes doit
possder un type de donnes prcis. Cependant, il nest pas toujours aussi
simple deffectuer cette attribution. Supposons quen dfinissant une table
de votre base de donnes vous affectiez une colonne un type de donnes
convenant parfaitement ltat actuel de votre application. Par la suite,
vous voulez tendre le champ de votre application, ou mme crire une
application totalement nouvelle qui utilise les donnes dune manire
diffrente. Cette nouvelle utilisation peut ncessiter un autre type de
donnes que celui qui a t choisi lorigine.
Vous pouvez aussi avoir besoin de comparer une colonne dune table
possdant un certain type avec une colonne dun type diffrent dans une
autre table. Cela se produira par exemple si vous stockez des dates sous la
forme de chanes de caractres dans une table, et encore des dates, mais au
format date-heure, dans une seconde table. Mme si les deux colonnes
contiennent des informations dont la nature est identique (des dates), il nest
normalement pas possible de procder la comparaison car leurs types sont
diffrents. Cette incompatibilit pose un problme dans SQL-86 et SQL-89.
Cependant, une solution simple existe depuis SQL-92 : lexpression CAST.

Lexpression CAST convertit les donnes dune table ou des variables dun
type dans un autre. Cest ce que lon appelle le transtypage. Aprs avoir
effectu la conversion, vous pouvez effectuer lopration ou les
comparaisons que vous souhaitez.
Bien entendu, lutilisation de lexpression CAST est soumise certaines
restrictions. Vous ne pouvez pas convertir nimporte quel type de donnes
dans un autre. La donne convertir doit tre compatible avec son nouveau
type. Par exemple, vous pouvez utiliser CAST pour convertir une chane de
caractres de type CHAR(10) 2007-04-26 en type DATE. Cependant, vous
ne pouvez pas utiliser CAST pour convertir la chane de caractres
CHAR(10) rhinocros en type DATE. De mme, il nest pas possible de
transformer un INTEGER en un type SMALLINT si la valeur de
INTEGER dpasse la valeur maximale autorise pour SMALLINT.
Vous pouvez convertir une donne de nimporte quel type caractre dans un
autre (tel que numrique ou date), condition que sa valeur adopte la forme
littrale du nouveau type. De mme, vous pouvez convertir une donne dun
type quelconque vers un type caractre condition que sa valeur prenne la
forme littrale du type original.
La liste suivante numre les problmes de conversion auxquels vous
pouvez tre confront :
Un type numrique en nimporte quel type
numrique : si vous convertissez vers un type dont la
partie dcimale est moins prcise, le systme arrondira ou
tronquera le rsultat.
Un type numrique exact en un intervalle tel que
INTERVAL DAY ou INTERVAL SECOND.

Une DATE en un TIMESTAMP : la partie heure de


TIMESTAMP sera remplie de zros.

Un TIME en TIME dont la partie dcimale des


fractions de seconde est diffrente, ou en TIMESTAMP :
la partie date de TIMESTAMP sera remplie avec la date
actuelle.

Un TIMESTAMP en DATE, en TIME ou en TIMESTAMP


dont la prcision de la partie fractionnelle des
secondes est diffrente.

Un INTERVAL mois-anne en un type numrique


exact ou en un INTERVAL anne-mois dont la prcision
du champ prfixe est diffrente.

Un INTERVAL jour-heure en un type numrique exact


ou en un autre INTERVAL jour-heure dont la prcision
du champ prfixe est diffrente.

Utiliser CAST avec SQL


Supposez que vous travaillez pour une socit qui gre par ordinateur la
liste complte de ses employs, quils soient temps plein ou temps
partiel. Vous stockez la liste des employs temps plein dans la table
EMPLOYES, et vous distinguez chacun dentre eux par leur numro de
Scurit sociale que vous stockez sous la forme dune chane du type
CHAR(9). Vous dressez la liste des employs temps partiel dans une table
TEMPS_PARTIEL. Mais, cette fois, leurs numros de Scurit sociale sont
enregistrs au format numrique INTEGER. Vous allez maintenant gnrer
la liste des personnes qui apparaissent dans ces deux tables. Vous pouvez
faire appel CAST pour effectuer cette tche :

SELECT * FROM EMPLOYES


WHERE EMPLOYES.NSS =
CAST (TEMPS_PARTIEL.NSS AS INTEGER) ;

Utiliser CAST avec SQL et un


langage hte
CAST se rvle trs utile pour grer des types de donnes lgaux dans
SQL, mais qui nexistent pas dans le langage hte que vous utilisez. La liste
suivante prsente quelques exemples de ces types de donnes :
Les types DECIMAL et NUMERIC de SQL nexistent pas en
Fortran et Pascal.

Les types FLOAT et REAL de SQL nexistent pas en COBOL


standard.

Le type SQL DATETIME nexiste dans aucun autre langage.

Supposons que vous utilisiez le Fortran ou le Pascal pour accder des


tables contenant des colonnes au format DECIMAL (5,3). Vous souhaitez
viter les erreurs gnres lors de la conversion de ces valeurs dans le type
de donnes REAL du Fortran et du Pascal. Vous pouvez transtyper la donne
dans/ depuis le type chane de caractres du langage hte. Vous rcuprez
alors un salaire numrique 898,37 sous la forme dune valeur CHAR(10)
0000898,37. Pour ce faire, vous allez utiliser CAST afin de
transformer le type de donnes SQL DECIMAL (5,3) en un CHAR(10).
Commencez par stocker lidentifiant EMPID dun employ dans la variable
hte : emp_id_var :

SELECT CAST (SALAIRE AS CHAR (10)) INTO


:salaire_var
FROM EMPLOYES
WHERE EMPID = :emp_id_var ;

Vous utiliserez ensuite le code suivant pour indiquer lapplication quelle


doit examiner la valeur chane de caractres que contient salaire_var,
la transformer en une nouvelle valeur 0000203,74, puis la mettre
jour dans la base de donnes :

UPDATE EMPLOYES
SET SALAIRE = CAST (:salaire_var AS DECIMAL
(5,3))
WHERE EMPID = :emp_id_var ;

Il est difficile de grer des chanes de caractres telles que 000198,37


en Fortran ou Pascal. Mais vous pouvez crire un ensemble de sous-
programmes qui effectueront les manipulations ncessaires. Il sera ensuite
possible de rcuprer et mettre jour nimporte quelle donne SQL depuis
un langage hte quelconque.
Lide gnrale est que CAST convient mieux la conversion de types de
donnes entre un hte et une base quau transtypage lintrieur de la base
de donnes elle-mme.

Les expressions valeur de ligne


Dans les standards SQL dorigine, tels que SQL-86 et SQL-89, la plupart
des oprations traitent une seule valeur ou une seule colonne dans une ligne
dune table. Pour oprer sur plusieurs valeurs, vous devez construire des
expressions complexes en utilisant des connecteurs logiques (ils sont
abords au Chapitre 10).
Depuis SQL-92, vous pouvez utiliser des expressions valeur de ligne. Ces
expressions permettent de manipuler une liste de valeurs ou de colonnes, et
non plus simplement une seule valeur ou une seule colonne. Elles se
prsentent sous la forme dune srie dexpressions de valeur spares par
des virgules et dlimites par des parenthses. Vous pouvez oprer sur une
ligne tout entire ou seulement sur une partie de cette ligne.
Le Chapitre 6 explique comment utiliser linstruction INSERT pour
ajouter une nouvelle ligne une table. Pour se faire, linstruction utilise une
expression valeur de ligne. Par exemple :

INSERT INTO ALIMENTS


(NOM, CALORIES, PROTEINES, GRAISSE,
HYDRATECARBONE)
VALUES
(Fromage, cheddar, 398, 25, 32.2, 2.1)

Dans cet exemple, (Fromage, cheddar, 398, 25, 32.2,


2.1) est une expression valeur de ligne. Si vous utilisez de cette manire
une telle expression dans une instruction INSERT, elle peut contenir des
valeurs nulles ou par dfaut (une valeur par dfaut est celle que
prend une colonne de la table en labsence de toute information). La ligne
suivante est une expression valeur de ligne autorise :

(Fromage, cheddar, 398, NULL, 32.2, DEFAULT)

Vous pouvez ajouter simultanment plusieurs lignes une table en utilisant


de multiples valeurs dans une clause VALUES, comme suit :

INSERT INTO ALIMENTS


(NOM, CALORIES, PROTEINES, GRAISSE,
HYDRATECARBONE)
VALUES
(Lait, 14, 1.2, 0.2, 2.5)
(Margarine, 720, 0.6, 81.0, 0.4)
(Moutarde, 75, 4.7, 4.4, 6.4)
(Spaghetti, 148, 5.0, 0.5, 30.1)

Il est aussi possible dutiliser des expressions valeur de ligne pour


simplifier lcriture de comparaisons. Supposez que vous avez deux tables
de valeurs nutritionnelles, lune en franais et lautre en espagnol. Vous
recherchez les lignes dans la table en franais qui correspondent exactement
aux lignes de la table en espagnol. Sans les expressions valeur de ligne,
vous devriez crire quelque chose comme :

SELECT * FROM ALIMENTS


WHERE ALIMENTS.CALORIES = COMIDA.CALORIA
AND ALIMENTS.PROTEINES = COMIDA.PROTEINA
AND ALIMENTS.GRAISSE = COMIDA.GORDO
AND ALIMENTS.HYDRATECARBO =
COMIDA.CARBOHIDRATO ;

Les expressions valeur de ligne vous permettent dcrire le mme code de


la manire suivante :

SELECT * FROM ALIMENTS


WHERE (ALIMENTS.CALORIES, ALIMENTS.PROTEINES,
ALI-
MENTS.GRAISSE,
ALIMENTS.HYDRATECARBO)
=
(COMIDA.CALORIA, COMIDA.PROTEINA,
COMIDA.GORDO,
COMIDA.CARBOHIDRATO) ;

Dans cet exemple, le gain de saisie nest pas norme. Mais vous pourriez la
simplifier davantage si vous compariez plusieurs colonnes. Si le profit nest
que marginal, autant utiliser la syntaxe dveloppe, car elle est plus facile
lire (et donc corriger ou modifier le cas chant).
Un autre avantage de lexpression valeur de ligne sur son quivalent cod
est quelle est plus rapide. En principe, une implmentation intelligente
devrait tre capable danalyser la version code et de la transformer en une
version valeur de ligne. Mais, en pratique, cest une opration difficile et
dlicate quaucun SGDB actuel ne sait effectuer.
Chapitre 10
Isoler les donnes dont vous avez
besoin
DANS CE CHAPITRE :
Spcifier les tables avec lesquelles vous voulez travailler.

Isoler les lignes dignes dintrt.

Construire des clauses WHERE efficaces.

Grer les valeurs nulles.

Construire des expressions composes avec des connecteurs logiques.

Regrouper les rsultats dune requte par colonne.

Ordonner le rsultat dune requte.

Oprer sur des lignes relatives.

U
n systme de gestion de base de donnes a deux fonctions principales :
stocker les donnes et y donner facilement accs. Enregistrer les
donnes nest pas compliqu. Une armoire fichiers peut faire la mme
chose. Toute la difficult rside dans laccs aux donnes. Pour que celles-
ci soient utiles, vous devez tre capable de sparer le petit nombre dentre
elles qui vous intresse de lnorme volume de donnes dont vous ne voulez
pas.
SQL vous permet dutiliser quelques caractristiques de la donne elle-
mme pour dterminer si une certaine ligne dune table est dun quelconque
intrt pour vous. Les instructions SELECT, DELETE et UPDATE
indiquent au moteur de la base (la partie du SGBD qui agit sur les donnes)
quelle ligne vous allez slectionner, supprimer ou modifier. Il est possible
dajouter des clauses modificatrices aux instructions SELECT, DELETE et
UPDATE afin daffiner la recherche.

Clauses modificatrices
Les clauses modificatrices disponibles en SQL sont
FROM, WHERE, HAVING, GROUP BY et ORDER BY. La clause
FROM indique au moteur de base de donnes la ou les tables sur lesquelles
vous voulez travailler. Les clauses WHERE et HAVING spcifient une
caractristique de la donne qui permet de dcider sil faut ou non inclure
une ligne particulire dans lopration courante. Les clauses GROUP BY et
ORDER BY prcisent comment organiser les lignes rcupres. Le
Tableau 10.1 vous prsente un rcapitulatif.

TABLEAU 10.1 Clauses modificatrices et fonctions.

Clause Fonction
modificatrice
FROM Spcifie de quelle table les donnes sont extraites.
WHERE Filtre les lignes qui ne rpondent pas aux critres de
recherche.
GROUP BY Spare les lignes regroupes selon les valeurs des
colonnes de regroupement.
HAVING Filtre les groupes qui ne correspondent pas aux
critres de recherche.
ORDER BY Trie les rsultats produits par les clauses prcdentes
pour donner le rsultat final.

Si vous utilisez simultanment plusieurs de ces clauses, elles doivent


apparatre dans lordre suivant :
SELECT liste_colonnes
FROM liste_tables
[WHERE criteres_recherche]
[GROUP BY colonnes_groupe]
[HAVING criteres_recherche]
[ORDER BY criteres_tri]

Voici un rsum du rle de ces clauses :


La clause WHERE est un filtre qui laisse passer les lignes
qui correspondent aux critres de recherche et rejette les
autres.

La clause GROUP BY ordonne les lignes que la clause


WHERE laisse passer en fonction des valeurs prsentes
dans les colonnes de regroupement.

La clause HAVING est un autre filtre qui ne laisse passer


que les groupes produits par la clause GROUP BY
rpondant au critre de recherche, les autres tant rejets.

La clause ORDER BY trie ce qui reste une fois que les


clauses prcdentes ont trait la table.

Comme la prsence de crochets ([]) lindique, les clauses WHERE, GROUP


BY, HAVING et ORDER BY sont optionnelles.

SQL value ces clauses dans lordre FROM, WHERE, GROUP BY, HAVING
et enfin SELECT. Elles sont traites comme dans un pipeline , ce qui
signifie que chaque clause reoit le rsultat de la clause prcdente et
produit un rsultat pour la clause suivante. En notation fonctionnelle, cet
ordre dvaluation est le suivant :

SELECT (HAVING(GROUP BY(WHERE(FROM...)))


ORDER BY intervient aprs SELECT, ce qui explique pourquoi ORDER
BY ne peut rfrencer que des colonnes prsentes dans la liste SELECT.
ORDER BY ne peut pas utiliser dautres colonnes provenant de la ou des
tables FROM.

Clauses FROM
Il est facile de comprendre la clause FROM si vous nutilisez quune seule
table, comme dans lexemple suivant :

SELECT * FROM VENTES ;

Cette instruction retourne toutes les donnes de toutes les lignes de chaque
colonne de la table VENTES. Cependant, vous pouvez spcifier plus dune
table dans une clause FROM. Considrez lexemple suivant :

SELECT *
FROM CLIENTS, VENTES ;

Cette instruction gnre une table virtuelle qui associe les donnes de la
table CLIENTS avec les donnes de la table VENTES. Chaque ligne de la
table CLIENTS est combine avec chaque ligne de la table VENTES pour
former la nouvelle table. Cette dernire contient donc un nombre de lignes
gal celui de la table CLIENTS multipli par le nombre de lignes de la
table VENTES. Si CLIENTS possde dix lignes et que VENTES en a cent,
alors la nouvelle table virtuelle en contient mille...
Cette opration est appele produit cartsien de deux tables sources. Le
produit cartsien est en fait un type de jointure. Les oprations de jointure
sont traites en dtail au Chapitre 11.
Dans la plupart des applications, les lignes obtenues lissue du produit
cartsien de deux tables sont gnralement dpourvues de sens. Dans le cas
de la table virtuelle forme partir des tables CLIENTS et VENTES,
seules les lignes o le CLIENT_ ID de la table CLIENTS correspond au
CLIENT_ID de la table VENTES sont dignes dintrt. Vous pouvez
liminer tout le reste en utilisant une clause WHERE.
Les clauses WHERE
Dans ce livre, jai dj utilis de nombreuses fois la clause WHERE sans
vraiment la prsenter, car sa signification et son utilisation semblent
videntes. Une instruction effectue une opration (comme SELECT,
DELETE ou UPDATE) uniquement sur les lignes qui vrifient la condition
exprime par la clause WHERE. La syntaxe de cette clause est la suivante :

SELECT liste_colonnes
FROM nom_table
WHERE condition ;

DELETE FROM nom_table


WHERE condition ;
UPDATE nom_table
SET colonne1=valeur1, colonne2=valeur2,
...co-
lonnen=valeurn
WHERE condition ;

La condition exprime par la clause WHERE peut tre simple ou


arbitrairement complexe. laide des connecteurs logiques AND, OR et
NOT (ils sont traits plus loin dans ce chapitre), il est possible de
combiner plusieurs conditions pour en crer une nouvelle.
Les instructions suivantes vous prsentent quelques utilisations de la clause
WHERE :

WHERE CLIENTS.CLIENT_ID =VENTES.CLIENT_ID


WHERE ALIMENTS.CALORIES = COMIDA.CALORIA
WHERE ALIMENTS.CALORIES < 219
WHERE ALIMENTS.CALORIES > 3 + valeur_base
WHERE ALIMENTS.CALORIES < 219 AND
ALIMENTS.PROTEINES >
27.4
Les conditions que la clause WHERE exprime sont galement appeles
prdicats. Un prdicat est une expression qui exprime un fait concernant les
valeurs.
Par exemple, le prdicat ALIMENTS. CALORIES < 219 est vrai si la
valeur de la ligne courante de la colonne ALIMENTS. CALORIES est
strictement infrieure 219. Si cette assertion est vraie, la condition est
remplie. Une assertion peut tre soit vraie, soit fausse, soit inconnue. Elle
est inconnue si un ou plusieurs lments dans cette assertion sont nuls
(cest--dire inconnus, indfinis, indterminables, etc.). Les prdicats de
comparaison (=, <, >, <>, <= et <=) sont les plus utiliss, mais SQL en
comporte dautres qui vous permettent disoler de manire beaucoup plus
prcise les donnes que vous recherchez. La liste suivante rpertorie les
prdicats servant filtrer les donnes :
Prdicats de comparaison

BETWEEN

IN [NOT IN]

LIKE [NOT LIKE]

NULL

ALL, SOME, ANY

EXISTS

UNIQUE

OVERLAPS

MATCH

SIMILAR

DISTINCT

Les prdicats de comparaison


Les exemples de la section prcdente sont des usages typiques des
prdicats de comparaison : vous y comparez une valeur une autre.
Lopration (SELECT, UPDATE, DELETE, etc.) est applique chaque
ligne pour laquelle cette comparaison est value comme tant vraie
(TRUE), autrement dit pour laquelle la clause WHERE est satisfaite. Les
lignes pour lesquelles la comparaison renvoie FALSE sont limines.
Considrez par exemple linstruction SQL suivante :

SELECT *FROM ALIMENTS


WHERE CALORIES < 219 ;

Cette instruction affiche toutes les lignes de la table ALIMENTS pour


lesquelles la valeur de la colonne CALORIES est infrieure 219.
Le Tableau 10.2 prsente six prdicats de comparaison :

BETWEEN
Il arrive que vous souhaitiez retenir une ligne uniquement si la valeur dune
de ses colonnes est comprise dans une certaine plage. Lutilisation de
prdicats de comparaison vous permet deffectuer ce type de slection. Par
exemple, vous pouvez formuler une clause WHERE servant slectionner
toutes les lignes de la table ALIMENTS dans lesquelles la valeur de la
colonne CALORIES est suprieure 100 et infrieure 300 :

TABLEAU 10.2 Prdicats de comparaison SQL.

Comparaison Symbole

Egal =

Diffrent de <>

Infrieur <

Infrieur ou gal <=

Suprieur >
Suprieur ou gal >=

WHERE ALIMENTS.CALORIES > 100 AND


ALIMENTS.CALORIES <300

Cette comparaison ninclut pas les aliments dont la valeur de CALORIES


vaut exactement 100 ou 300. Pour inclure ces valeurs limites, vous pouvez
crire linstruction ci-dessous :

WHERE ALIMENTS.CALORIES >=100 AND


ALIMENTS.CALORIES <=300

Une autre manire de spcifier une plage qui comprend ces bornes consiste
utiliser le prdicat BETWEEN comme suit :

WHERE ALIMENTS.CALORIES BETWEEN 100 AND 300

Cette clause est fonctionnellement identique celle de lexemple prcdent,


qui utilise des prdicats de comparaison. Comme vous pouvez le constater,
cette formulation est plus efficace et un peu plus intuitive que celle qui
utilise deux prdicats de comparaison relis par le connecteur logique AND.

Le mot cl BETWEEN peut prter confusion, car il nindique pas


explicitement si la clause comprend les valeurs limites. En fait, la rponse
est oui. De plus, aucun petit oiseau ne va venir se poser sur votre paule
pour vous rappeler que le premier terme de la comparaison doit tre gal
ou infrieur au second. Par exemple, si ALIMENTS. CALORIES contient
une valeur de 200, la clause suivante est valide :

WHERE ALIMENTS.CALORIES BETWEEN 100 AND 300

Cependant, la clause ci-dessous, qui semble pourtant quivaloir lexemple


prcdent, fournira le rsultat inverse :

WHERE ALIMENTS.CALORIES BETWEEN 300 AND 100

Si vous utilisez BETWEEN, vous devez pouvoir garantir que le premier


terme de votre comparaison est toujours gal ou infrieur au second.
Vous pouvez utiliser le prdicat BETWEEN avec les types de donnes
caractre, bit, date/heure ainsi quavec les types numriques. Vous pourriez
rencontrer quelque chose comme ceci :

SELECT PRENOM, NOM


FROM CLIENTS
WHERE CLIENTS.NOM BETWEEN A AND Mzzz ;

Cet exemple retourne tous les clients dont le nom est dans la premire
moiti de lalphabet ( moins que ne commerciez avec M. Mzzzzza).

IN et NOT IN
Les prdicats IN et NOT IN permettent de vrifier si des valeurs
spcifiques (telles que OR, WA et ID) appartiennent des ensembles
particuliers de valeurs (en loccurrence, des tats des tats-Unis). Par
exemple, une de vos tables contient la liste des fournisseurs amricains de
consommables que votre socit achte rgulirement. Vous voulez
connatre les numros de tlphone des fournisseurs qui se trouvent dans le
Nord-Ouest Pacifique. Vous pouvez obtenir ces numros en utilisant des
prdicats de comparaison comme suit :

SELECT Societe, Telephone


FROM FOURNISSEURS
WHERE Etat = OR OR Etat = WA Or Etat =
ID ;

Vous pouvez galement faire appel au prdicat IN pour raliser la mme


tche :

SELECT Societe, Telephone


FROM FOURNISSEURS
WHERE Etat IN (OR, WA, ID) ;

Cette formulation est un peu plus compacte que la prcdente. La version


NOT IN de ce prdicat fonctionne de la mme manire. Supposez que
vous possdiez des succursales en Californie, en Arizona et au Nouveau-
Mexique, et que pour viter de payer des taxes vous cherchiez vous
adresser tous les fournisseurs sauf ceux qui rsident dans ces tats.
Utilisez alors la construction suivante :

SELECT Societe, Telephone


FROM FOURNISSEURS
WHERE Etat NOT IN (CA, AZ, NM) ;

Utiliser ainsi le mot cl IN est un peu plus conomique. Ce qui nest pas
forcment en soi un avantage dcisif. Vous pourriez tout aussi bien obtenir
le mme rsultat en utilisant les prdicats de comparaison, comme dans le
premier exemple de cette section.
Mme si lutilisation de IN ne reprsente pas une conomie considrable,
elle offre un autre avantage par rapport aux prdicats de comparaison. Votre
SGBD implmente probablement ces deux mthodes diffremment. De ce
fait, lune dentre elles peut sexcuter bien plus rapidement que lautre sur
votre systme. Bien entendu, vous allez opter pour la plus rapide.
Dailleurs, un SGBD dot dun bon optimisateur fera automatiquement le
choix de lefficacit, sans tenir compte de la syntaxe que vous aurez utilise
dans votre requte. Un test de comparaison des performances vous donnera
une ide sur la manire de travailler de votre SGBD. Si vous remarquez une
diffrence significative entre les temps dexcution des deux mthodes,
cest que la qualit de loptimisateur de votre SGBD peut tre remise en
question.
Le mot cl IN se rvle galement utile dans un autre cas. Si IN fait
partie dune sous-requte, il vous permet dextraire des informations
provenant de deux tables afin dobtenir des rsultats que vous ne pourriez
pas driver dune seule table. Le Chapitre 11 revient plus en dtail sur les
sous-requtes. Cependant, lexemple suivant montre comment utiliser le mot
cl IN dans une sous-requte.
Supposez que vous vouliez afficher tous les noms des clients qui ont achet
le produit F-117A dans les trente derniers jours. Les noms des clients sont
stocks dans la table CLIENTS et les transactions commerciales sont
mmorises dans la table TRANSACTIONS. Vous pouvez utiliser la
requte suivante :

SELECT NOM, PRENOM


FROM CLIENTS
WHERE CLIENT_ID IN
(SELECT CLIENT_ID
FROM TRANSACTIONS
WHERE PRODUIT_ID = F-117A
AND DATE_TRANS >= (DATE_COURANTE -30)) ;

Le SELECT interne qui porte sur la table TRANSACTIONS est inclus


dans le SELECT externe qui traite la table CLIENTS. Le SELECT interne
retourne les numros CLIENT_ID de tous les clients qui ont achet le
produit F-117A durant les trente derniers jours. Le SELECT externe affiche
les noms et prnoms des clients dont le CLIENT_ID a t rcupr par le
SELECT interne.

LIKE et NOT LIKE


Vous pouvez utiliser le prdicat LIKE pour procder une comparaison
partielle de deux chanes de caractre. Les comparaisons partielles sont
utiles si vous ne connaissez pas la forme exacte de ce que vous recherchez.
Vous pouvez aussi utiliser des comparaisons partielles pour rcuprer
plusieurs lignes qui contiennent des chanes similaires dans une colonne
donne.
SQL utilise deux caractres de substitution. Le signe pourcentage( %)
remplace nimporte quelle chane de caractres qui comprend zro ou
plusieurs caractres. Le trait de soulignement (_) se substitue un caractre
unique quelconque. Le Tableau 10.3 contient quelques exemples
dutilisation de LIKE.
Le prdicat NOT LIKE retourne toutes les lignes qui ne vrifient pas la
comparaison partielle, comme dans :

WHERE TELEPHONE NOT LIKE 503%

Cet exemple retourne toutes les lignes de la table dont le numro de


tlphone commence par quelque chose de diffrent de 503.

TABLEAU 10.3 Le prdicat LIKE de SQL.


Instruction Valeur retourne

WHERE WORD LIKE intern % interne


international
internet

WHERE WORD LIKE % paci % ocan pacifique


mouvement pacifique

WHERE WORD LIKE t_p_ tape


tapi
tipi
type

Il peut arriver que vous recherchiez une chane qui contienne elle-mme le
signe pourcentage ou un trait de soulignement. Dans ce cas, vous voudrez
que SQL interprte le signe pourcentage comme le signe % et non
comme un caractre de substitution. Pour ce faire, vous devrez saisir un
caractre dchappement juste avant le signe en question. Vous pouvez
utiliser nim
porte quel caractre comme caractre dchappement du moment quil
napparat pas dans la chane que vous testez. Par exemple :

SELECT CITATION
FROM BARTLETTS
WHERE CITATION LIKE 20#%
ESCAPE # ;

Le caractre % est prfix du signe dchappement # , si bien que


linstruction interprte ce symbole comme le signe % et non comme le
caractre de substitution. Vous pouvez traiter le trait de soulignement et le
caractre dchappement lui-mme de la mme manire. Ainsi la requte
prcdente pourrait renvoyer la citation suivante :
20% des commerciaux produisent 80% des rsultats

Elle retournerait aussi :

20%

SIMILAR
Le prdicat SIMILAR (introduit dans SQL:1999) permet aussi deffectuer
des comparaisons partielles, mais il est plus puissant que LIKE. Grce au
prdicat SIMILAR, vous pouvez comparer une chane de caractres une
expression rgulire. Supposez par exemple que vous deviez effectuer une
recherche dans la colonne SYSTEME_EXPLOITATION dune table de
compatibilit logicielle la recherche dune compatibilit avec Microsoft
Windows. Vous pourriez construire une clause WHERE comme suit :

WHERE SYSTEME_EXPLOITATION SIMILAR TO


(Windows (3.1|95|98|Millenium Edi-
tion|CE|NT|2000|XP)) ;

Ce prdicat retourne toutes les lignes qui contiennent lun des systmes
dexploitation de Microsoft.

NULL
Le prdicat NULL retourne toutes les lignes o la valeur de la colonne
slectionne est nulle. Dans la table ALIMENTS du Chapitre 8, la colonne
HYDRATECARBONE de plusieurs lignes contient une valeur nulle. Vous
pouvez rcuprer le nom des aliments correspondants en utilisant :

SELECT (ALIMENT)
FROM ALIMENTS
WHERE HYDRATECARBONE IS NULL ;

Cette requte retourne les valeurs suivantes :


Boeuf, hamburger allg
Poulet, allg
Opossum, rti
Porc, jambon

Comme vous vous y attendez, le mot cl NOT inverse le rsultat, comme


dans lexemple suivant :

SELECT (ALIMENT)
FROM ALIMENTS
WHERE HYDRATECARBONE IS NOT NULL ;

Cette requte renvoie toutes les lignes de la table, lexception des quatre
retournes par lexemple prcdent.
Linstruction HYDRATECARBONE IS NULL nest pas la mme que
HYDRATECARBONE = NULL. Supposez que dans la ligne courante de la
table ALIMENTS les champs HYDRATECARBONE et PROTEINES
soient nuls. Vous pourrez en conclure ce qui suit :
HYDRATECARBONE IS NULL est vrai.

PROTEINES IS NULL est vrai.

HYDRATECARBONE IS NULL AND PROTEINES IS NULL


est vrai.

HYDRATECARBONE = PROTEINES est inconnu.

HYDRATECARBONE = NULL est une expression illgale.

Lutilisation du mot cl NULL dans une comparaison na aucun sens, car,


dans ce cas, le rsultat de la comparaison est toujours inconnu.
Pourquoi HYDRATECARBONE = PROTEINES est-il inconnu, mme si
HYDRATECARBONE et PROTEINES ont la mme valeur nulle ? Parce
que NULL signifie simplement je ne sais pas . Si vous ne savez pas
quoi correspondent HYDRATECARBONE et PROTEINES, vous ne pouvez
pas savoir si ces deux valeurs sont identiques. Peut-tre que
HYDRATECARBONE vaut 37 et PROTEINES 14, ou peut-tre que
HYDRATECARBONE et PROTEINES valent chacune 93. Si vous ne savez
pas ce que sont ces deux valeurs, vous navez aucun moyen de dterminer si
elles sont ou non gales.

ALL, SOME, ANY


Il y a des centaines dannes, le philosophe grec Aristote a formul un
systme de logique qui est devenu le fondement dune bonne partie de la
pense occidentale. Lessence de cette logique repose sur lnonc de
prmisses que vous savez (ou supposez) tre vraies, prmisses auxquelles
vous appliquez des oprations valides pour arriver de nouvelles vrits.
Voici un exemple de cette procdure :

Prdicat 1 : Tous les Grecs sont humains.

Prdicat 2 : Tous les humains sont mortels.

Conclusion : Tous les Grecs sont mortels.

Autre exemple :

Prdicat 1 : Certains Grecs sont des femmes.

Prdicat 2 : Toutes les femmes sont des tres humains.

Conclusion : Certains Grecs sont des tres humains.

Le mme raisonnement logique pourrait tre formul dune manire un peu


diffrente :

Si quelques Grecs sont des femmes, et que toutes les

femmes sont des tres humains, alors quelques Grecs

sont des tres humains.

Le premier exemple utilise le quantificateur universel ALL (tous) dans les


deux prmisses, ce qui vous permet de procder une dduction gnrale
sur les Grecs dans la conclusion. Le deuxime exemple utilise le
quantificateur existentiel SOME (certains, quelques) dans la premire
prmisse, ce qui vous permet de procder une dduction sur un certain
nombre de Grecs dans la conclusion. Le troisime exemple (qui scrirait
en anglais if any Greeks...) utilise un quantificateur existentiel (ANY) qui est
un synonyme de SOME pour arriver la mme conclusion que le deuxime
exemple. Voyons comment ANY et SOME sont traits en SQL en passant
directement de la Grce aux tats-Unis.
Prenons lexemple de statistiques de base-ball. Le base-ball est un sport
trs prouvant, en particulier pour les lanceurs. Un lanceur doit lancer la
balle entre 90 et 150 fois lors dune partie, ce qui est trs fatigant. Cest
pourquoi le lanceur est souvent remplac par un autre joueur avant la fin de
la partie. Tenir le rle de lanceur pendant toute une partie est un vritable
exploit, quel que soit le rsultat du match.
Supposez que vous conserviez toutes les grandes parties dans lesquelles
tous les grands lanceurs ont jou. Dans une table, vous allez dresser la liste
des lanceurs de la Ligue amricaine, et dans une autre table celle des
lanceurs de la Ligue nationale. Chaque table contient pour un joueur son
nom, son prnom et le nombre de matches entiers auxquels il a particip.
Supposons maintenant que vous souteniez la thorie selon laquelle les
lanceurs de la Ligue amricaine jouent des parties entires plus souvent que
ceux de la Ligue nationale. Pour vrifier cette hypothse, vous allez
formuler la requte suivante :

SELECT NOM, PRENOM


FROM LIGUE_AMERICAINE
WHERE PARTIES_COMPLETES > ALL
(SELECT PARTIES_COMPLETES
FROM LIGUE_NATIONALE) ;

La sous-requte (SELECT interne) retourne une liste qui indique le nombre


de parties compltes auxquelles a particip chaque lanceur de la Ligue
nationale. La requte externe retourne ensuite le nom et le prnom des
lanceurs de la Ligue amricaine qui ont particip plus de parties
compltes que tous (ALL) les lanceurs de la Ligue nationale.
Regardez maintenant linstruction suivante :
SELECT NOM, PRENOM
FROM LIGUE_AMERICAINE
WHERE PARTIES_COMPLETES > ANY
(SELECT PARTIES_COMPLETES
FROM LIGUE_NATIONALE) ;

Dans ce cas, vous utilisez le quantificateur existentiel ANY, et non le


quantificateur universel ALL. La sous-requte (interne) est identique celle
de lexemple prcdent. Elle retourne nouveau la liste de toutes les
parties compltes auxquelles ont particip les lanceurs de la Ligue
nationale. La requte externe retourne le nom et le prnom de tous les
lanceurs de la Ligue amricaine qui ont particip plus de matches entiers
que nimporte quel lanceur de la Ligue nationale. Comme vous pouvez tre
virtuellement certain quau moins un des lanceurs de la Ligue nationale na
pas particip un match entier, le rsultat comprend probablement tous les
lanceurs de la Ligue amricaine qui ont ralis au moins une partie
complte.
Si vous remplacez le mot cl ANY par le mot cl quivalent SOME, le
rsultat est identique. Si lassertion au moins un lanceur de la Ligue
nationale na pas particip une partie complte est vrifie, il devient
exact de dire quelques lanceurs de la Ligue nationale nont pas particip
une partie complte .

EXISTS
Vous pouvez utiliser le prdicat EXISTS avec une sous-requte pour
dterminer si cette dernire retourne ou non des lignes. Si la sous-requte
retourne au moins une ligne, cest que le rsultat vrifie la condition
EXISTS. La requte externe est alors excute. Par exemple :

SELECT NOM, PRENOM


FROM CLIENTS
WHERE EXISTS
(SELECT DISTINCT CLIENT_ID
FROM VENTES
WHERE VENTES.CLIENT_ID =
CLIENTS.CLIENT_ID) ;

La table VENTES contient un enregistrement de toutes les ventes de la


socit. On y trouve le CLIENT_ID de chaque client ayant effectu un
achat ainsi que dautres informations pertinentes. La table CLIENTS
contient le nom et le prnom de chaque client, mais aucune information sur
des transactions spcifiques.
La sous-requte de lexemple prcdent renvoie une ligne pour chaque
client qui a effectu au moins un achat. La requte externe retourne le nom et
le prnom des clients qui ont effectu des achats rfrencs dans la table
VENTES.
EXISTS est lquivalent dune comparaison de COUNT avec zro,
comme le montre la requte suivante :

SELECT NOM, PRENOM


FROM CLIENTS
WHERE 0 <>
(SELECT COUNT (*)
FROM VENTES
WHERE VENTES.CLIENT_ID =CLIENTS.CLIENT_ID) ;

Pour chaque ligne qui contient un CLIENT_ID gal un CLIENT_ ID


de la table CLIENTS, cette instruction renvoie les colonnes NOM et
PRENOM de la table CLIENTS. En dautres termes, elle affiche le nom du
client qui a effectu lachat pour chaque transaction de la table VENTES.

UNIQUE
Tout comme pour EXISTS, vous pouvez utiliser le prdicat UNIQUE avec
une sous-requte. Mais alors quEXISTS est valu comme tant vrai si
et seulement si la sous-requte renvoie au moins une ligne, le prdicat
UNIQUE est valid si et seulement si la sous-requte ne retourne pas deux
lignes identiques. Autrement dit, UNIQUE nest vrai que quand toutes les
lignes fournies par la sous-requte sont uniques.
Prenons lexemple suivant :
SELECT NOM, PRENOM
FROM CLIENTS
WHERE UNIQUE
(SELECT CLIENT_ID FROM VENTES
WHERE VENTES.CLIENT_ID = CLIENTS.CLIENT_ID)
;

Cette instruction retrouve les noms de tous les clients pour lesquels la table
VENTES ne recense quune seule transaction. Notez bien que deux valeurs
nulles ne sont pas considres comme tant gales et sont donc uniques.
Lorsque le mot cl UNIQUE est appliqu une table de rsultat qui ne
contient que deux lignes nulles, le prdicat UNIQUE est valu comme
ayant la valeur True (vrai).

DISTINCT
Le prdicat DISTINCT est comparable UNIQUE, si ce nest quil ne
traite pas les valeurs nulles de la mme manire. Si toutes les valeurs de la
table rsultat sont UNIQUE, alors elles sont DISTINCT les unes des
autres. Cependant, le prdicat DISTINCT nest pas vrifi quand il est
appliqu une table rsultat qui ne contient que deux lignes nulles. Deux
valeurs nulles ne sont pas considres comme tant distinctes, tout en tant
quand mme uniques.
Cela peut sembler paradoxal, mais il ny a aucune raison cela. Dans
certains cas, vous voulez traiter deux valeurs nulles comme tant diffrentes
lune de lautre. Dans dautres circonstances, vous avez besoin de les
placer dans un mme sac, et donc de les considrer comme identiques. Avec
la premire situation, vous utiliserez le prdicat UNIQUE ; dans la
seconde, vous ferez appel au prdicat DISTINCT.

OVERLAPS
Le prdicat OVERLAPS permet de dterminer si deux intervalles de temps
se chevauchent. Il est utile pour viter par exemple des conflits demploi du
temps. Si deux intervalles se chevauchent, le prdicat est valu comme
tant vrai. Sinon, il nest pas valid.
Vous pouvez spcifier un intervalle de deux manires : soit laide dun
point de dpart et dun point final, soit partir dun point de dpart et dune
dure. Voici quelques exemples :

(TIME 2:55:00, INTERVAL 1 HOUR)


OVERLAPS
(TIME 3:30:00, INTERVAL 2 HOUR)

Lexemple prcdent renvoie True, car 3 heures 30 est moins dune heure
aprs 2 heures 55.

(TIME 9:00:00, TIME 9:30:00)


OVERLAPS
(TIME 9:29:00, TIME 9:31:00)

Lexemple prcdent renvoie True, car les deux intervalles se chevauchent


dune minute.

(TIME 9:00:00, TIME 10:00:00)


OVERLAPS
(TIME 10:15:00, INTERVAL 3 HOUR)

Lexemple prcdent renvoie False, car les deux intervalles ne se


recouvrent pas.

(TIME 9:00:00, TIME 9:30:00)


OVERLAPS
(TIME 9:30:00, TIME 9:35:00)

Cet exemple renvoie False, car mme si les deux intervalles sont
contigus, ils ne se chevauchent pas.

MATCH
Le respect de lintgrit rfrentielle, traite au Chapitre 5, implique de
maintenir la cohrence dune base de donnes qui contient plusieurs tables.
Vous pouvez perdre cette intgrit en ajoutant une table enfant une ligne
sans correspondance dans la table parent. Des problmes similaires se
posent si vous supprimez une ligne de la table parent alors quune ligne
correspondante existe dans la table enfant.
Supposons nouveau que vous ayez une table CLIENTS qui conserve la
trace de tous vos clients, et une table VENTES qui enregistre toutes les
transactions. Vous ne voulez videmment pas ajouter une ligne VENTES
tant que vous navez pas saisi dans la table CLIENTS les rfrences du
client qui a effectu un achat. De mme, vous ne voulez pas supprimer un
client sil a effectu un ou plusieurs achats mmoriss dans la table
VENTES. Avant deffectuer une opration dinsertion ou de suppression,
vous devrez donc vrifier quelle nengendre pas des problmes dintgrit.
Le prdicat MATCH peut effectuer un tel contrle.

Dans notre exemple, CLIENT_ID est la cl primaire de la table CLIENTS


et elle joue le rle dune cl trangre dans la table VENTES. Chaque ligne
de la table CLIENTS doit comporter un CLIENT_ID unique et non nul.
Par contre, CLIENT_ID nest pas unique dans la table VENTES, car un
client peut effectuer plusieurs achats. Cette situation ne pose pas de
problme et ne compromet pas lintgrit, car CLIENT_ID est ici une cl
trangre et non une cl primaire.
De mme, CLIENT_ID peut tre nul dans la table VENTES, car
quelquun peut entrer dans votre magasin, acheter quelque chose et partir
avant mme que vous ayez eu le temps de saisir son nom et son adresse dans
la table CLIENTS. Cette situation peut crer une ligne dans la table enfant
qui na pas de correspondance dans la table parent. Pour contourner ce
problme, il suffit de crer un client gnrique dans la table CLIENTS et de
lui attribuer tous les achats anonymes.
Supposez quun client entre dans votre magasin et prtende avoir achet un
F-117A Stealth Fighter le 18 mai 2006. Il a perdu son ticket de caisse, mais
il veut tout prix vous rendre lavion, car il est visible sur les radars
ennemis. Vous pouvez vrifier ses propos en recherchant une
correspondance dans votre base de donnes. En premier lieu, vous allez
rcuprer son CLIENT_ID dans la variable vclientid, puis vous
utiliserez la syntaxe suivante :
...WHERE (:vclientid, F-117A, 2006-05-18)
MATCH
(SELECT CLIENT_ID, PRODUIT_ID, DATE_VENTE
FROM VENTES)

Si une vente de F-117A existe pour ce client cette date, le prdicat


MATCH va renvoyer la valeur True. Vous allez devoir reprendre
lappareil dfectueux et rembourser le client. (Note : Si une des valeurs du
premier argument de MATCH est nulle, le prdicat est toujours vrifi.)

Les dveloppeurs de SQL ont ajout les prdicats MATCH et UNIQUE


pour la mme raison : ils permettent deffectuer des tests explicites afin de
vrifier lintgrit rfrentielle implicite et les contraintes UNIQUE.

La forme gnrale du prdicat MATCH est la suivante :

Valeur_ligne MATCH [UNIQUE] [SIMPLE] PARTIAL /


FULL]
Sous_requte

Les options UNIQUE, PARTIAL et FULL interviennent quand Va-


leur_ligne dsigne une ligne dont une ou plusieurs colonnes sont
nulles (voir le Chapitre 9 pour plus dinformations sur les expressions de
valeur de ligne). Les rgles rgissant le prdicat MATCH sont une copie
des rgles dintgrit rfrentielle correspondantes.

Les rgles dintgrit rfrentielle


et le prdicat MATCH
Les rgles dintgrit rfrentielle imposent que les valeurs dune colonne
dans une table correspondent celles dune ou aux colonnes de la premire
table comme la cl trangre, et aux colonnes de la seconde table comme
tant la cl primaire ou cl unique. Par exemple, vous pouvez dclarer la
colonne EMP_NODPT de la table EMPLOYE comme une cl trangre qui
rfrence la colonne NODEPT dans la table DEPT. Cela vous permet de
vous assurer que si vous enregistrez un employ dans la table EMPLOYE
comme travaillant au dpartement 123, une ligne dont la valeur NODEPT
est gale 123 apparatra dans la table DEPT.
Si la cl trangre et la cl primaire ne concernent quune seule colonne, la
situation est assez simple. Mais les deux cls sont souvent formes partir
de plusieurs colonnes. Par exemple, la valeur NODEPT peut ntre unique
que pour un seul endroit, si bien que pour identifier parfaitement une
colonne DEPT, vous devez spcifier la fois un LIEU et un NODEPT. Si les
bureaux de Boston et de Tampa ont tous deux un dpartement 123, ils
correspondront (Boston, 123) et (Tampa, 123). Dans ce cas, la
table EMPLOYE doit possder deux colonnes pour identifier un DEPT.
Nommez ces colonnes LIEU_EMP et NODEPT_EMP. Si un employ
travaille au dpartement 123 Boston, LIEU_EMP et NO-DEPT_EMP
vaudront respectivement Boston et 123. La dclaration trangre de
lemploy est alors la suivante :

FOREIGN KEY (LIEU_EMP, NODEPT_EMP)


REFERENCES DEPT (LIEU, NODEPT)

Tirer des conclusions valides de ltude de vos donnes peut devenir


extrmement problmatique si elles contiennent des valeurs nulles. Vous
allez parfois traiter des donnes qui contiennent des valeurs nulles dune
certaine faon, et dans dautres cas vous les traiterez dune autre manire.
Les mots cls UNIQUE, SIMPLE, PARTIAL et FULL sont autant de
manires de travailler sur des donnes qui contiennent des valeurs nulles. Si
vous ntes pas concern par cette question, sautez le reste de cette section
et passez directement la suivante, Connecteurs logiques . Sinon, lisez
attentivement les paragraphes suivants. Chaque entre de la liste prsente un
cas particulier de valeurs nulles et explique comment le prdicat MATCH
les gre.
Voici les scnarios qui illustrent les rgles rgissant les valeurs nulles et le
prdicat MATCH :
Les deux valeurs sont de mme nature : Si les valeurs
de LIEU_EMP et de NODEPT sont toutes deux non nulles
ou toutes deux nulles, les rgles dintgrit rfrentielle
sont les mmes que pour des cls bases sur une colonne
unique dont les valeurs sont nulles ou non nulles.

Une valeur est nulle et lautre pas : Si, par exemple,


LIEU_EMP est nulle et que NODEPT est non nulle, ou si
LIEU_ EMP est non nulle et NODEPT est nulle, vous avez
besoin de nouvelles rgles. Quelle rgle appliquer si vous
mettez jour la table EMPLOYE avec les valeurs de
LIEU_EMP et de NODEPT de (NULL 123) ou (Boston,
NULL) ? Six alternatives se prsentent : SIMPLE, PARTIAL
et FULL, chacune combine ou non au mot cl UNIQUE.

Le mot cl UNIQUE est prsent : Il spcifie quune


colonne correspondante dans la table rsultat de la sous-
requte doit tre unique pour que le prdicat soit valid.

Les deux composants de la valeur de R sont nuls : Le


prdicat MATCH est valid quel que soit le contenu de la
table rsultat de la sous-requte comparer.

Aucun des composants de la valeur de ligne R nest


nul, SIMPLE est spcifi, UNIQUE nest pas spcifi et
au moins une ligne de la table sous-requte
correspond R : le prdicat MATCH renvoie la valeur True.
Sinon, il retourne False.

Aucun des composants de la valeur de ligne R nest


nul, SIMPLE est spcifi, UNIQUE est spcifi et au
moins une ligne de la table rsultat de la sous-requte
est la fois UNIQUE et correspond R : le prdicat
MATCH renvoie la valeur True. Sinon, il retourne False.
Un composant de lexpression valeur de ligne R est nul
et SIMPLE est spcifi : Le prdicat MATCH est vrifi.

UNE RGLE DMOCRATIQUE

La version SQL-89 du standard spcifiait que la rgle UNIQUE tait la


rgle par dfaut sans que quiconque ait dbattu de possibles
alternatives. Au cours du dveloppement de la version SQL-92 du
standard, plusieurs propositions furent suggres. Certaines
personnes prfraient de loin les rgles PARTIAL et demandaient
ce quelles soient les uniques rgles. Elles estimaient que les rgles
UNIQUE de SQL-89 posaient dnormes problmes et souhaitaient
quelles soient considres comme un bogue et que les rgles
PARTIAL soient juges comme tant des corrections.

Dautres personnes penchaient pour les rgles UNIQUE, jugeant les


rgles PARTIAL obscures, sujettes erreurs et inefficaces. Dautres
encore souhaitaient sen tenir la discipline supplmentaire offerte
par les rgles FULL. Pour finir, les trois mots cls furent intgrs au
standard, si bien que lutilisateur peut choisir celui quil prfre.
SQL:1999 a ajout tout cela les rgles SIMPLE. Cette prolifration
rend la gestion des valeurs nulles tout sauf simple. Si SIMPLE,
PARTIAL ou FULL ne sont pas spcifies, les rgles SIMPLE sont
appliques.

Un composant quelconque de lexpression valeur de


ligne R nest pas nul, PARTIAL est spcifi, UNIQUE
nest pas spcifi, et les parties non nulles dau moins
une ligne de la table rsultat produite par la sous-
requte correspondent R : Le prdicat MATCH renvoie
la valeur True. Sinon, il retourne False.

Un composant quelconque de lexpression valeur de


ligne R nest pas nul, PARTIAL est spcifi, UNIQUE est
spcifi, et les parties non nulles de R correspondent
aux parties non nulles dau moins une ligne unique de
la table rsultat de la sous-requte : Le prdicat MATCH
renvoie la valeur True. Sinon, il retourne False.

Aucun des composants de la valeur de ligne R nest


nul, FULL est spcifi, UNIQUE nest pas spcifi, et au
moins une ligne de la table rsultat de la sous-requte
correspond R : Le prdicat MATCH renvoie la valeur
True. Sinon, il retourne False.

Aucun des composants de la valeur de ligne R nest


nul, FULL est spcifi, UNIQUE est spcifi, et au
moins une ligne de la table rsultat de la sous-requte
est la fois UNIQUE et correspond R : Le prdicat
MATCH renvoie la valeur True. Sinon, il retourne False.

Un composant quelconque de lexpression valeur de


ligne R est nul, et FULL est spcifi : Le prdicat MATCH
renvoie la valeur True. Sinon, il retourne False.

Connecteurs logiques
Comme les exemples prcdents lont dmontr, une seule condition nest
quelquefois pas suffisante pour rcuprer toutes les lignes que vous voulez
extraire dune table. Dans certains cas, ces lignes doivent remplir une ou
plusieurs conditions. Dans dautres situations, cela suffit simplement les
qualifier pour la partie suivante. Dans dautres situations encore, vous
voudrez peut-tre rcuprer uniquement les lignes qui ne remplissent pas
certaines conditions. Pour rpondre tous ces besoins, SQL propose les
connecteurs logiques AND, OR et NOT.

AND
Si lobtention dune ligne est soumise la validit conjointe de plusieurs
conditions, utilisez le connecteur logique AND. Par exemple :

SELECT NO_FACTURE, DATE_VENTE, VENDEUR,


TOTAL_VENTE
FROM VENTES
WHERE DATE_VENTE > =2006-05-15
AND DATE_VENTE <= 2006-05-21 ;

La clause WHERE doit remplir les deux conditions suivantes :


DATE_VENTE doit tre suprieur ou gal au 15 mai 2006.

DATE_VENTE doit tre infrieur ou gal au 21 mai 2006.

Seules les lignes qui correspondent des ventes effectues dans la semaine
du 15 mai 2006 remplissent les deux conditions. La requte ne retourne que
ces lignes.
Remarquez que le connecteur AND est strictement logique. Cette restriction
peut prter quelquefois confusion, car certaines personnes emploient le
mot et (AND) dans un contexte moins prcis. Par exemple, votre patron
vous dit : Je voudrais voir les rsultats des ventes de Dupont et
Nemours. Il a dit Dupont et Nemours ; par consquent, vous allez
certainement crire la requte SQL suivante :

SELECT *
FROM VENTES
WHERE VENDEUR = Dupont
AND VENDEUR =Nemours ;

Mais en fait votre patron avait une autre ide en tte :


SELECT *
FROM VENTES
WHERE VENDEUR IN (Dupont, Nemours) ;

La premire requte ne retournera rien, car aucune des ventes de la table


VENTES na t effectue la fois par Dupont et Nemours. La seconde
requte renverra les informations concernant les ventes effectues par
Dupont ou par Nemours, et cest ce que votre patron demandait
probablement.

OR
Si une ou plusieurs conditions doivent tre valides pour quune ligne soit
retourne comme rsultat, utilisez le connecteur logique OR. Par exemple :

SELECT NO_FACTURE, DATE_VENTE, VENDEUR,


TOTAL_VENTE
FROM VENDEUR
WHERE VENDEUR = Dupont
OR TOTAL_VENTE > 2000 ;

Cette requte retourne toutes les ventes faites par Dupont, quelle que soit
leur importance, ainsi que toutes les ventes de plus de 2 000 euros quelle
que soit la personne qui les a effectues.

NOT
Le connecteur de ngation NOT inverse le sens dune condition. Si une
condition doit normalement retourner une valeur vraie, ajouter NOT lui fait
renvoyer une valeur fausse. Si une condition renvoie normalement une
valeur fausse, ajouter NOT lui fait retourner une valeur vraie. Prenons
lexemple suivant :

SELECT NO_FACTURE, DATE_VENTE, VENDEUR


FROM VENTES
WHERE NOT (VENDEUR = Dupont) ;
Cette requte retourne les lignes de toutes les ventes que les vendeurs autres
que Dupont ont effectues.
Lorsque vous utilisez AND, OR et NOT, il peut arriver que la porte du
connecteur ne soit pas claire. Utilisez des parenthses pour vous assurer
que SQL lapplique au prdicat voulu. Dans lexemple prcdent, le
connecteur NOT sapplique au prdicat (VENDEUR= Dupont).

Clauses GROUP BY
Si vous rcuprez des lignes dune table en utilisant linstruction SELECT,
ces lignes vous sont retournes par dfaut dans lordre o elles apparaissent
dans la table source. Cet ordre na quelquefois aucun sens. La clause
GROUP BY vous permet alors de spcifier une ou plusieurs colonnes qui
dterminent lappartenance dune entre un groupe. Prcisons cela.
Supposez que vous soyez un responsable commercial et que vous souhaitiez
examiner les performances de votre force de vente pour une semaine
donne. Les informations produites doivent tre groupes par vendeur. Vous
pourriez simplement crire linstruction suivante :

SELECT NO_FACTURE, DATE_VENTE, VENDEUR,


TOTAL_VENTE
FROM VENTES ;

La rponse se prsenterait alors comme la Figure 10.1.


FIGURE 10.1 Rsultat des ventes dune priode donne.

Comme il ny a que peu de ventes, ce rsultat vous donne dj une certaine


ide du travail de vos reprsentants. Evidemment, dans la vraie vie, il y
aurait beaucoup plus de ventes (heureusement !), et il serait difficile de dire
si vos objectifs ont t atteints. Pour obtenir lanalyse dont vous avez
besoin, vous pouvez combiner une clause GROUP BY avec des fonctions
dagrgation (ou densemble) afin dafficher une vision quantitative des
performances du dpartement commercial. Linstruction suivante classe les
vendeurs selon la moyenne de leur chiffre daffaires :

SELECT VENDEUR, AVG(VENTE_TOTAL)


FROM VENTES
GROUP BY VENDEUR ;

Le rsultat de cette requte, excute dans Microsoft Access 2013, est


illustr la Figure 10.2. Vous pouvez lexcuter avec un autre gestionnaire
de base de donnes, mais le rsultat affich sera peut-tre diffrent :
lvidence, la moyenne des ventes de Dupont est considrablement
suprieure celle de ses collgues. Vous pouvez vrifier la vracit de ce
fait en demandant le total des ventes ralises par chaque commercial :

SELECT VENDEUR, SUM(VENTE_TOTAL)


FROM VENTES
GROUP BY VENDEUR ;

Ce qui affichera le rsultat reproduit la Figure 10.3 qui est cohrent avec
les informations prcdentes.
FIGURE 10.2 La moyenne des ventes de chaque vendeur.

FIGURE 10.3 Total des ventes de chaque vendeur.

Les clauses HAVING


Une clause HAVING est un filtre qui applique une restriction sur la table
virtuelle quune clause GROUP BY vient de crer. Tout comme une clause
WHERE exclut des lignes dune requte, une clause HAVING exclut des
groupes.
Reprenons lexemple de la section prcdente. Supposez que le responsable
commercial veuille se concentrer sur les performances des vendeurs autres
que celles de Dupont (vu ses rsultats, il doit constituer une classe lui tout
seul). Vous pouvez le lui permettre en ajoutant une clause HAVING la
requte prcdente, comme suit :

SELECT VENDEUR, SUM(VENTE_TOTAL)


FROM VENTES
GROUP BY VENDEUR ;
HAVING VENDEUR <> Dupont ;

Le rsultat sera le suivant :

VENDEUR Total
------- -----------
Nemours 12.48
Podoleck 12.00

Les clauses ORDER BY


Utilisez la clause ORDER BY pour afficher une table rsultat dans un ordre
alphabtique croissant ou dcroissant. Alors que la clause GROUP BY
runit les lignes par groupes classs par ordre alphabtique, la clause
ORDER BY trie pour sa part des lignes individuelles. Elle doit tre la
dernire clause que vous spcifiez dans une requte. Si cette requte
contient galement la clause GROUP BY, celle-ci provoque dabord un
regroupement des lignes, puis la clause ORDER BY trie ces lignes
lintrieur de chacun des groupes qui auront t forms. Si vous nutilisez
pas la clause GROUP BY, linstruction considre la table tout entire
comme un groupe. ORDER BY trie alors toutes ces lignes en fonction de la
colonne ou des colonnes que vous aurez spcifies.
Pour illustrer cela, considrez les donnes de la table VENTES. Elle
contient des colonnes pour NO_FACTURE, DATE_VENTE, VENDEUR et
TOTAL_VENTE. Si vous utilisez lexemple suivant, vous pourrez
visualiser les donnes VENTES selon un ordre arbitraire :

SELECT * FROM VENTES ;


Dans une certaine implmentation, lordre du tri peut tre celui dans lequel
vous avez insr des lignes dans la table. Dans dautres cas, le classement
sera celui de la dernire mise jour. Et si quelquun a physiquement
rorganis la base de donnes, le rsultat sera pratiquement imprvisible.
En rgle gnrale, vous devez spcifier lordre dans lequel vous voulez
visualiser les donnes. Vous pouvez par exemple trier les lignes en fonction
de la date de vente (DATE_VENTE) de la manire suivante :

SELECT * FROM VENTES ORDER BY DATE_VENTE ;

Cet exemple retourne toutes les lignes de la table VENTES groupes en


fonction de DATE_VENTE.

Les lignes dont les colonnes DATE_VENTE sont identiques seront tries
entre elles selon un ordre par dfaut qui dpend de limplmentation.
Cependant, vous pouvez spcifier vous-mme comment trier les lignes en
fonction de la date de vente, par exemple dans lordre des numros de
factures :

SELECT * FROM VENTES ORDER BY DATE_VENTE,


NO_FACTURE ;

Cette requte trie tout dabord les ventes par DATE_VENTE. Puis, pour
chaque date de vente, elle ordonne les rsultats par NO_ FACTURE.
Attention ! Ne confondez pas cet exemple avec la requte suivante :

SELECT* FROM VENTES ORDER BY NO_FACTURE,


DATE_VENTE ;

Cette requte trie dabord les ventes par NO_FACTURE, puis par
DATE_VENTE pour chaque NO_FACTURE diffrent. Ce qui ne produira
probablement pas le rsultat escompt, car il est peu vraisemblable quune
seule facture comporte plusieurs dates.
La requte suivante est un autre exemple de la manire dont SQL peut
retourner les donnes :

SELECT* FROM VENTES ORDER BY VENDEUR, DATE_VENTE


;
Cet exemple trie par vendeur, puis par date de vente. Une fois les donnes
visualises dans cet ordre, vous pouvez linverser de la manire suivante :

SELECT * FROM VENTES ORDER BY DATE_VENTE, VENDEUR


;

Cet exemple trie les lignes selon DATE_VENTE, puis selon la colonne
VENDEUR.
Tous ces exemples de tri se font par dfaut en ordre croissant (ASC). Le
dernier SELECT classe tout dabord les VENTES en commenant par les
plus rcentes, puis, pour une date donne, affiche les VENTES pour
Albert avant Bernard. Si vous prfrez un ordre dcroissant (DESC),
vous pouvez le spcifier pour une ou plusieurs colonnes de tri de la manire
suivante :

SELECT *FROM VENTES


ORDER BY DATE_VENTE DESC, VENDEUR ASC ;

Cet exemple spcifie un ordre dcroissant pour les dates de vente (les plus
rcentes tant donc affiches en premier), puis un ordre croissant pour les
vendeurs, ce qui les classe par ordre alphabtique.

Les limites de Fetch


Quand on a chang le standard ISO/IEC SQL, on a dvelopp ses capacits
de langage, ce qui est en soi une bonne chose. Mais il arrive quelquefois
que de tels changements ne permettent pas danticiper toutes les
consquences possibles. Cest ce qui sest produit avec les limitations de
FETCH dans SQL:2008.
Lide de limiter FETCH est due au fait quune instruction SELECT peut
retourner un nombre indtermin de lignes, alors que quelquefois seules les
trois ou les dix premires lignes sont intressantes. Cest dans cet esprit que
lon a ajout dans SQL: : 2008 la syntaxe suivante :

SELECT Vendeur, AVG(TOTAL_VENTE)


FROM VENTES
GROUP BY Vendeur
ORDER BY AVG(TOTAL_VENTE) DESC
FETCH FIRST 3 ROWS ONLY;

Tout va bien. Vous obtenez ainsi les noms des trois premiers vendeurs qui
ont vendu des produits trs chers. Mais il reste un petit problme : que faire
si ces trois vendeurs ont le mme total de ventes ? Seul lun de ces trois
noms sera retourn. Lequel ? Cest indtermin.
Lindtermination nest pas acceptable pour toute personne qui est charg
dune base de donnes digne de son nom, cest la raison pour laquelle on a
corrig la syntaxe dans SQL:2011. On a inclus des liens de cette manire :

SELECT Vendeur, AVG(TOTAL_VENTE)


FROM VENTES
GROUP BY Vendeur
ORDER BY AVG(TOTAL_VENTE) DESC
FETCH FIRST 3 ROWS WITH TIES;

prsent, le rsultat est compltement dtermin : sil y a un lien, vous


obtiendrez toutes les lignes lies. Comme avant, si vous vous arrtez au
modificateur WITH TIES, le rsultat sera indtermin.

Mais SQL:2011 apporte aussi deux autres amliorations FETCH limit.


La premire est que les pourcentages sont traits comme un nombre
spcifique de lignes. Considrez cet exemple :

SELECT Vendeur, AVG(TOTAL_VENTE)


FROM VENTES
GROUP BY Vendeur
ORDER BY AVG(TOTAL_VENTE) DESC
FETCH FIRST 10 PERCENT ROWS ONLY;

Un problme de liens peut apparatre lorsque lon traite des pourcentages


comme de simples numros denregistrements, cest pourquoi la syntaxe
WITH TIES est ici utilise. Vous pouvez ou non inclure des liens, tout
dpend de ce que vous souhaitez faire dans une situation donne.
Deuximement, supposez que vous ne souhaitiez pas obtenir les trois
premiers ou les dix premiers pourcentages, mais le second ou le troisime
pourcentage. Peut-tre voulez-vous passer directement un point qui vous
semble plus intressant. SQL:2011 vous permet aussi de traiter ce type de
cas. Considrez le code ci-dessous :

SELECT Vendeur, AVG(TOTAL_VENTE)


FROM VENTES
GROUP BY Vendeur
ORDER BY AVG(TOTAL_VENTE) DESC
OFFSET 3 ROWS
FETCH NEXT 3 ROWS ONLY;

Le mot cl OFFSET indique le nombre de lignes sauter avant de


rcuprer. Le mot cl NEXT spcifie que les lignes rcuprer sont celles
qui se situent immdiatement aprs loffset. Puis le nom du vendeur qui a la
quatrime, cinquime ou sixime moyenne la plus leve de ventes est
retourn. Comme vous pouvez le constater, sans la syntaxe WITH TIES, il
y aurait encore un problme dindtermination. Si le troisime ou quatrime
ou cinquime vendeur sont lis, est indtermin lequel est trait dans le
premier lot, lequel dans le second lot.
Il vaut mieux viter dutiliser la capacit de limitation de FETCH, car elle
risque de retourner des rsultats qui induisent en erreur.

Regarder par une fentre pour


crer un jeu de rsultats
Les fentres et les fonctions de fentre ont t dabord introduites dans
SQL:1999. Grce une fentre, lutilisateur peut partitionner un ensemble
de donnes, ventuellement classer les lignes par partitions et spcifier une
suite de lignes (le cadre de la fentre) qui est associe une ligne donne.
Le cadre de la fentre de la ligne R est un sous-ensemble de la partition
contenant R. Par exemple, le cadre de la fentre peut se composer de toutes
les lignes du dbut la fin de la partition y compris R, en fonction de la
manire dont sont classes les lignes dans la partition.
Une fonction de fentre calcule une valeur de la ligne R en fonction des
lignes dans le cadre de R.

Par exemple, supposons que vous ayez une table VENTES qui comporte
des colonnes CLIENT_ID, NO_FACTURE et TOTAL_VENTE. Le
responsable du magasin veut connatre le montant total des achats qua fait
chaque client sur un nombre spcifique de factures. Vous pouvez obtenir ces
informations laide du code suivant :

SELECT CLIENT_ID, NO_FACTURE,


SUM (TOTAL_VENTE) OVER
( PARTITION BY CLIENT_ID
ORDER BY NO_FACTURE
ROWS BETWEEN
UNBOUNDED PRECEDING
AND CURRENT ROW )
FROM VENTES;

La clause OVER dtermine le nombre de lignes de la requte qui sont


partitionnes avant le traitement. Ici cest la fonction SUM. Une partition est
alloue chaque client. Chaque partition a une liste de numros de facture,
chacune associe la somme des valeurs de TOTAL_VENTE dune range
spcifique de ligne, pour chaque client.
Dans SQL:2011 la fonctionnalit originale de fentre a connu dimportantes
amliorations, notamment avec lapparition de nouveaux mots cls.

Partitionner une fentre en


paquets avec NTILE
La fonction de fentre NTILE distribue les lignes dune partition trie dans
un nombre entier positif de groupes. Les groupes sont numrots partir de
un n. Si le nombre de lignes dans une partition m nest pas divisible par n,
alors une fois que la fonction NTILE a distribu un nombre chaque
groupe, le reste m/n, appel r, est rattribu au premier groupe r, le rendant
ainsi un groupe plus grand que les autres.
Supposez que vous souhaitiez classer vos employs par salaire, en les
classant dans cinq groupes de salaire du plus haut au plus bas. Vous le ferez
avec le code suivant :

SELECT PRENOM, NOM, NTILE (5)


OVER (ORDER BY SALAIRE DESC)
AS BUCKET
FROM EMPLOYE;

Si vous avez 11 employs, chaque groupe comptera deux employs,


lexception du premier, qui en comportera trois. Le premier groupe sera
celui des trois employs les mieux pays, et le cinquime groupe aura les
deux employs les moins bien pays.

Naviguer dans une fentre


SQL:2011 comporte cinq fonctions de fentre qui valuent une expression
dans une ligne R2 qui se trouve quelque part dans le cadre de la fentre de
la ligne actuelle R1. Ces fonctions sont LAG, LEAD, NTH_VALUE,
FIRST_VALUE et LAST_VALUE.
Ces fonctions vous permettent de retrouver des informations dans des lignes
spcifies qui sont lintrieur du cadre de la fentre de la ligne actuelle.

Fonction LAG
La fonction LAG vous permet de rcuprer des informations de la ligne
actuelle de la fentre que vous examinez ainsi que des informations dune
autre ligne que vous avez spcifie et qui prcde la ligne courante.
Supposez que vous disposiez dune table qui enregistre les ventes totales de
chaque jour de lanne en cours. Vous pourrez ainsi connatre le montant
total des ventes par jour et comparer le montant des ventes daujourdhui
celui dhier par exemple. Vous le ferez en utilisant la fonction LAG comme
suit :
SELECT TOTAL_VENTE AS VENTE_DU_JOUR,
LAG (TOTAL_VETE) OVER
(ORDER BY DATE_VENTE) AS PrevDaySale
FROM TOTAL_JOUR;

Pour chaque ligne de TOTAL_JOUR, la requte retournera une ligne listant


la ligne du total du jour et celle qui calcule le total de la veille. Loffset par
dfaut est 1, cest la raison pour laquelle le rsultat de la veille est
retourn et non celui dun autre jour.
Pour comparer les ventes du jour celles dune semaine avant, utilisez le
code suivant :

SELECT TOTAL_VENTE AS VENTE_DU_JOUR,


LAG (TOTAL_VENTE, 7) OVER
(ORDER BY DATE_VENTE) AS PrevDaySale
FROM TOTAL_JOUR;

Les sept premires lignes dans le cadre de la fentre nauront pas de


prcdent antrieur une semaine. La rponse par dfaut dans ce cas est de
retourner un rsultat null pour PrevDaySale. Si vous souhaitez faire
apparatre un rsultat autre que null, spcifiez que vous voulez voir
retourner la valeur 0, par exemple, et non la valeur null comme suit :

SELECT TOTAL_VENTE AS VENTE_DU_JOUR,


LAG (TOTAL_VENTE, 7, 0) OVER
(ORDER BY DATE_VENTE) AS PrevDaySale
FROM TOTAL_JOUR;

Par dfaut, ici ne sont comptabilises que les lignes qui sont trs grandes,
comme cest le cas de TOTAL_VENTE, qui peut contenir une valeur nulle.
Si vous voulez sauter toutes les lignes qui ont une valeur nulle et ne prendre
en compte que celles qui ont une valeur relle, ajoutez le mot cl IGNORE
NULLS comme dans cette variante de lexemple prcdent :

SELECT TOTAL_VENTE AS VENTE_DU_JOUR,


LAG (TOTAL_VENTE, 7, 0) IGNORE NULLS
OVER (ORDER BY DATE_VENTE) AS PrevDaySale
FROM TOTAL_JOUR;

Fonction LEAD
La fonction LEAD fonctionne exactement comme la fonction LAG, except
quelle nexamine pas la ligne prcdente, mais la suivante. En voici un
exemple ;

SELECT TOTAL_VENTE AS VENTE_DU_JOUR,


LEAD (TOTAL_VENTE, 7, 0) IGNORE NULLS
OVER (ORDER BY DATE_VENTE) AS NextDaySale
FROM TOTAL_JOUR;

Fonction NTH_VALUE
La fonction NTH_VALUE est semblable aux fonctions LAG et LEAD,
lexception prs quelle nvalue pas une expression dans une ligne
prcdente ou suivante de la ligne en cours, mais quelle value une
expression dans une ligne qui est un offset spcifi de la premire ou
dernire ligne dans le cadre de la fentre.
En voici un exemple :

SELECT TOTAL_VENTE AS CHOIX_VENTE,


NTH_VALUE (TOTAL_VENTE, 2)
FROM FIRST
IGNORE NULLS
OVER (ORDER BY DATE_VENTE)
ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING )
AS PREMIERE_VENTE
FROM TOTAL_JOUR;

Dans cet exemple, PREMIERE_VENTE est value ainsi :


Le cadre de la fentre associ la ligne en cours est
form. Ce qui inclut les dix lignes prcdentes et suivantes.
TOTAL_VENTE est valu dans chaque ligne du cadre de
la fentre.

IGNORE NULLS est spcifi, toutes les lignes contenant


une valeur nulle pour TOTAL_VENTE sont sautes.

On commence aprs la premire valeur qui reste une fois


les valeurs nulles pour TOTAL_VENTE exclues, on avance
de deux lignes la fois parce que FROM FIRST tait
spcifi.

La valeur PREMIERE_VENTE est la valeur de TOTAL_VENTE dans une


ligne spcifie.
Si vous ne voulez pas sauter les lignes qui ont une valeur nulle pour
TOTAL_VENTE, spcifiez RESPECT NULLS la place de IGNORE
NULLS. La fonction NTH_VALUE fonctionne de la mme manire, que
vous prcisiez FROM LAST ou FROM FIRST, sauf si vous comptez
rebours partir du dernier enregistrement et non partir du premier
enregistrement. Le nombre de lignes compter est toujours positif, que vous
comptiez rebours ou en avant.

Fonctions FIRST_VALUE et LAST_VALUE


Les fonctions FIRST_VALUE et LAST_VALUE sont des cas spciaux de
la fonction NTH_VALUE ; FIRST_VALUE est lquivalent de
NTH_VALUE o FROM FIRST est spcifi et loffset vaut 0 (zro).
LAST_VALUE est lquivalent de NTH_VALUE o LAST_VALUE est
spcifi et loffset vaut 0. Pour les deux fonctions, vous avez le choix de
respecter ou dignorer les valeurs nulles.

Imbriquer des fonctions de fentre


Imbriquer une fonction dans une autre peut tre quelquefois la solution dont
vous avez besoin. Dans SQL:2011, cette possibilit a t ajoute et tendue
aux fonctions de fentre.
Un investisseur cherche dterminer si cest le bon moment dacheter un
stock particulier. Afin de bien arrter son choix, il dcide de comparer le
prix du stock actuel aux prix des 100 derniers fournisseurs qui lont vendu.
Il se demande de combien est moins cher le prix des 100 fournisseurs qui
lont vendu par rapport au prix actuel. Pour avoir une rponse satisfaisante,
il effectue la requte suivante :

SELECT DATE_VENTE,
SUM ( CASE WHEN PRIX_VENTE <
VALUE OF (PRIX_VENTE AT CURRENT ROW)
THEN 1 ELSE 0 )
OVER (ORDER BY DATE_VENTE
ROWS BETWEEN 100 PRECEDING AND CURRENT ROW )
FROM STOCK_VENTE;

La fentre inclut les 100 lignes prcdant la ligne en cours, lesquelles


correspondent aux 100 ventes immdiatement antrieures au moment actuel.
chaque fois quune ligne o la valeur de PRIX_VENTE est infrieure au
prix de vente actuel, on ajoute 1 la somme. Le rsultat final est un nombre
qui indique le nombre de ventes parmi les 100 prcdentes qui ont un prix
infrieur au prix actuel.

valuer un groupe de lignes


Il peut arriver que les cls de tri que vous avez choisies pour classer une
partition peuvent avoir des doubles. Pour valuer toutes les lignes qui ont la
mme cl de tri sous forme de groupe, utilisez loption GROUPS. Vous
pourrez ainsi compter les groupes de lignes qui ont une cl de tri identique.
En voici un exemple :

SELECT CLIENT_ID, DATE_VENTE,


SUM (TOTAL_FACTURE) OVER
( PARTITION BY CLIENT_ID
ORDER BY DATE_VENTE
GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING )
FROM CLIENTS;

Le cadre de fentre de cet exemple se compose de cinq groupes de lignes :


deux groupes avant le groupe contenant la ligne actuelle, le groupe de la
ligne actuelle, et deux groupes qui suivent le groupe de la ligne actuelle. Les
lignes de chaque groupe ont la mme DATE_VENTE et la DATE_VENTE
associe chaque groupe est diffrente des valeurs de DATE_VENTE des
autres groupes.
Chapitre 11
Les oprateurs relationnels
DANS CE CHAPITRE :
Combiner des tables de mme structure.

Combiner des tables de structures diffrentes.

Rcuprer des donnes pertinentes depuis plusieurs tables.

S
QL est un langage de requtes pour les bases de donnes relationnelles.
Dans les prcdents chapitres, jai prsent des bases de donnes
lmentaires et, dans la plupart des cas, mes exemples ne faisaient
rfrence qu une seule table. Il est temps de mettre un peu de relationnel
dans la base de donnes ! Aprs tout, une base est qualifie de relationnelle
quand elle contient plusieurs tables lies entre elles.
Comme une base de donnes relationnelle contient un ensemble de tables,
une requte extrait gnralement des informations partir de plusieurs
tables. SQL dispose doprateurs qui permettent de combiner des donnes
issues de plusieurs sources au sein dune seule table rsultat. Ce sont les
oprateurs UNION, INTERSECT et EXCEPT ainsi que la famille des
oprateurs JOIN. Chacun dentre eux combine des donnes provenant de
plusieurs tables dune manire diffrente.

UNION
Loprateur UNION est limplmentation SQL de loprateur union de
lalgbre relationnelle. Il vous permet dextraire des informations de deux
ou plusieurs tables de mme structure. De mme structure signifie que :
Les tables doivent toutes avoir le mme nombre de
colonnes.

Les colonnes correspondantes doivent possder des


donnes de mme type et de mme longueur.

Lorsque ces conditions sont satisfaites, les tables sont dclares


compatibles pour une union. Lunion de deux tables retourne toutes les
lignes de chaque table et limine les doublons.
Supposons que vous criez une base de donnes pour grer des statistiques
sur le base-ball (comme celle du Chapitre 12). Elle contient deux tables
nommes AMERICAINE et NATIONALE qui sont compatibles pour une
union. Toutes deux ont trois colonnes, et les colonnes correspondantes ont
toujours le mme type. De plus, les colonnes correspondantes portent des
noms identiques (mme si cette condition nest pas requise pour que ces
tables soient dclares compatibles pour une union).
NATIONALE contient les noms des lanceurs de la Ligue nationale ainsi que
le nombre de parties compltes auxquelles ils ont particip. AMERICAINE
contient les mmes informations, mais sur les lanceurs de la Ligue
amricaine. Lunion des deux tables est une table qui contient toutes les
lignes de la premire table et toutes les lignes de la seconde.

SELECT * FROM NATIONALE ;


PRENOM NOM PARTIES_COMPLETES
---------- --------- ------------------
Sal Maglie 11
Don Newcombe 9
Sandy Koufax 13
Don Drysdale 12

SELECT * FROM AMERICAINE ;

PRENOM NOM PARTIES_COMPLETES


---------- --------- ------------------
Whitey Ford 12
Don Larson 10
Bob Turley 8
Allie Reynolds 14
SELECT * FROM NATIONALE
UNION

SELECT * FROM AMERICAINE ;

PRENOM NOM PARTIES_COMPLETES


---------- --------- ------------------
Allie Reynolds 14
Bob Turley 8
Don Drysdale 12
Don Larson 10
Don Newcombe 9
Sal Maglie 11
Sandy Koufax 13
Whitey Ford 12

La variante UNION DISTINCT fonctionne exactement de la mme


manire. Avec ou sans la prcision DISTINCT, loprateur UNION limine
par dfaut toutes les lignes en double du jeu de rsultat.
Jai utilis un astrisque (*) pour adresser plus rapidement toutes les
colonnes dune table. Cette notation peut vous poser des problmes quand
vous utilisez des oprateurs relationnels dans du SQL incorpor ou dans des
modules. Que va-t-il se passer si vous ajoutez une ou plusieurs colonnes
une table et pas lautre, ou si vous ajoutez des colonnes diffrentes aux
deux tables ? Simplement, elles ne seront plus compatibles pour une union.
Votre programme sera donc invalide lors de sa prochaine compilation.
Mme si deux colonnes identiques sont ajoutes aux deux tables de sorte
quelles restent compatibles pour une union, votre programme ne sera
vraisemblablement pas inform de lexistence de ces nouvelles donnes.
Par consquent, il vaut toujours mieux dresser la liste explicite des
colonnes que vous comptez utiliser plutt que de se reposer sur le raccourci
*. Mais lorsque vous vous contentez de saisir des requtes SQL depuis la
console, lutilisation de lastrisque ne pose probablement pas de
problme. Si la requte choue, vous pouvez en effet afficher rapidement la
structure de la table rsultat afin de vrifier sil y a ou non compatibilit
pour lunion.

Lopration UNION ALL


Comme je lai indiqu plus haut, lopration UNION limine normalement
les doublons, ce qui est la plupart du temps la bonne mthode. Cependant, il
peut arriver que vous dsiriez conserver ces lignes redondantes. Vous
utiliserez alors UNION ALL.
Pour reprendre lexemple prcdent, supposons que Bob Turley soit pass
en cours de saison de lquipe New York Yankees de la Ligue amricaine
lquipe Brooklyn Dodgers de la Ligue nationale. Supposons ensuite quil
ait jou huit parties compltes pour chaque quipe lors de cette saison.
Lutilisation dUNION liminera systmatiquement lune des deux lignes
concernant Turley. Mme sil semble quil nait jou que huit parties
compltes lors de cette saison, il a en ralit fait 16 matches en entier. La
requte suivante produira le bon rsultat :

SELECT * FROM NATIONALE


UNION ALL
SELECT * FROM AMERICAINE

Vous pouvez parfois former lunion de deux tables, mme si elles ne sont
normalement pas compatibles pour cela. Si les colonnes que vous dsirez
avoir dans la table rsultat sont prsentes, et si elles sont compatibles dans
les deux tables, vous avez la possibilit deffectuer une opration UNION
CORRESPONDING. Seules les colonnes que vous spcifiez alors sont
utilises pour raliser lunion, et ce sont aussi les seules qui apparaissent
dans la table rsultat.

Lopration
Les statisticiens du base-ball conservent des statistiques trs diffrentes sur
les lanceurs et sur les autres joueurs. Mais dans les deux cas, ils conservent
le nom et le prnom de chaque sportif. Bien que ces tables soient
incompatibles, vous pouvez procder leur union pour ne rcuprer que les
noms, les prnoms, et, disons, les erreurs commises par les uns et par les
autres :

SELECT *
FROM JOUEURS
UNION CORRESPONDING
(PRENOM, NOM, ERREURS)
SELECT *
FROM LANCEURS;

La table rsultante va afficher les noms, prnoms et nombre derreurs


commises par tous les joueurs, lanceurs ou non. Comme pour une simple
UNION, tous les doublons sont limins. Dans lhypothse o un joueur
aurait chang de poste en cours de saison, une partie des statistiques qui le
concernent seraient donc perdues. Pour viter ce problme, vous disposez
de la variante UNION ALL CORRESPONDING.
Chaque nom de colonne cit dans la liste qui suit le mot cl
CORRESPONDING doit exister dans les deux tables. Si vous omettez cette
liste, toutes les colonnes qui apparaissent dans les deux tables seront
utilises. Mais cette liste implicite peut changer si des colonnes sont
ajoutes ultrieurement lune ou aux deux tables. Cest pourquoi il vaut
toujours mieux dresser une liste explicite des noms des colonnes que vous
souhaitez utiliser.

INTERSECT
Loprateur UNION produit une table rsultat qui contient toutes les lignes
qui apparaissent dans nimporte laquelle des tables sources. Si vous ne
voulez faire apparatre que les lignes qui apparaissent dans toutes les tables
sources, vous pouvez utiliser loprateur INTERSECT, qui est
limplmentation SQL de loprateur intersection de lalgbre relationnelle.
Reprenons lexemple prcdent :

SELECT * FROM NATIONALE;


PRENOM NOM PARTIES_COMPLETES
---------- --------- -----------------
Sal Maglie 11
Don Newcombe 9
Sandy Koufax 13
Don Drysdale 12
Bob Turley 8

SELECT * FROM AMERICAINE;


PRENOM NOM PARTIES_COMPLETES
---------- --------- -----------------
Whitey Ford 12
Don Larson 10
Bob Turley 8
Allie Reynolds 14

Avec linstruction qui suit, seules les lignes apparaissant dans toutes les
tables sources figurent dans la table rsultat :

SELECT *
FROM NATIONALE
INTERSECT
SELECT *
FROM AMERICAINE;

PRENOM NOM PARTIES_COMPLETES


---------- --------- -----------------
Bob Turley 8

La table rsultat nous indique que Bob Turley est le seul lanceur avoir
particip au mme nombre de parties compltes dans les deux ligues. Note :
comme avec UNION, INTERSECT DISTINCT retourne le mme rsultat
que loprateur INTERSECT utilis seul. Dans cet exemple, seule la ligne
mentionnant Bob Turley est retourne.
Les mots cls ALL et CORRESPONDING fonctionnent avec un oprateur
INTERSECT de la mme manire quavec UNION. Si vous utilisez ALL,
les lignes redondantes apparaissent dans la table rsultat. Si vous utilisez
CORRESPONDING, les tables dont vous calculez lintersection nont pas
besoin dtre compatibles pour lunion, mme si les colonnes
correspondantes doivent tre du mme type et de la mme longueur.
Voici ce que vous obtiendrez avec INTERSECT ALL :

SELECT *
FROM NATIONAL
INTERSECT ALL
SELECT *
FROM AMERICAINE;

PRENOM NOM PARTIES_COMPLETESs


--------- -------- -------------
Bob Turley 8
Bob Turley 8

Prenons un autre exemple. Une municipalit gre la liste des tlphones


portables qui quipent ses lus, ses officiers de police, ses pompiers, ses
chefs de service et autres employs municipaux. Une table appele
TELVILLE contient des informations sur tous les appareils en service. Une
autre table nomme HS, dont la structure est identique, contient les donnes
sur tous les portables qui, pour une raison ou une autre, ont t dclars
inutilisables. Aucun tlphone ne devrait figurer simultanment dans les
deux tables. Vous pouvez utiliser un oprateur INTERSECT pour vrifier
que cette rgle est bien applique :

SELECT *
FROM TELVILLE
INTERSECT CORRESPONDING (TELEPHONE_ID)
SELECT *
FROM HS ;

Si la table rsultat contient des lignes, vous savez que vous avez un
problme. Car cela signifie quun tlphone est la fois en service et hors
service, ce qui est incohrent. Une fois le dfaut localis, vous pouvez
corriger la situation en excutant une opration DELETE sur une des tables
afin de restaurer lintgrit de la base.

EXCEPT
Loprateur UNION traite deux tables sources et retourne toutes les lignes
qui apparaissent dans les deux tables. Loprateur INTERSECT retourne
toutes les lignes qui apparaissent la fois dans les deux tables. Par
contraste, loprateur EXCEPT (ou EXCEPT DISTINCT) retourne toutes
les lignes qui apparaissent dans la premire table, mais pas dans la
seconde.
Reprenons lexemple des tlphones portables de la base de donnes
municipale. Certains appareils avaient t dclars hors service et
retourns chez le fabricant pour rparation. Ils sont maintenant rentrs et
remis en service. La table TELVILLE a t mise jour pour y rintgrer les
tlphones rpars. Mais, pour une raison quelconque, ces appareils nont
pas t supprims de la table HS, alors quils auraient d ltre. Vous
pouvez afficher les numros TELEPHONE_ID de la table HS tout en
liminant les rfrences des tlphones remis en service laide de
loprateur EXCEPT :

SELECT *
FROM HS
EXCEPT CORRESPONDING (TELEPHONE_ID)
SELECT *
FROM TELVILLE;

Cette requte retourne toutes les lignes de la table HS pour lesquelles


TELEPHONE_ID est aussi prsent dans la table TELVILLE.

Les oprateurs JOIN


Les oprations UNION, INTERSECT et EXCEPT sont trs utiles pour
manipuler plusieurs tables qui sont compatibles pour une union. Mais vous
allez souvent devoir extraire des donnes de tables qui ont bien peu de
choses en commun. Les jointures (JOIN) sont des oprateurs relationnels
trs puissants qui permettent de combiner des donnes extraites de plusieurs
sources disparates afin de former une table rsultat. SQL dispose de
plusieurs types de jointures. Toute la difficult consiste choisir celui qui
correspond le mieux au rsultat que vous souhaitez obtenir. Nous allons
tenter de nous y retrouver dans les sections qui suivent.

Jointure lmentaire
Toute requte qui porte sur plusieurs tables est un type de jointure. Les
tables sources sont jointes en ce sens que la table rsultat contient des
informations extraites de toutes les tables sources. Le plus simple des JOIN
est un SELECT sans clause WHERE appliqu deux tables. Chaque ligne
de la premire table est jointe chaque ligne de la seconde table. Le
rsultat est le produit cartsien des deux tables sources. Le nombre de
lignes que contient la table rsultat est gal au nombre de lignes de la
premire table source multipli par le nombre de lignes de la seconde table
source.
Imaginons par exemple que vous soyez le DRH dune socit et quune
partie de votre travail consiste grer des informations sur les membres du
personnel. La plupart des donnes qui concernent un employ, comme
ladresse de son domicile et son numro de tlphone, ne sont pas
particulirement confidentielles. Mais dautres donnes, comme son salaire,
ne doivent tre consultes que par les personnes autorises. Pour protger
ces informations, vous allez les stocker dans une table distincte dont laccs
est protg par un mot de passe. Considrez ces deux tables :

EMPLOYES INDEMNITES
-------- ----------
EMP_ID EMPLOYE
PRENOM SALAIRE
NOM PRIMES
VILLE
TELEPHONE

Remplissons les tables avec ces exemples :


EMP_ID PRENOM NOM VILLE TELEPHONE
------ ------ --- ------ ---------
1 Whitey Ford Orange 555-1001
2 Don Larson Newark 555-3221
3 Sal Maglie Nutley 555-6905
4 Bob Turley Passaic 555-8908
EMPLOYE SALAIRE PRIMES
------- -------- ------
1 33000 10000
2 18000 2000
3 24000 5000
4 22000 7000

Crez maintenant une table rsultat laide de la requte suivante :

SELECT *
FROM EMPLOYES, INDEMNITES ;

Ce qui produit :

EMP_ID PRENOM NOM VILLE TELEPHONE


EMPLOYE SALAIRE PRIMES
------ ------ ------ ------ --------- ---
---- ------- ------
1 Whitey Ford Orange 555-1001 1
33000 10000
1 Whitey Ford Orange 555-1001 2
18000 2000
1 Whitey Ford Orange 555-1001 3
24000 5000
1 Whitey Ford Orange 555-1001 4
22000 7000
2 Don Larson Newark 555-3221 1
33000 10000
2 Don Larson Newark 555-3221 2
18000 2000
2 Don Larson Newark 555-3221 3
24000 5000
2 Don Larson Newark 555-3221 4
22000 7000
3 Sal Maglie Nutley 555-6905 1
33000 10000
3 Sal Maglie Nutley 555-6905 2
18000 2000
3 Sal Maglie Nutley 555-6905 3
24000 5000
3 Sal Maglie Nutley 555-6905 4
22000 7000
4 Bob Turley Passaic 555-8908 1
33000 10000
4 Bob Turley Passaic 555-8908 2
18000 2000
4 Bob Turley Passaic 555-8908 3
24000 5000
4 Bob Turley Passaic 555-8908 4
22000 7000

La table rsultat, qui est le produit cartsien dEMPLOYES et


dINDEMNITES, contient beaucoup de lignes redondantes. En outre, sa
signification nest pas claire. Elle combine chaque ligne dEMPLOYES
avec chaque ligne dINDEMNITES. Les seules lignes significatives sont
celles qui ont un numro EMP_ID extrait dEMPLOYES correspondant
un numro EMPLOYE provenant dINDEMNITES. Dans ce cas seulement,
le nom et ladresse dun employ sont associs son salaire.
Lorsque vous essayez dextraire des informations dune base de donnes
qui contient plusieurs tables, le produit cartsien retourn par une jointure
lmentaire nest presque jamais ce que vous attendez. Cependant, en
appliquant des contraintes aux JOIN avec des clauses WHERE, vous
pouvez liminer toutes les lignes indsirables. Le JOIN le plus courant qui
utilise la clause WHERE pour filtrer est une jointure quivalente.

Equijointure
Une jointure quivalente (ou quijointure) est une jointure lmentaire dont
la clause WHERE contient une condition qui spcifie quune valeur dune
colonne de la premire table doit tre gale la valeur de la colonne
correspondante de la seconde table. En appliquant une quijointure aux
tables de lexemple prcdent, vous obtiendrez un rsultat bien plus
pertinent :

SELECT *
FROM EMPLOYES, INDEMNITES
WHERE EMPLOYES.EMP_ID = INDEMNITES.EMPLOYE ;

Ce qui produit :

EMP_ID PRENOM NOM VILLE TELEPHONE


EMPLOYE SALAIRE PRIMES
------ ------ ---- ------ --------- ---
---- ------- ------
1 Whitey Ford Orange 555-1001
1 33000 10000
2 Don Larson Newark 55-3221
2 18000 2000
3 Sal Maglie Nutley 555-6905
3 24000 5000
4 Bob Turley Passaic 555-8908
4 22000 7000

Dans cette table de rsultat, les salaires et les primes qui figurent droite
sont associs aux employs dont les noms figurent gauche. Mais la table
contient encore quelques donnes redondantes, car la colonne EMP_ID est
rpte dans la colonne EMPLOYES. Vous pouvez rsoudre ce problme en
reformulant lgrement la requte :
SELECT
EMPLOYES.*,INDEMNITES.SALAIRE,INDEMNITES.PRIMES
FROM EMPLOYES, INDEMNITES
WHERE EMPLOYES.EMP_ID = INDEMNITES.EMPLOYE ;

Ce qui produit :

EMP_ID PRENOM NOM VILLE TELEPHONE


SALAIRE PRIMES
------ ------ ------ ------- ---------
------- ------
1 Whitey Ford Orange 555-1001
33000 10000
2 Don Larson Newark 555-3221
18000 2000
3 Sal Maglie Nutley 555-6905
24000 5000
4 Bob Turley Passaic 555-8908
22000 7000

Cette table vous indique ce que vous voulez savoir sans vous encombrer de
donnes superflues. Cependant, la requte est quelque peu fastidieuse
crire, car pour ter toute ambigut vous avez prfix chaque colonne par
le nom de la table laquelle elle appartient.
Vous pouvez simplifier lcriture de la requte en utilisant des alias (ou
noms de corrlation). Un alias est labrviation du nom dune table. Si
vous utilisez des alias pour crire la requte prcdente, elle ressemblera
ceci :

SELECT E.*, I.SALAIRE, I.PRIMES


FROM EMPLOYES E, INDEMNITES I
WHERE E.EMP_ID = I.EMPLOYE ;

Dans cet exemple, E est lalias dEMPLOYES et I celui


dINDEMNITES. La porte de lalias est limite celle de linstruction
o il est dclar. Une fois que vous avez dclar un alias (dans la clause
FROM), vous ne devez plus utiliser que cet alias dans la requte. Vous ne
pouvez plus indiquer la fois lalias et le vrai nom de la table.
Lutilisation simultane du nom initial de la table et de lalias peut induire
en erreur. Considrez la requte suivante :

SELECT T1.C, T2.C


FROM T1 T2, T2 T1
WHERE T1.C > T2.C ;

Dans cet exemple, lalias de T1 est T2 et lalias pour T2 est T1. Bien
entendu, dfinir de telles corrlations nest pas recommandable, mais rien
ne linterdit. Si vous utilisez en mme temps les alias et les noms des tables
dans la requte, vous ne serez plus en mesure de distinguer les tables que
vous manipulez.
Lexemple prcdent quivaut au SELECT suivant :

SELECT T2.C, T1.C


FROM T1 , T2
WHERE T2.C > T1.C ;

SQL vous permet deffectuer la jointure de plus de deux tables. Le nombre


maximal de tables que vous pouvez joindre varie dune implmentation
une autre (mais il est en gnral plus que suffisant pour couvrir tous vos
besoins). La syntaxe utilise se prsente de la manire suivante :

SELECT E.*, C.SALAIRE, C.PRIMES, Y.TOTAL_VENTES


FROM EMPLOYES E, INDEMNITES C, VENTES Y
WHERE E.EMP_ID = C.EMPLOYE
AND C.EMPLOYE = Y.NOEMP ;

Cette instruction effectue une quijointure sur trois tables pour produire une
table rsultat qui contient le nom, le montant des ventes et le salaire de
chaque commercial. Le directeur des ventes peut ainsi rapidement juger de
ladquation entre le salaire et les performances dun commercial.
Pour amliorer les performances et la fiabilit, il est conseill de stocker
les ventes effectues par les commerciaux dans une table distincte de la
table EMPLOYES. En effet, les donnes de la table EMPLOYES sont
relativement statiques. Le nom, le numro de tlphone et ladresse dun
commercial ne changent pas souvent. Par contre, ses rsultats sur lanne
sont par essence variables. Comme la table VENTES contient moins de
colonnes quEMPLOYES, vous pourrez la mettre jour plus rapidement. En
outre, cela vous pargnera de modifier les informations contenues dans la
table EMPLOYES.

Jointure croise
CROSS JOIN est le mot cl pour dsigner une jointure lmentaire
dpourvue de clause WHERE. Par consquent :

SELECT *
FROM EMPLOYES, INDEMNITES ;

peut aussi scrire :

SELECT *
FROM EMPLOYES CROSS JOIN INDEMNITES ;

Le rsultat est le produit cartsien (galement appel produit vectoriel) des


deux tables sources. CROSS JOIN produit rarement le rsultat que vous
escomptiez, mais cest un traitement qui est souvent utilis pour effectuer un
regroupement pralable de donnes avant de les manipuler pour construire
le rsultat final.

Jointure naturelle
Une jointure naturelle est un cas particulier dquijointure. Dans la clause
WHERE dune quijointure, une colonne dune table source est compare
une colonne dune seconde table pour dterminer si leurs valeurs sont
gales. Ces deux colonnes doivent tre de mme type et de mme longueur,
mais peuvent porter des noms diffrents. En fait, dans une jointure naturelle,
toutes les colonnes dune table qui ont les mmes nom, type et longueur que
les colonnes correspondantes dans la seconde table font lobjet dune
comparaison.
Supposez que la table INDEMNITES de lexemple prcdent contienne les
colonnes EMP_ID, SALAIRE et PRIMES la place de EMPLOYE,
SALAIRE et PRIMES. Dans ce cas, vous pouvez effectuer une jointure
naturelle entre les tables INDEMNITES et EMPLOYES. La syntaxe de ce
JOIN serait la suivante :

SELECT E.*, I.SALAIRE, I.PRIMES


FROM EMPLOYES E, INDEMNITES I
WHERE E.EMP_ID =I.EMP_ID ;

Cette requte est une jointure naturelle. Vous pouvez aussi utiliser la syntaxe
suivante :

SELECT E.*, I.SALAIRE, I.PRIMES


FROM EMPLOYES E NATURAL JOIN INDEMNITES I ;

Cette requte effectue la jointure des lignes o E.EMP_ID = I.EMP_ID, o


I.SALAIRE=C.SALAIRE, et o I.PRIMES =C.PRIMES. La table rsultat
contiendra seulement les lignes dont toutes les colonnes auront des
correspondances. Dans cet exemple, le rsultat de ces requtes est le mme
car la table EPLOYE ne contient ni colonne Salaire ni colonne Prime.

Jointure conditionnelle
Une jointure conditionnelle est une quijointure, ceci prs que la
condition de test nest pas lgalit (bien que ce puisse tre le cas), mais un
prdicat. Si la condition est satisfaite par une ligne, celle-ci est intgre la
table rsultat. La syntaxe employe est lgrement diffrente de ce que vous
avez pu voir jusqu prsent. La condition est contenue dans une clause ON
et non plus dans une clause WHERE.
Supposons quun statisticien du base-ball dsire identifier les lanceurs de la
Ligue nationale qui ont particip au mme nombre de parties compltes
quun ou plusieurs des lanceurs de la Ligue amricaine. Cette question peut
tre rsolue avec une jointure quivalente, mais aussi avec une jointure
conditionnelle :

SELECT *
FROM NATIONALE JOIN AMERICAINE
ON NATIONALE.PARTIES_COMPLETES =
AMERICAINE.PARTIES_COM-
PLETES ;

Jointure par nom de colonne


Une jointure par nom de colonne est une jointure naturelle trs souple
dutilisation. Lors dune jointure naturelle, toutes les colonnes qui portent le
mme nom dans les tables sources sont compares entre elles pour tester
leur galit. Avec une jointure par nom de colonne, il est possible de
spcifier les colonnes homonymes qui doivent tre compares et celles qui
ne doivent pas ltre. Vous pouvez choisir toutes les colonnes, faisant ainsi
de cette jointure par nom de colonne une jointure naturelle. Vous pouvez
galement ne spcifier que quelques colonnes homonymes, ce qui vous
permettra de contrler finement les lignes qui apparatront dans votre table
rsultat.
Supposons que vous soyez un fabricant dchiquiers et que vous disposiez
dune table dinventaire pour grer votre stock de pices blanches, et dune
autre table concernant quant elle votre stock de pices noires. Ces tables
contiennent les donnes suivantes :

BLANC NOIR
----- -----
Pice Quant Bois Pice Quant
Bois
----- ----- ----- ----- ----- --
---
Roi 502 Chne Roi 502
Ebne
Reine 398 Chne Reine 397
Ebne
Pion 1020 Chne Pion 1020
Ebne
Fou 985 Chne Fou 985
Ebne
Cavalier 950 Chne Cavalier 950
Ebne
Tour 431 Chne Tour 453
Ebne

Pour chaque type de pice, le nombre de pices blanches devrait tre gal
au nombre de pices noires. Si ce nest pas le cas, des chiquiers sont
incomplets. Les pices ont pu tre perdues ou voles. Dans tous les cas, des
mesures de contrle simposent.
Une jointure naturelle teste lgalit de toutes les colonnes homonymes.
Dans notre exemple, la table rsultat ne contiendra rien, car aucune ligne de
la colonne BOIS de la table BLANC ne correspond une ligne de la
colonne BOIS de la table NOIR. Cette table rsultat ne vous permet pas de
savoir si des pices sont manquantes. Effectuez plutt une jointure par nom
de colonne en excluant la colonne BOIS. La requte peut prendre la forme
suivante :

SELECT *
FROM BLANC JOIN NOIR
USING (PIECE, QUANT) ;

La table rsultat ne contient que les lignes pour lesquelles le nombre de


pices blanches est gal au nombre de pices noires.

Pice Quant Bois Pice Quant Bois


----- ----- ----- ----- ----- -----
Roi 502 Chne Roi 502 Ebne
Pion 1020 Chne Pion 1020 Ebne
Fou 985 Chne Fou 985 Ebne
Cavalier 950 Chne Cavalier 950 Ebne

La personne qui gre les stocks pourra dduire de cette liste quil y a un
problme avec les reines et les tours.
Jointure interne
Vous en tes probablement au stade o vous pensez que les jointures sont
une affaire plutt sotrique, et quil faut un haut degr de discernement
spirituel pour sen servir correctement. Vous avez peut-tre aussi entendu
parler de la mystrieuse jointure interne, ce qui vous a plong dans une
profonde rflexion sur lessence mme des oprations relationnelles et leurs
rapports ventuels avec danciennes pratiques chamaniques...
En fait, cette jointure na rien de mystrieux. Toutes les jointures prsentes
dans ce chapitre sont des jointures internes. Jaurais pu qualifier la jointure
par nom de colonne de lexemple prcdent de jointure interne en utilisant
la syntaxe suivante :

SELECT *
FROM BLANC INNER JOIN NOIR
USING (PIECE, QUANT) ;

Le rsultat obtenu aurait t exactement le mme.


Tout simplement, la jointure interne est ainsi appele pour la distinguer de
la jointure externe. Une jointure interne supprime toutes les lignes dans la
table rsultat qui ne correspondent pas des lignes quivalentes dans les
deux tables sources. La jointure externe conserve ces lignes. Cest l toute
la diffrence ! Il ny a donc rien de mtaphysique dans cette affaire.

Jointure externe
Lorsque vous effectuez la jointure de deux tables, la premire ( gauche)
peut contenir des lignes sans quivalent dans la seconde table ( droite). De
la mme manire, la table de droite peut contenir des lignes sans quivalent
dans la table de gauche. Si vous effectuez une jointure interne sur ces tables,
toutes les lignes sans correspondance seront exclues du rsultat. Par contre,
une jointure externe les conservera. Il existe trois types de jointures
externes : la jointure externe gauche, la jointure externe droite et la jointure
externe complte.

Jointure externe gauche


Dans une requte qui contient une jointure, la table de gauche est celle qui
prcde le mot cl JOIN, et la table de droite celle qui le suit (mais vous
aviez trouv !). Une jointure externe gauche conserve les lignes de la table
de gauche qui nont pas dquivalent, mais elle supprime celles de la table
de droite qui sont dans le mme cas.
Pour mieux comprendre les jointures externes, prenons lexemple dune
base de donnes contenant des informations sur les employs, les
dpartements et les sites dune entreprise. Les Tableaux 11.1,
11.2 et 11.3 contiennent quelques exemples de donnes.

TABLEAU 11.1 La table SITES.

SITE_ID VILLE

1 Boston

3 Tampa

5 Chicago

Supposons maintenant que vous souhaitiez visualiser toutes les informations


relatives aux employs, y compris leur dpartement et leur site. Vous pouvez
obtenir le rsultat voulu avec une quijointure :

TABLEAU 11.2 La table DEPARTEMENTS.

DEPT_ID SITE_ID NOM

21 1 Ventes

24 1 Admin

27 5 Rparation

29 5 Stock

TABLEAU 11.3 La table EMPLOYES.


EMP_ID DEPT_ID NOM

61 24 Kirk

63 27 McCoy

SELECT *
FROM SITES S, DEPARTEMENTS D, EMPLOYES E
WHERE S.SITE_ID = D.SITE_ID
AND D.DEPT_ID = E.DEPT_ID ;

Cette instruction produit le rsultat suivant :

1 Boston 24 1 Admin 61 24 Kirk


5 Chicago 27 5 Reparation 63 27 McCoy

La table rsultat contient toutes les donnes relatives tous les employs,
dont le site et le dpartement o ils travaillent. Lquijointure fonctionne,
car tous les employs travaillent sur un site dans un certain dpartement.
Supposons maintenant que vous souhaitiez obtenir des informations sur les
sites. Le problme est diffrent, car un site peut trs bien ne pas avoir de
dpartement. Pour obtenir le rsultat escompt, vous devez utiliser une
jointure externe telle que :

SELECT *
FROM SITES S LEFT OUTER JOIN DEPARTEMENTS D
ON (S.SITE_ID = D.SITE_ID)
LEFT OUTER JOIN EMPLOYES E
ON (D.DEPT_ID = E.DEPT_ID);

La jointure extrait des donnes des trois tables. Tout dabord, la table
SITES est jointe la table DEPARTEMENTS. Puis la table rsultat est
son tour jointe la table EMPLOYES. Les lignes de la table qui se trouve
gauche de loprateur LEFT OUTER JOIN et qui nont pas dquivalent
dans la table place droite de loprateur sont incluses dans le rsultat.
Par consquent, lors de cette premire jointure, tous les sites sont inclus, y
compris ceux qui ne sont pas associs des dpartements. Lors de la
seconde jointure, tous les dpartements sont inclus, mme si aucun employ
ny est attach. Le rsultat est le suivant :

1 Boston 24 1 Admin 61 24 Kirk


5 Chicago 27 5 Reparation 63 27 McCoy
3 Tampa NULL NULL NULL NULL NULL NULL
5 Chicago 29 5 Stock NULL NULL NULL
1 Boston 21 1 Ventes NULL NULL NULL

Les deux premires lignes sont identiques celles de lexemple prcdent.


Les colonnes qui correspondent au dpartement et lemploy de la
troisime ligne (3 Tampa) contiennent des valeurs nulles, car aucun
dpartement nest dfini Tampa et aucun employ ny travaille. Les
quatrime et cinquime lignes (5 Chicago et 1 Boston) contiennent des
informations sur les dpartements Ventes et Stock, mais la colonne
Employs y prend une valeur nulle, car aucune personne nest rattache
ces deux dpartements. La jointure externe vous fournit tout ce que la
jointure quivalente vous donnait, plus :
Tous les sites de la socit, quils possdent ou non un
dpartement.

Tous les dpartements de la socit, quils disposent ou


non demploys.

Les lignes retournes dans lexemple prcdent napparaissent pas


forcment dans lordre que vous souhaitez. Cet ordre peut varier dune
implmentation une autre. Pour vous assurer que les lignes retournes sont
classes comme vous le dsirez, ajoutez une clause ORDER BY dans votre
instruction SELECT, comme ceci :

SELECT *
FROM SITES S LEFT OUTER JOIN DEPARTEMENTS D
ON (S.SITE_ID = D.SITE_ID)
LEFT OUTER JOIN EMPLOYES E
ON (D.DEPT_ID = E.DEPT_ID)
ORDER BY S.SITE_ID, D.DEPT_ID, E.EMP_ID;
Une jointure externe gauche peut galement scrire LEFT JOIN, car il
nexiste pas de jointure interne gauche.

Jointure externe droite


Il ny a plus qu intervertir les quipes... La jointure externe droite
prserve dans la table de droite les lignes sans quivalent dans la table de
gauche, et inversement supprime de la table de gauche les lignes sans
quivalent dans la table de droite. Vous pouvez lutiliser sur les mmes
tables et obtenir les mmes rsultats en inversant simplement lordre dans
lequel vous indiquez les tables lors de la jointure.

SELECT *
FROM EMPLOYES E RIGHT OUTER JOIN DEPARTEMENTS
D
ON (D.DEPT_ID = E.DEPT_ID)
RIGHT OUTER JOIN SITES S
ON (S.SITE_ID = D.SITE_ID) ;

Dans cette formule, la premire jointure produit une table qui contient tous
les dpartements, quils aient ou non un employ. La seconde produit une
table qui contient tous les sites, quils disposent ou non dun dpartement.
Une jointure externe droite peut galement sabrger en RIGHT JOIN, car
il nexiste pas de jointure interne droite.

Jointure externe complte


La jointure externe complte est une combinaison de jointure externe
gauche et de jointure externe droite. Elle retient les lignes sans
correspondance la fois dans les tables de gauche et de droite. Reprenons
lexemple prcdent. Notre socit peut avoir :
Des sites sans dpartements.

Des dpartements sans site.

Des dpartements sans employs.


Des employs sans dpartement.

Pour afficher tous les sites, dpartements et employs, que leurs lignes
disposent ou non de lignes quivalentes dans les autres tables, utilisez une
jointure externe complte sous la forme suivante :

SELECT *
FROM SITES S FULL JOIN DEPARTEMENTS D
ON (S.SITE_ID = D.SITE_ID)
FULL JOIN EMPLOYES E
ON (D.DEPT_ID = E.DEPT_ID) ;

Une jointure externe complte peut galement sabrger en FULL JOIN,


car il nexiste pas de jointure interne complte.

Jointure dunion
Contrairement aux autres types de jointure, la jointure dunion nessaie pas
de comparer une ligne de la table source de gauche aux lignes de la table
source de droite. Elle cre une nouvelle table virtuelle qui contient le
rsultat de lunion des colonnes des deux tables sources.
Dans la table virtuelle rsultat, les colonnes extraites de la table source de
gauche contiennent toutes les lignes qui se trouvaient dans cette table. Dans
ces lignes, les colonnes extraites de la table de droite prennent des valeurs
nulles. De mme, les colonnes extraites de la table source de droite
contiennent toutes les lignes qui se trouvaient dans cette table, et, dans
chacune de ces lignes, les colonnes extraites de la table de gauche prennent
la valeur nulle. Ainsi la table rsultat dune jointure union reprend toutes les
colonnes des deux tables sources, et la quantit de lignes quelle contient
est gale la somme du nombre des lignes des deux tables sources.
Le rsultat dune jointure dunion nest pas immdiatement utilisable dans la
plupart des cas, la table produite contenant gnralement de nombreuses
valeurs nulles. Cependant, vous pouvez utiliser cette table avec
lexpression COALESCE (voyez le Chapitre 9) pour rcuprer des
informations intressantes. Prenons un exemple.
Supposons que vous travailliez pour une socit qui conoit et construit des
fuses exprimentales. Vous menez de front plusieurs projets. Vous
collaborez avec des ingnieurs dont les comptences sont multiples. En
qualit de responsable, vous voulez savoir qui sont ces ingnieurs, de
quelles comptences ils disposent et sur quels projets ils travaillent.
Actuellement, ces informations sont rparties entre les tables EMPLOYES,
PROJETS et COMPETENCES.
La table EMPLOYES contient des donnes sur les personnels et EMP_ID
est sa cl primaire. La table PROJETS contient une ligne pour chaque projet
auquel un employ a particip. PROJETS. EMP_ID est une cl trangre
qui fait rfrence la table EMPLOYES. La table COMPETENCES dcrit
les comptences de chaque employ. COMPETENCES.EMP_ID est une
cl trangre qui rfrence la table EMPLOYES.
La table EMPLOYES contient exactement une ligne pour chaque employ.
Les tables PROJETS et COMPETENCES ont zro ou plusieurs lignes.
Les Tableaux 11.4, 11.5 et 11.6 prsentent des exemples de donnes pour
ces trois tables.

TABLEAU 11.4 La table EMPLOYES.

EMP_ID NOM

1 Ferguson

2 Frost

3 Toyon

TABLEAU 11.5 La table PROJETS.

NOM_PROJET EMP_ID

X-63 Structure 1

X-64 Structure 1

X-63 Guidage 2
X-64 Guidage 2

X-63 Tlmtrie 3

X-64 Tlmtrie 3

TABLEAU 11.6 La table COMPETENCES.

COMPETENCE EMP_ID

Conception mcanique 1

Arodynamique 1

Conception analogique 2

Gyroscope 2

Conception numrique 3

Conception R/F 3

la lecture de ces tableaux, vous apprenez que Ferguson a travaill la


construction des structures des X-63 et X-64, et quil est un expert en
conception mcanique et en arodynamique.
Vous souhaitez maintenant visualiser toutes les informations relatives tous
les employs. Vous dcidez dappliquer une quijointure aux tables
EMPLOYES, PROJETS et COMPETENCES.

SELECT *
FROM EMPLOYES E, PROJETS P, COMPETENCES C
WHERE E.EMP_ID = P.EMP_ID
AND E.EMP_ID = C.EMP_ID ;

Vous pouvez exprimer cette mme opration en utilisant une jointure interne
de la manire suivante :

SELECT *
FROM EMPLOYES E INNER JOIN PROJETS P
ON (E.EMP_ID = P.EMP_ID)
INNER JOIN COMPETENCES C
ON (E.EMP_ID = C.EMP_ID) ;

Les deux formulations donnent le mme rsultat, celui qui est reprsent
dans le Tableau 11.7.

TABLEAU 11.7 Rsultat de la jointure interne.

E.EMP_ E.NOM P.EMP_ P.NOM_ C.EMP_ID C.COMPETENCE


ID ID PROJET

1 Ferguson 1 X-63 1 Conception


Structure mcanique

1 Ferguson 1 X-63 1 Arodynamique


Structure

1 Ferguson 1 X-64 1 Conception


Structure mcanique

1 Ferguson 1 X-64 1 Arodynamique


Structure

2 Frost 2 X-63 2 Conception


Guidage analogique

2 Frost 2 X-63 2 Gyroscope


Guidage

2 Frost 2 X-64 2 Conception


Guidage analogique

2 Frost 2 X-64 2 Gyroscope


Guidage
3 Toyon 3 X-63 3 Conception
Tlmtrie numrique

3 Toyon 3 X-63 3 Conception R/F


Tlmtrie

3 Toyon 3 X-64 3 Conception


Tlmtrie numrique

3 Toyon 3 X-64 3 Conception R/F


Tlmtrie

Ces donnes ne vous apprennent pas grand-chose. Les numros identifiant


les employs apparaissent quatre fois chacun et les lignes relatives aux
comptences dun employ sont dupliques. La jointure interne nest donc
pas particulirement adapte pour rpondre ce type de question. Vous
pouvez obtenir un meilleur rsultat en utilisant une jointure dunion
combine quelques instructions SELECT soigneusement choisies.
Commenons par une jointure dunion de base :

SELECT *
FROM EMPLOYES E UNION JOIN PROJETS P
UNION JOIN COMPETENCES C ;

Remarquez labsence de clause ON. La jointure dunion ne filtre pas les


donnes. Cest pourquoi cette clause nest pas ncessaire. Linstruction
produit le rsultat reprsent dans le Tableau 11.8.

TABLEAU 11.8 Rsultat de UNION JOIN.

E.EMP_ E.NOM P.EMP_ID P.NOM_PROJET C.EMP_ID C.COMPETENCE


ID

1 Ferguson NULL NULL NULL NULL

NULL NULL 1 X-63 Structure NULL NULL


NULL NULL 1 X-64 Structure NULL NULL

NULL NULL NULL NULL 1 Conception


mcanique

NULL NULL NULL NULL 1 Arodynamique

2 Frost NULL NULL NULL NULL

NULL NULL 2 X-63 Guidage NULL NULL

NULL NULL 2 X-64 Guidage NULL NULL

NULL NULL NULL NULL 2 Conception


analogique

NULL NULL NULL NULL 2 Gyroscope

3 Toyon NULL NULL NULL NULL

NULL NULL 3 X-63 NULL NULL


Tlmtrie

NULL NULL 3 X-64 NULL NULL


Tlmtrie

NULL NULL NULL NULL 3 Conception


numrique

NULL NULL NULL NULL 3 Conception R/F

Chaque table a t tendue vers la droite ou vers la gauche avec des valeurs
nulles, et les lignes ainsi tendues ont t runies. Notez que lordre des
lignes est arbitraire et dpend de limplmentation. Vous pouvez maintenant
organiser les donnes sous une forme plus exploitable.
Remarquez que la table comporte trois colonnes ID dont une seule ne
contient pas de valeur nulle dans chaque ligne. Vous pouvez amliorer
laffichage en fusionnant ces colonnes ID. Comme je lai dit au Chapitre 9,
lexpression COALESCE slectionne la premire valeur non nulle dans une
liste. Ici, nous allons lui demander de prendre la valeur du seul numro
didentification non nul dans la liste de colonnes qui lui est fournie :

SELECT COALESCE (E.EMP_ID, P.EMP_ID, C.EMP_ID) AS


ID,
E.NOM, P.NOM_PROJET, C.COMPETENCES
FROM EMPLOYES E UNION JOIN PROJETS P
UNION JOIN COMPETENCES C
ORDER BY ID ;

La clause FROM est la mme que dans les exemples prcdents, mais vous
fusionnez les trois colonnes EMP_ID en une seule colonne appele ID.
Vous triez le rsultat selon ID. Le Tableau 11.9 vous montre le rsultat
obtenu.

TABLEAU 11.9 Rsultat de la jointure dunion avec lexpression COALESCE.

ID E.NOM P.NOM_PROJET C.COMPETENCE

1 Ferguson X-63 Structure NULL

1 Ferguson X-64 Structure NULL

1 Ferguson NULL Conception mcanique

1 Ferguson NULL Arodynamique

2 Frost X-63 Guidage NULL

2 Frost X-64 Guidage NULL

2 Frost NULL Conception analogique

2 Frost NULL Gyroscope

3 Toyon X-63Tlmtrie NULL

3 Toyon X-64 Tlmtrie NULL


3 Toyon NULL Conception numrique

3 Toyon NULL Conception R/F

SELECT COALESCE (E.EMP_ID, P.EMP_ID, C.EMP_ID) AS


ID,
E.NOM, COALESCE (P.TYPE, C.TYPE) AS TYPE,

Chacune des lignes de ce rsultat contient des donnes relatives un projet


ou une comptence, mais pas aux deux la fois. Pour lire ce rsultat, vous
devez tout dabord dterminer de quoi parle chaque ligne (projet ou
comptence). Si la colonne NOM_PROJET ne contient pas une valeur
nulle, la ligne correspond un projet. Si la colonne COMPETENCES ne
contient pas une valeur nulle, la ligne correspond une comptence.
Vous pouvez clarifier ce rsultat en ajoutant une autre expression
COALESCE linstruction SELECT, comme suit :

NOM_PROJET, C.COMPETENCES
FROM EMPLOYES E
UNION JOIN (SELECT Projet AS TYPE, P.*
FROM PROJETS) P
UNION JOIN (SELECT Comptence AS TYPE, C.*
FROM COMPETENCES) C
ORDER BY ID, TYPE ;

Dans la jointure dunion, la table PROJETS est remplace par un SELECT


imbriqu qui rajoute une colonne appele P.TYPE, dont la valeur constante
est Projet , aux colonnes provenant de la table PROJETS. De mme,
la table COMPETENCES a t remplace par un SELECT imbriqu qui
rajoute une colonne appele C.TYPE, dont la valeur constante est
Comptence , aux colonnes extraites de la table COMPETENCES.
Dans chaque ligne, donc, P.TYPE est soit nulle, soit Projet , et
C.TYPE est soit nulle, soit Comptence .
Le SELECT externe utilise COALESCE pour fusionner ces deux colonnes
types en une seule appele TYPE. Vous spcifiez ensuite TYPE dans la
clause ORDER BY afin de trier les lignes qui ont le mme ID pour faire
apparatre dabord les projets, puis les comptences. Le rsultat est montr
dans le Tableau 11.10.

TABLEAU 11.10 Rsultats affins de la jointure dunion avec des expressions


COALESCE.

ID E.NOM TYPE NOM_PROJET COMPETENCE

1 Ferguson Projet X-63 Structure NULL

1 Ferguson Projet X-64 Structure NULL

1 Ferguson Comptences NULL Conception mcanique

1 Ferguson Comptences NULL Arodynamique

2 Frost Projet X-63 Guidage NULL

2 Frost Projet X-64 Guidage NULL

2 Frost Comptences NULL Conception analogique

2 Frost Comptences NULL Gyroscope

3 Toyon Projet X-63 Tlmtrie NULL

3 Toyon Project X-64 Tlmtrie NULL

3 Toyon Comptences NULL Conception numrique

3 Toyon Comptences NULL Conception R/F

La table rsultat contient maintenant un expos trs lisible des comptences


et des projets sur lesquels ont travaill les employs enregistrs dans la
table EMPLOYES.
tant donn le grand nombre doprations de jointure quil est possible
deffectuer, tablir des liens entre diffrentes tables ne devrait pas tre un
problme quelle que soit leur structure. partir du moment o les donnes
existent dans votre base, SQL vous permettra de les retrouver et de les
afficher sous une forme significative.

ON et WHERE
La fonction des clauses ON et WHERE dans les diffrents types de jointure
peut prter confusion. Ces diffrents points devraient vous permettre de
clarifier la situation :
La clause ON sutilise dans des jointures interne, gauche,
droite et complte. Les jointures croises et union ne
comportent pas de clause ON, car aucune dentre elles ne
filtre les donnes.

La clause ON dans une jointure interne est lquivalent


logique de la clause WHERE. La condition nonce pourrait
tre spcifie avec une clause ON ou une clause WHERE.

La clause ON joue dans les jointures externes (gauche,


droite et complte) un rle diffrent des clauses WHERE.
WHERE ne filtre que les lignes retournes par la clause
FROM. Les lignes rejetes par le filtre ne sont pas incluses
dans le rsultat. linverse, la clause ON filtre dabord les
lignes issues du produit cartsien, puis les inclut dans le
rsultat en les tendant ventuellement laide de valeurs
nulles.
Chapitre 12
Effectuer des recherches
approfondies avec des requtes
imbriques
DANS CE CHAPITRE :
Extraire des donnes de plusieurs tables avec une seule instruction SQL.

Comparer une valeur dune table avec un ensemble de valeurs dune autre
table.

Utiliser SELECT pour comparer une valeur dune table avec une valeur dune
autre table.

Comparer une valeur dune table avec toutes les valeurs correspondantes
dune autre table.

Crer des requtes qui mettent en corrlation deux lignes correspondantes


dans des tables.

Dterminer les lignes mettre jour, supprimer ou insrer en utilisant


une sous-requte.

L
une des meilleures mthodes pour protger lintgrit de vos donnes
est de normaliser votre base de donnes, ce qui prviendra lapparition
danomalie lors des modifications. La normalisation consiste diviser
une table en plusieurs autres tables, chacune traitant dun thme particulier.

Par exemple, vous nallez pas mlanger des informations sur les produits
avec des informations sur les clients au sein dune mme table, mme si les
clients ont achet des produits. Si vous normalisez une base de donnes
correctement, les donnes seront rparties entre des tables multiples. La
plupart des requtes que vous effectuerez alors devront extraire des donnes
de deux ou plusieurs tables. Pour cela, vous utiliserez une jointure ou lun
des oprateurs relationnels (UNION, INTERSECT ou EXCEPT). Ces
oprateurs extraient des informations de plusieurs tables et les combinent en
une seule table.
Une autre solution pour extraire des donnes de deux ou plusieurs tables
consiste utiliser des requtes imbriques. En SQL, une requte imbrique
est une requte o une instruction externe contient une sous-requte. Cette
sous-requte peut elle-mme incorporer une autre sous-requte de plus bas
niveau. Le nombre de requtes que vous pouvez ainsi imbriquer est en
thorie infini, mais il est dans la pratique limit par certaines
implmentations.
Les sous-requtes sont invariablement des instructions SELECT, mais les
instructions qui les incluent peuvent aussi tre une opration INSERT,
UPDATE ou DELETE.
Comme une sous-requte est parfaitement capable de traiter une table
diffrente de celle sur laquelle porte linstruction qui la contient, les
requtes imbriques sont un excellent moyen pour extraire des informations
provenant de multiples tables.
Supposons par exemple que vous interrogiez la base de donnes de votre
socit pour trouver tous les responsables commerciaux gs de plus
de 50 ans. Si vous utilisez les jointures (tudies au Chapitre 11), votre
requte pourra se prsenter ainsi :

SELECT D.NODEPT, D.NOM, E.NOM, E.AGE


FROM DEPT D, EMPLOYES E
WHERE D.RESPONSABLE_ID = E.ID AND E.AGE > 50
;

D est lalias de la table DEPT et E lalias de la table EMPLOYES. Cette


dernire contient une colonne ID qui joue le rle de cl primaire, tandis que
la table DEPT possde une colonne RESPON-SABLE_ID dont la valeur
est celle de lID de lemploy responsable du dpartement. Jemploie
une seule jointure (la liste des tables de la clause FROM) pour coupler les
tables, et un WHERE pour filtrer toutes les lignes lexception de celles
qui correspondent aux critres. Remarquez que la liste des paramtres de
linstruction SELECT mentionne les colonnes NODEPT et NOM de la
table DEPT, et les colonnes NOM et AGE de la table EMPLOYES.
Supposons maintenant que vous souhaitiez rcuprer le mme ensemble de
lignes, mais en vous limitant aux colonnes de la table DEPT. Autrement dit,
vous voulez obtenir la liste des dpartements dont le responsable est g de
plus de 50 ans, mais lidentit et lge exact des personnes ne vous
intressent pas. Vous pouvez reformuler la requte en remplaant la jointure
par une sous-requte :

SELECT D.NODEPT, D.NOM


FROM DEPT D
WHERE EXISTS (SELECT * FROM EMPLOYES E
WHERE E.ID = D.RESPONSABLEID AND E.AGE >
50) ;

Cette requte contient deux nouveaux lments : le mot cl EXISTS et le


SELECT * dans la clause WHERE. Le second SELECT est une sous-
requte (ou sous-slection), et le mot cl EXISTS est lun des nombreux
outils que vous pouvez utiliser dans une sous-requte.

Que fait une sous-requte ?


Les sous-requtes se trouvent gnralement dans la clause WHERE de
linstruction qui les englobe. Leur fonction consiste spcifier les critres
de recherche de la clause WHERE. Diffrents types de sous-requtes
produiront diffrents rsultats. Certaines renvoient une liste de valeurs que
linstruction externe utilise comme entre. Dautres retournent une unique
valeur que linstruction englobante value laide dun oprateur de
comparaison. Un troisime type de sous-requte produit une valeur True
ou False.

Requtes imbriques retournant


un ensemble de lignes
Pour illustrer comment une requte imbrique retourne un ensemble de
lignes, supposons que vous travailliez pour un intgrateur de matriel
informatique. Votre socit, Zetec Corporation, assemble des systmes
partir de composants achets, puis vend ces systmes des socits ou des
administrations. Cette activit est dcrite dans une base de donnes
relationnelle. Elle contient de nombreuses tables, mais nous ne nous
intresserons qu trois dentre elles : PRODUITS, COMP_UTI-LISES,
COMPOSANTS. La table PRODUITS (voir le Tableau 12.1) contient la
liste de tous les produits que vous proposez. La table COMPOSANTS (voir
le Tableau 12.2) regroupe la liste de tous les composants que vous utilisez.
La table COMP_UTILISES (voir Tableau 12.3) prcise les composants
utiliss dans chaque produit. Ces tables sont dfinies comme suit :
Un composant peut tre utilis dans plusieurs produits et un produit peut
contenir plusieurs composants (relation plusieurs plusieurs), ce qui peut
engendrer des problmes dintgrit. Pour contourner cette difficult, la
table de liaison COMP_UTI-LISES permet de relier les tables
COMPOSANTS et PRODUITS. Un composant peut apparatre dans
plusieurs lignes de COMP_ UTILISES, mais chaque ligne de
COMP_UTILISES ne rfrence quun seul composant (relation un
plusieurs). De mme, un produit peut apparatre dans plusieurs lignes de
COMP_UTI-LISES, mais chaque ligne de COMP_UTILISES ne rfrence
quun seul produit (autre relation un plusieurs). En ajoutant cette table de
liaison, une relation plusieurs plusieurs a t transforme en deux
relations un plusieurs. Cette rduction de complexit de relation est un
exemple de normalisation.

Les sous-requtes introduites par le mot


cl IN
Une des formes de sous-requte imbrique compare une valeur unique un
ensemble de valeurs retournes par SELECT. Elle fait appel au prdicat
IN, selon la syntaxe suivante :

SELECT liste_colonnes
FROM table
WHERE expression IN (sous-requte) ;

TABLEAU 12.1 La table PRODUITS.


Colonne Type Contraintes
MODELE Char (6) PRIMARY KEY

NOM_PROD Char (35)

DESC_PROD Char (31)

PRIX Numeric (9,2)

TABLEAU 12.2 La table COMPOSANTS.

Colonne Type Contraintes


COMP_ID CHAR (6) PRIMARY KEY

TYPE_COMP CHAR (10)

DESC_COMP CHAR (31)

TABLEAU 12.3 La table COMP_UTILISES.

Colonne Type Contraintes


MODELE CHAR (6) FOREIGN KEY (pour PRODUITS)
COMP_ID CHAR (6) FOREIGN KEY (pour COMPOSANTS)

Lvaluation de lexpression qui Figure dans la clause WHERE produit une


valeur. Si cette dernire appartient la liste retourne par la sous-requte,
la clause WHERE retourne une valeur Vrai, et les colonnes de la ligne
traite sont ajoutes au rsultat. La sous-requte peut rfrencer la mme
table que la requte externe ou une autre table.
La base de donnes de Zetec illustre lutilisation de ce type de requte.
Supposez que lindustrie informatique soit frappe par une pnurie de
moniteurs. Si votre stock est puis, vous ne serez plus en mesure de livrer
les produits qui comportent des crans. Vous voulez donc savoir quels sont
ces produits. Saisissez la requte suivante :
SELECT MODELE
FROM COMP_UTILISES
WHERE COMP_ID IN
(SELECT COMP_ID
FROM COMPOSANTS
WHERE TYPE_COMP = Moniteur) ;

SQL excute la requte la plus imbrique en premier, cest--dire celle qui


retourne la valeur de COMP_ID de chaque ligne de la table
COMPOSANTS o le TYPE_COMP est Moniteur. Le rsultat est une
liste des numros didentification de tous les moniteurs. La requte externe
compare ensuite la valeur du COMP_ID de chaque ligne de la table
COMP_UTILISES aux valeurs de cette liste. Si la comparaison est
valide, la valeur de la colonne MODELE de cette ligne est ajoute la
table rsultat produite par le SELECT externe. Le rsultat final est une liste
de tous les produits qui comportent un moniteur. Lexemple suivant vous
montre ce qui se passe lors de lexcution de cette requte :

MODELE
------
CX3000
CX3010
CX3020
MB3030
MX3020
MX3030

Vous connaissez maintenant les produits pour lesquels vous serez bientt en
rupture de stock.
Si vous utilisez cette forme dimbrication, la sous-requte doit spcifier une
seule colonne, et le type de donne de cette colonne doit correspondre au
type de largument prcdant le mot cl IN.

Les sous-requtes introduites par le mot


cl NOT IN
Vous pouvez tout aussi bien introduire une sous-requte avec le mot cl NOT
IN. En utilisant la requte dcrite dans la section prcdente, la direction
de Zetec a identifi les produits qui ne peuvent plus tre commercialiss
faute de moniteurs. Cest intressant, mais pas trs efficace sur le plan
commercial. Elle veut donc maintenant savoir quels sont les produits qui ne
comportent pas de moniteur afin de renforcer leur vente. Une requte
imbrique comportant une sous-requte introduite par le mot cl NOT IN
fournira le rsultat escompt :

SELECT MODELE
FROM COMP_UTILISES
WHERE MODELE NOT IN
(SELECT COMP_ID
FROM COMPOSANTS
WHERE TYPE_COMP = Moniteur)) ;

Cette requte produit le rsultat suivant :

MODELE
------
PX3040
PB3050
PX3040
PB3050

Notez que la table rsultat contient des entres dupliques. Cette duplication
est due au fait quun produit contenant plusieurs composants autres que des
moniteurs possde une ligne dans la table COMP_UTILISE pour chaque
composant utilis. La requte cre une entre dans la table rsultat pour
chacune de ces lignes.
Dans cet exemple, le nombre de lignes ne cre pas de problme, car la table
rsultat est de taille rduite. Mais cette table pourrait contenir des
centaines, voire des milliers de lignes. Vous devriez alors liminer les
doublons. Pour cela, ajoutez dans la requte le mot cl DISTINCT. Seules
les lignes distinctes (diffrentes) de toutes celles qui ont dj t rcupres
seront ajoutes la table rsultat :

SELECT DISTINCT MODELE


FROM COMP_UTILISES
WHERE MODELE NOT IN
(SELECT COMP_ID
FROM COMPOSANTS
WHERE TYPE_COMP = Moniteur)) ;

Comme prvu, le rsultat est le suivant :

MODELE
------
PX3040
PB3050

Requtes imbriques retournant


une seule valeur
Lintroduction dune sous-requte par lun des six oprateurs de
comparaison (=, <>, <, <=, >, >=) se rvle souvent utile.
Lexpression qui prcde loprateur est value pour obtenir une valeur
unique. Il en va de mme pour la sous-requte qui suit loprateur. Il existe
cependant une exception cela : lemploi dun oprateur de comparaison
quantifi, qui est un oprateur de comparaison suivi dun quantificateur
(ANY, SOME ou ALL).
Reprenons lexemple de la base de donnes de Zetec. Cette base de
donnes possde une table CLIENTS charge de mmoriser des
informations sur les socits qui achtent des produits Zetec. Elle comporte
galement une table CONTACTS contenant des informations confidentielles
sur les personnes qui travaillent dans les entreprises clientes de Zetec. Les
Tableaux 12.4 et 12.5 reprsentent la structure de ces tables.

TABLEAU 12.4 La table CLIENTS.


Type Colonne Contraintes
CLIENT_ID INTEGER PRIMARY KEY

SOCIETE CHAR (40)

ADRESSE_CLIENT CHAR (30)

VILLE_CLIENT CHAR (20)

ETAT_CLIENT CHAR (2)

CP_CLIENT CHAR (10)

TEL_CLIENT CHAR (12)

NIV_MOD INTEGER

TABLEAU 12.5 La table CONTACTS.

Type Colonne Contraintes


CLIENT_ID INTEGER FOREIGN KEY
CONT_NOM CHAR (10)

CONT_PRENOM CHAR (16)

CONT_TELEPHONE CHAR (12)

CONT_INFO CHAR (50)

Supposez que vous recherchiez votre contact chez Olympic Sales, mais
vous ne vous rappelez plus du CLIENT_ID de cette socit. Vous pouvez
utiliser la requte suivante :

SELECT *
FROM CONTACTS
WHERE CLIENT_ID =
(SELECT CLIENT_ID
FROM CLIENTS
WHERE SOCIETE = Olympic Sales) ;

Le rsultat obtenu est le suivant :

CLIENT_ID CONT_PRENOM CONT_NOM CONT_TELEPHON


E CONT_INFO
--------- ----------- -------- -------------
- ------------
118 Jerry Attwater 505-876-3456
Va jouer un rle

majeur dans la

mise en oeuvre du

Web sans fil.

Si vous utilisez une sous-requte dans une comparaison =, la liste


spcifie dans la sous-requte SELECT ne doit mentionner quune seule
colonne (par exemple CLIENT_ID). Lorsquelle est excute, elle doit
retourner une seule ligne de manire produire une valeur unique.
Dans cet exemple, je suppose que la table CLIENTS ne contient quune
ligne dont la valeur de la colonne SOCIETE est Olympic Sales. Si
linstruction CREATE TABLE spcifie la contrainte UNIQUE pour
SOCIETE, la sous-requte de lexemple prcdent retournera
systmatiquement une seule valeur (ou aucune). Toutefois, ce type de sous-
requte est largement utilis avec des colonnes qui ne sont pas spcifies
comme tant UNIQUE.
Vous ne pouvez alors que vous fier votre connaissance de la base de
donnes pour prsumer que la colonne nest pas duplique.
Si la colonne SOCIETE de plusieurs clients prend la valeur Olympic
Sales (peut-tre dans diffrentes rgions), la sous-requte gnrera une
erreur.
Par ailleurs, sil ny a aucun client pour la socit indique, la sous-requte
est traite comme si elle gnrait une valeur nulle et le rsultat de la
comparaison devient inconnu. Dans ce cas, la clause WHERE ne retourne
aucune ligne (car elle ne donne que les lignes pour lesquelles la condition
est satisfaite, et limine celles pour lesquelles la condition est fausse ou
indtermine). Cette situation peut survenir si une personne orthographie
mal le nom de la SOCIETE en tapant par exemple Olumpic Sales.

Mme si loprateur dgalit (=) est le plus utilis, vous pouvez utiliser
les cinq autres oprateurs de la mme manire. Pour chaque ligne de la
table spcifie dans linstruction englobant la clause FROM, la valeur
retourne par la sous-requte est compare celle de lexpression figurant
dans la clause WHERE de linstruction de niveau suprieur. Si la
comparaison renvoie une valeur True, la ligne est ajoute la table rsultat.
Vous pouvez vous assurer que la sous-requte retournera une seule valeur en
utilisant une fonction dagrgation. En effet, les fonctions dagrgation
retournent toujours une seule valeur (reportez-vous au Chapitre 3 pour plus
de dtails). Bien entendu, cette manire de procder nest utile que si vous
voulez le rsultat produit par une telle fonction.
Supposons maintenant que vous soyez commercial chez Zetec. Vous voulez
faire un bon chiffre daffaires (pour rgler quelques factures en retard) et
vous concentrez vos ventes sur le produit le plus cher de Zetec. Vous pouvez
identifier ce produit avec la requte suivante :

SELECT MODELE, NOM_PROD, PRIX


FROM PRODUITS
WHERE PRIX =
(SELECT MAX(PRIX)
FROM PRODUITS) ;

Dans cet exemple de requte imbrique, la sous-requte et linstruction qui


lenglobe travaillent sur la mme table. La sous-requte retourne une unique
valeur : le prix maximal trouv dans la table PRODUITS. La requte
externe retourne toutes les lignes de la table PRODUITS o Figure ce prix.
Lexemple suivant est une sous-requte qui utilise un oprateur de
comparaison autre que = :
SELECT MODELE, NOM_PROD, PRIX
FROM PRODUITS
WHERE PRIX <
(SELECT AVG(PRIX)
FROM PRODUITS) ;

La sous-requte retourne une valeur : le prix moyen de la table PRODUITS.


La requte externe retourne toutes les lignes de la table PRODUITS dans
lesquelles le prix est infrieur ou gal cette moyenne.
Dans le standard initial de SQL, une comparaison ne pouvait avoir quune
seule sous-requte, et celle-ci devait se placer droite de la comparaison.
SQL:1999 permet dutiliser des sous-requtes droite comme gauche de
loprateur de comparaison.

Les quantificateurs ALL, SOME et


ANY
Une autre manire de sassurer quune sous-requte retourne une seule
valeur consiste lintroduire avec un oprateur de comparaison quantifi.
Le quantificateur universel ALL et les quantificateurs existentiels SOME et
ANY associs un oprateur de comparaison traitent la liste retourne par
une sous-requte et la rduisent une seule valeur.
Vous allez maintenant voir comment ces quantificateurs affectent une
comparaison en examinant la base de donnes des parties compltes de
base-ball prsente au Chapitre 11.
Le contenu des deux tables est retourn par les deux requtes suivantes :

SELECT * FROM NATIONALE


PRENOM NOM PARTIES_COMPLETES
------ -------- -----------------
Sal Maglie 11
Don Newcombe 9
Sandy Koufax 13
Don Drysdale 12
Bob Turley 8
SELECT * FROM AMERICAINE
PRENOM NOM PARTIES_COMPLETES
------ -------- -----------------
Whitey Ford 12
Don Larson 10
Bob Turley 8
Allie Reynolds 14

En thorie, les lanceurs qui ont particip au plus grand nombre de parties
compltes sont les membres de la Ligue amricaine. Pour le vrifier, il
suffit de construire une requte qui retourne tous les lanceurs de cette ligue
qui ont particip plus de parties compltes que les lanceurs de la Ligue
nationale. Cette requte peut se formuler comme suit :

SELECT *
FROM AMERICAINE
WHERE PARTIES_COMPLETES > ALL
(SELECT PARTIES_COMPLETES FROM
NATIONALE) ;

Le rsultat est le suivant :

PRENOM NOM PARTIES_COMPLETES


------ -------- -----------------
Allie Reynolds 14

La sous-requte (SELECT PARTIES_COMPLETES FROM


NATIONALE) retourne les valeurs de la colonne PARTIES_COMPLETES
de tous les lanceurs de la Ligue nationale. Le quantificateur > ALL
indique quil ne faut retourner que les valeurs de PARTIES_COM-
PLETES de la table AMERICAINE qui sont suprieures toutes les
valeurs renvoyes par la sous-requte. La condition peut donc se traduire
par plus grande que la valeur la plus leve retourne par la sous-
requte . Dans notre cas, la valeur la plus leve retourne par la sous-
requte est 13 (Sandy Koudax). La seule ligne dans la table
AMERICAINE dont la valeur de la colonne PARTIES_COMPLETES est
suprieure 13 est celle dAllie Reynolds (il a particip 14 matches
entiers).
Et si votre thorie se rvlait fausse ? Dans ce cas, la requte suivante vous
signalera quaucun des lanceurs de la Ligue amricaine na particip plus
de parties compltes quun lanceur de la Ligue nationale (autrement dit quil
ny a aucune ligne retourner) :

SELECT *
FROM AMERICAINE
WHERE PARTIES_COMPLETES > ALL
(SELECT PARTIES_COMPLETES FROM NATIONALE) ;

Requtes imbriques servant de


test dexistence
Une requte retourne des donnes extraites de toutes les lignes de la table
qui satisfont aux conditions poses. Il arrive que de nombreuses lignes
soient retournes. Parfois, il y en a simplement une seule. Mais il est aussi
possible quaucune ligne ne satisfasse les conditions, et donc quaucune
ligne ne soit renvoye. Vous pouvez utiliser les prdicats EXISTS et NOT
EXISTS pour introduire une sous-requte. Ils vous indiqueront si la table
identifie dans la clause FROM satisfait ou non les conditions nonces
dans la clause WHERE.
Les sous-requtes introduites par EXISTS ou NOT EXISTS sont
fondamentalement diffrentes des autres sous-requtes prsentes dans ce
chapitre. Dans les exemples prcdents, SQL excute en premier la sous-
requte, puis utilise le rsultat de cette opration linstruction qui
lenglobe. Dun autre ct, EXISTS et NOT EXISTS sont des exemples
de sous-requtes corrles.
Une sous-requte corrle recherche tout dabord la table et la ligne
spcifie par linstruction englobante, puis excute la sous-requte sur la
ligne de la table qui correspond la ligne courante de la table de
linstruction de plus niveau.
La sous-requte retourne soit une ou plusieurs lignes, soit aucune. Si elle
renvoie au moins une ligne, le prdicat EXISTS est valid, et linstruction
englobante est excute. Dans les mmes conditions, le prdicat NOT
EXISTS ne sera pas valid et donc linstruction ne sera pas excute.
Lorsquune ligne de la table de linstruction englobante a t traite,
lopration se rpte pour la ligne suivante. Et ainsi de suite jusqu ce que
toutes les lignes de la table de linstruction englobante aient t passes en
revue.

EXISTS
Vous tes un vendeur de Zetec Corporation, et vous devez tlphoner tous
les contacts des clients de Zetec en Californie. Essayez la requte suivante :

SELECT *
FROM CONTACTS
WHERE EXISTS
(SELECT *
FROM CLIENTS
WHERE CLIENT_ETAT = CA
AND CONTACTS.CLIENT_ID =
CLIENTS.CLIENT_ID) ;

Remarquez la prsence de CLIENT_ID qui rfrence une colonne de la


requte externe et la compare une autre colonne (CLIENTS.
CLIENT_ID) de la requte interne. Pour chaque ligne de la table
CONTACTS traite par la requte externe, vous valuez la requte interne
en utilisant sa valeur CLIENT_ID dans la clause WHERE de la requte
interne.
Voici comment :
1. La colonne CLIENT_ID relie les tables CONTACTS et
CLIENTS.

2. SQL se place sur le premier enregistrement de la table


CONTACT. Il trouve la ligne de la table CLIENTS qui possde
le mme CLIENT_ID, puis teste le champ CLIENT_ETAT de
cette ligne.

3. Si CLIENTS. CLIENT_ETAT = CA, la ligne courante de


CONTACTS est ajoute la table rsultat.

4. Lenregistrement suivant est trait de la mme manire, et


ainsi de suite jusqu ce que la table CONTACTS ait t
entirement parcourue.

5. Comme la requte spcifie SELECT * FROM CONTACTS,


tous les champs de la table sont affichs, y compris le nom
et le numro de tlphone dun contact.

NOT EXISTS
Dans lexemple prcdent, le vendeur de Zetec recherchait les noms et les
numros de tlphone des contacts de tous les clients rsidant en Californie.
Imaginez quun second vendeur soit responsable de tous les tats-Unis
lexception de la Californie. Il peut rcuprer la liste de ses contacts en
utilisant NOT EXISTS dans une requte semblable la prcdente :

SELECT *
FROM CONTACTS
WHERE NOT EXISTS
(SELECT *
FROM CLIENTS
WHERE CLIENT_ETAT = CA
AND CONTACTS.CLIENT_ID =
CLIENT.CLI-
ENT_ID) ;

Chaque ligne de CONTACTS pour laquelle la sous-requte ne retourne rien


est ajoute la table rsultat.
Autres sous-requtes corrles
Comme je lai dj expliqu plus haut, les sous-requtes introduites par IN
ou par un oprateur de comparaison nont pas besoin dtre des requtes
corrles. Mais elles peuvent ltre.

Sous-requtes corrles introduites par IN


Dans la section intitule Les sous-requtes introduites par le mot cl
IN , jai expliqu comment des sous-requtes non corrles peuvent tre
utilises avec le prdicat IN. Pour comprendre maintenant comment une
sous-requte corrle est capable dutiliser le prdicat IN, posons-nous la
mme question quavec le prdicat EXISTS : Quels sont les noms et
numros de tlphone des contacts de Zetec en Californie ? Vous pouvez
rpondre cette question avec une sous-requte corrle IN :

SELECT *
FROM CONTACTS
WHERE CA IN
(SELECT CLIENT_ETAT
FROM CLIENTS
WHERE CONTACTS.CLIENT_ID =
CLIENTS.CLIENT_ID) ;

Linstruction est value pour chaque enregistrement de la table


CONTACTS. Si, pour cet enregistrement, les numros CLIENT_ID dans
CONTACTS et dans CLIENTS sont identiques, la valeur de CLIENTS.
CLIENT_ETAT est compare CA. Le rsultat de la sous-requte est
une liste qui contient au plus un lment. Si cet lment est CA, la clause
WHERE de linstruction de niveau suprieur est valide et la ligne est
ajoute dans la table rsultat.

Sous-requtes introduites par des oprateurs de


comparaison
Une sous-requte corrle peut tre galement introduite par lun des six
oprateurs de comparaison, comme lillustre lexemple suivant.
Zetec verse des primes ses vendeurs en fonction du volume des ventes
quils ralisent par mois. Plus ce volume est important, plus le pourcentage
de la prime est important. Ce pourcentage est conserv dans une table
appele PRIMES :

MONTANT_MIN MONTANT_MAX PCT_PRIME


----------- ----------- ---------
0.00 24999.99 0.
25000.00 49999.99 0.1
50000.00 99999.99 0.2
100000.00 249999.99 0.3
250000.00 499999.99 0.4
500000.00 749999.99 0.5
750000.00 999999.99 0.6

Si les ventes mensuelles dun vendeur sont comprises entre 100


000 et 249 999,99 units, le pourcentage de la prime slve 0,3 % des
ventes.
Les ventes sont enregistres dans une table appele TRANSMASTER :

TRANSMASTER
-----------
Colonne Type Contraintes
------------ -------- -----------
TRANS_I INTEGER PRIMARY KEY
CLIENT_ID INTEGER FOREIGN KEY
EMP_ID INTEGER FOREIGN KEY
TRANS_DATE DATE
MONTANT_NET NUMERIC
PORT NUMERIC
TAXES NUMERIC
TOTALFACTURE NUMERIC

La prime est base sur la somme des champs MONTANT_NET de toutes les
transactions effectues par un vendeur durant le mois. Vous pouvez calculer
la prime dun vendeur en utilisant une sous-requte corrle qui fait appel
aux oprateurs de comparaison :

SELECT PCT_PRIME
FROM PRIMES
WHERE MONTANT_MIN <=
(SELECT SUM (MONTANT_NET)

FROM TRANSMASTER
WHERE EMP_ID = 133)
AND MONTANT_MAX >=
(SELECT SUM (MONTANT_NET)
FROM TRANSMASTER

WHERE EMP_ID = 133) ;

Cette requte est intressante, car elle contient deux sous-requtes relies
par le connecteur logique AND. Les sous-requtes utilisent loprateur
dagrgation SUM qui retourne une seule valeur : le montant total des
ventes ralises par le vendeur numro 133. Cette valeur est ensuite
compare aux colonnes MONTANT_MIN et MONTANT_MAX de la table
PRIMES pour obtenir la prime de ce commercial.
Si vous ne connaissez pas la valeur EMP_ID, mais le nom du vendeur, vous
obtiendrez le mme rsultat avec une requte un peu plus complexe :

SELECT PCT_PRIME
FROM PRIMES
WHERE MONTANT_MIN <=
(SELECT SUM (MONTANT_NET)
FROM TRANSMASTER
WHERE EMP_ID = 133)
AND MONTANT_MAX >=
(SELECT SUM (MONTANT_NET)
FROM TRANSMASTER
WHERE EMP_ID = 133) ;

Cet exemple utilise des sous-requtes imbriques dans des sous-requtes,


qui sont leur tour imbriques dans une requte globale pour calculer la
prime de lemploy dnomm Coffin. Cette structure ne fonctionnera que si
vous tes absolument certain que la socit emploie un et un seul vendeur
appel Coffin. Si lentreprise emploie plusieurs personnes portant le mme
nom, vous pouvez ajouter des termes dans la clause WHERE de la sous-
requte la plus imbrique jusqu ce que vous soyez sr quune seule ligne
de la table EMPLOYES est slectionne.

Sous-requtes dans une clause HAVING


Exactement comme dans une clause WHERE, vous pouvez utiliser une sous-
requte corrle dans une clause HAVING. Comme je lexplique au
Chapitre 9, une clause HAVING est gnralement prcde dune clause
GROUP BY. La clause HAVING se comporte comme un filtre qui crme
les groupes crs par la clause GROUP BY. Ceux qui ne remplissent pas
les conditions de la clause HAVING ne figurent pas dans le rsultat. Dans
ce cas, la clause HAVING est employe pour chaque groupe cr par la
clause GROUP BY.

En labsence de GROUP BY, la clause HAVING est excute pour


lensemble des lignes retourn par la clause WHERE, dont le rsultat est
alors assimil un seul groupe. Si ni WHERE ni GROUP BY ne sont
prsentes, la clause HAVING est excute pour toute la table :

SELECT PCT_PRIME
FROM PRIMES
WHERE MONTANT_MIN <=
(SELECT SUM (MONTANT_NET)
FROM TRANSMASTER
WHERE EMP_ID =
(SELECT EMP_ID
FROM EMPLOYES
WHERE EMP_NOM = Coffin))
AND MONTANT_MAX >=
(SELECT SUM (MONTANT_NET)
FROM TRANSMASTER
WHERE EMP_ID =
(SELECT EMP_ID

FROM EMPLOYES
WHERE EMP_NOM = Coffin));

Cette requte utilise deux alias pour la mme table afin de pouvoir
rcuprer le numro didentifiant de tous les vendeurs dont le volume des
ventes est au moins deux fois gal au volume des ventes moyennes de tous
les autres vendeurs. Cette requte fonctionne comme suit :

1 La requte externe regroupe les lignes de TRANSMASTER


par EMP_ID. Cest le travail des clauses SELECT, FROM et
GROUP BY.

2. La clause HAVING filtre ces groupes et calcule pour chaque


groupe le MAX de la colonne MONTANT_NET des lignes de
ce groupe.

3. La requte interne value deux fois le MONTANT_NET


moyen de toutes les lignes de TRANSMASTER dont le
EMP_ID est diffrent du EMP_ID du groupe courant de la
requte externe.

Remarquez que, dans la dernire ligne, vous devez


rfrencer deux valeurs EMP_ID diffrentes, si bien quil
vous faut utiliser des alias diffrents de TRANSMASTER dans
les clauses FROM des requtes internes et externes.

4. Vous pouvez ensuite utiliser ces alias dans la comparaison


de la dernire ligne de la requte pour indiquer que vous
rfrencez la fois le EMP_ID de la ligne courante de la
sous-requte interne (TM2. EMP_ID) et le EMP_ID du
groupe courant de la sous-requte externe (TM1. EMP_ID).

Instructions UPDATE, DELETE et


INSERT
linstar des instructions SELECT, les instructions UPDATE, DELETE et
INSERT peuvent galement comprendre des clauses WHERE. Ces clauses
WHERE sont aussi susceptibles de contenir des sous-requtes, exactement
comme les clauses WHERE des instructions SELECT.
Par exemple, Zetec vient tout juste de raliser une vente importante avec
Olympic Sales et veut rtroactivement concder Olympic une ristourne
de 10 % sur tous ses achats du mois dernier. Vous pouvez accorder ce crdit
avec une instruction UPDATE :

UPDATE TRANSMASTER
SET MONTANT_NET = MONTANT_NET * 0.9
WHERE CLIENT_ID =
(SELECT CLIENT_ID
FROM CLIENTS
WHERE COMPAGNIE = Olympic Sales) ;

Vous pouvez galement utiliser une sous-requte corrle dans une


instruction UPDATE. Supposez que la table CLIENTS contienne une
colonne MOIS_DERNIER_MAX et que Zetec accorde un crdit de 10 %
aux clients dont les achats ont dpass MOIS_ DERNIER_MAX :

UPDATE TRANSMASTER TM
SET MONTANT_NET = MONTANT_NET * 0.9
WHERE MONTANT_NET >
(SELECT MOIS_DERNIER_MAX
FROM CLIENT C
WHERE C.CLIENT_ID = TM.CLIENT_ID) ;
Remarquez que cette sous-requte est corrle. La clause WHERE de la
dernire ligne rfrence la fois le CLIENT_ID de la ligne CLIENTS de
la sous-requte et le CLIENT_ID de la ligne TRANSMASTER courante
mettre jour.
Une sous-requte dans une instruction UPDATE peut galement rfrencer
la table qui est en cours de mise jour. Supposez que Zetec accorde une
ristourne de 10 % aux clients dont les achats ont dpass 10 000 units :

UPDATE TRANSMASTER TM1


SET MONTANT_NET = MONTANT_NET * 0.9
WHERE 10000 <
(SELECT SUM(MONTANT_NET)
FROM TRANSMASTER TM2
WHERE TM1.CLIENT_ID = TM2.CLIENT_ID) ;

La sous-requte interne calcule le total (SUM) de la colonne MON-


TANT_NET pour toutes les lignes de TRANSMASTER relatives un
mme client. Concrtement, supposons que le client vrifiant CLIENT_ID
= 37 possde quatre lignes dans TRANSMASTER avec les valeurs
suivantes pour MONTANT_NET : 3 000, 5 000, 2 000 et 1 000. Le total du
montant net pour ce code client est donc de 11 000.
Lordre dans lequel linstruction UPDATE traite les lignes est dfini par
votre implmentation et donc nest pas en rgle gnrale prvisible. Lordre
peut varier en fonction de la manire dont les lignes sont agences dans le
disque. Supposez que votre implmentation prenne les lignes de
TRANSMASTER dans cet ordre : celle dont MONTANT_NET
vaut 3 000, puis celle dont MONTANT_NET vaut 5 000, et ainsi de
suite. Une fois les trois premires lignes de CLIENT_ID 37 traites, leur
valeur MONTANT_ NET devient 2 700 (90 % de 3 000), 4 500 (90 %
de 5 000) et 1 800 (90 % de 2 000). Lorsque vous allez passer la dernire
ligne de TRANSMASTER pour le CLIENT_ID 37 pour laquelle MON-
TANT_NET vaut 1 000, la SOMME retourne par la sous-requte
semblera valoir 10 000, cest--dire la SOMME des nouvelles valeurs de
MONTANT_NET des trois premires lignes du CLIENT_ID 37 et de
lancienne valeur de MONTANT_NET de la dernire ligne du
CLIENT_ID 37. Par consquent, la dernire ligne du CLIENT_
ID 37 nest apparemment pas mise jour, car la comparaison avec cette
somme nest pas valide (10 000 nest pas infrieur SELECT (SUM
(MONTANT_NET)). Mais ce nest pas ainsi que fonctionne une
instruction UPDATE lorsquune sous-requte rfrence une table qui est en
cours de mise jour.
Toutes les valuations des sous-requtes dune instruction UPDATE font
rfrence aux anciennes valeurs de la table mettre jour. Dans le
prcdent UPDATE pour le CLIENT_ID 37, la sous-requte
retourne 11 000, qui est la somme originale.
La sous-requte dune clause WHERE fonctionne exactement de la mme
manire quune instruction SELECT ou une instruction UPDATE. Il en va
de mme pour DELETE ou INSERT. Pour supprimer toutes les
transactions relatives Olympic, utilisez cette instruction :

DELETE TRANSMASTER
WHERE CLIENT_ID =
(SELECT CLIENT_ID
FROM CLIENTS
WHERE COMPAGNIE = Olympic Sales) ;

Comme dans le cas dUPDATE, les sous-requtes DELETE peuvent


galement tre corrles et rfrences dans la table supprimer. Les rgles
qui valent dans ce cas sont identiques celles qui sappliquent aux sous-
requtes UPDATE. Supposons que vous vouliez supprimer toutes les lignes
de TRANSMASTER pour les clients dont le MONTANT_NET est suprieur
10 000 units :

UPDATE TRANSMASTER TM1


WHERE 10000 < (SELECT SUM(NET_AMOUNT)
FROM TRANSMASTER TM2
WHERE TM1. CLIENT_ID = TM2. CLIENT_ID);
Cette requte supprime toutes les lignes de TRANSMASTER pour le
CLIENT_ID 37 ainsi que tous les autres clients dont les achats
dpassent 10 000 units. Toutes les rfrences TRANSMASTER dans la
sous-requte portent sur le contenu de cette table avant toute suppression
opre par linstruction. Par consquent, et mme si vous tes en train de
supprimer la dernire ligne de TRANSMASTER pour le CLIENT_ID 37,
la sous-requte sera value sur la base de la table TRANSMASTER
initiale et retournera 11 000.
Lorsque vous mettez jour, supprimez ou insrez des enregistrements dans
une base de donnes, vous prenez le risque de rendre inconsistantes les
donnes de cette table avec les autres tables de la base. Cette inconsistance,
appele anomalie de modification, est prsente au Chapitre 5. Si vous
supprimez des enregistrements de TRANSMASTER et quune table
TRANSDETAIL dpend de TRANSMASTER, vous devez supprimer les
enregistrements correspondants dans TRANSDETAIL. Cette opration est
appele suppression en cascade, car leffacement dun enregistrement
parent est rpercut sur les enregistrements enfants qui lui sont associs. Si
ces suppressions navaient pas lieu, les enregistrements enfants
deviendraient orphelins.
Si votre implmentation ne prend pas en charge les suppressions en
cascade, vous devrez les faire vous-mme. Dans ce cas, supprimez dabord
les enregistrements de la table enfant, puis les enregistrements
correspondants de la table parent. Vous naurez pas ainsi denregistrements
orphelins dans la table enfant.

Rcuprer des modifications avec le


langage de manipulation de donnes
Dans les prcdentes sections, vous avez appris comment une instruction
UPDATE, DELETE ou INSERT peut inclure une instruction imbrique
dans une clause WHERE. SQL:2011 permet dimbriquer une commande de
manipulation de donnes (telles que UPDATE, INSERT, DELETE ou
MERGE) dans une instruction SELECT. Cette fonctionnalit est appele
instruction DML.
Une autre faon de modifier des donnes consiste considrer une table
avant toute opration DELETE, INSERT, ou UPDATE. Nommez la table
avant toute modification vieille table et la table aprs modification nouvelle
table. Pendant les modifications, des tables auxiliaires, appeles tables
delta, sont cres. Une opration DELETE cre une vieille table delta qui
contient les lignes supprimer. Une opration INSERT cre une nouvelle
table delta qui contient les lignes insrer. Une opration UPDATE cre en
mme temps une vieille et une nouvelle table delta, la vieille pour les lignes
supprimer et la nouvelle pour les lignes remplacer.
Avec une DML vous pouvez rcuprer les informations des tables delta.
Supposez que vous supprimiez tous les produits PRODUIT_ID
entre 1 000 et 1 399 de la ligne produit et que vous souhaitiez obtenir
le compte-rendu exact de ce qui se passe quand tous ces produits sont
supprims. Vous pourriez utiliser les lignes de code ci-dessous :

SELECT Oldtable.PRODUIT_ID
FROM OLD TABLE (DELETE FROM PRODUIT
WHERE PRODUIT_ID BETWEEN 1000
AND 1399)
AS Oldtable ;

Dans cet exemple, le mot cl OLD TABLE spcifie que le rsultat de


SELECT se trouve dans la vieille table delta. Le rsultat est la liste des
numros de produits supprims.
Vous pouvez aussi rcuprer une liste dune nouvelle table delta avec le mot
cl NEW TABLE qui affiche les numros de PRO-DUIT_ID des lignes
insres par une opration INSERT ou mises jour par une opration
UPDATE. Comme une opration UPDATE cre aussi bien une vieille
quune nouvelle table, vous pouvez rcuprer le contenu de lune ou de
lautre ou encore des deux avec une DML.
Chapitre 13
Requtes rcursives
DANS CE CHAPITRE :
Comprendre la rcursivit.

Dfinir des requtes rcursives.

Savoir utiliser des requtes rcursives.

L
une des principales critiques formules lencontre de SQL, jusqu sa
version SQL-92 incluse, tait son incapacit implmenter des
traitements rcursifs. De nombreux problmes sont difficiles rsoudre
sans recourir la rcursivit. Les extensions ajoutes
SQL:1999 permettent deffectuer des requtes rcursives, accroissant ainsi
la puissance du langage. Si limplmentation de SQL que vous utilisez
dispose de ces extensions, vous serez en mesure de rsoudre nombre de
nouvelles classes de problmes. Cependant, comme la rcursivit nest pas
une fonctionnalit obligatoire de SQL, de nombreuses implmentations ne
lincluent pas.

Quest-ce que la rcursivit ?


La notion de rcursivit est apparue il y a bien longtemps dans des langages
de programmation tels que Logo, LISP et C++. Dans ces langages, vous
pouvez dfinir une fonction (ensemble constitu dune ou plusieurs
commandes) qui effectue une certaine opration. Le programme principal
invoque la fonction en utilisant une commande dite appel de fonction. Si,
au cours de cette opration, la fonction sappelle elle-mme, vous tes
confront la forme la plus lmentaire de rcursivit.
Un programme trs simple dont une des fonctions utilise la rcursivit peut
suffire expliquer les joies et les peines de cette technique. Le programme
suivant, crit en C++, dessine une spirale lcran. Il comprend trois
fonctions :
La fonction ligne (n) trace une ligne de n units de long.

La fonction tourner_gauche (d) fait tourner la ligne de d


degrs dans le sens inverse des aiguilles dune montre.

La fonction spirale (segment) que lon peut dfinir


comme suit :

void spirale(int segment)


{
ligne(segment)
tourner_gauche(90)
spirale(segment + 1)
} ;

Si nous appelons spirale (1) depuis le programme principal, les


actions suivantes sont entreprises :

spirale (1) trace unelignede une unitde long vers le


haut de lcran.

spirale (1) tourne de 90 degrs.

spirale (1) appelle spirale (2).

spirale (2) trace une ligne de deux units de long


vers le ct gauche de lcran.

spirale (2) tourne de 90 degrs.

spirale (2) appelle spirale (3).

Et ainsi de suite.
Pour finir, le programme gnre la spirale reprsente sur la Figure 13.1.
Houston, nous avons un problme
Certes, notre situation nest pas aussi critique que celle dApollo 13 lorsque
les astronautes durent rejoindre la Terre alors que leur principale rserve
doxygne avait explos dans lespace. Mais un problme existe. Notre
petit programme chappe notre contrle. Il sappelle sans cesse pour
tracer des lignes de plus en plus longues. Il continuera ainsi jusqu ce quil
ait puis les ressources de lordinateur, ce qui gnrera un message
derreur. Dans le pire des cas, lordinateur se plantera.

FIGURE 13.1 Rsultat de lappel spirale (1).

Le plantage nest pas une option


Ce scnario vous explique lun des dangers de la rcursivit. Un
programme crit pour sappeler invoque une nouvelle instance de lui-mme,
qui son tour fait appel une autre instance de lui-mme, et ainsi de suite
jusqu linfini. Ce qui nest gnralement pas ce que vous souhaitez.
Pour pallier ce problme, les programmeurs intgrent une condition de
sortie dans la fonction rcursive, cest--dire une limite la profondeur des
appels rcursifs. De cette manire, le programme peut effectuer laction
dsire et se termine sans encombre. Nous allons inclure une telle condition
de sortie dans notre programme de dessin de spirale pour sauvegarder les
ressources de lordinateur et viter de plonger llite des programmeurs
dans une dpression noire :

void spirale2(int segment)


{
if (segment <= 10)
{
ligne(segment)
tourner_gauche(90)
spirale2(segment + 1)
}
} ;

Lorsque vous faites appel spirale2 (1), la fonction sexcute, puis


sappelle (rcursivement) jusqu ce que la valeur du segment dpasse 10.
Lorsque segment =11, la structure if (segment<=10) retourne
une valeur Faux et le code lintrieur des accolades nest pas excut. Le
contrle revient alors lappel prcdent de spirale2, puis revient
lappel prcdant cet appel prcdent, et ainsi de suite jusqu ce que le
contrle revienne au premier appel, ce qui met fin au programme.
La Figure 13.2 illustre cette squence dappels.

FIGURE 13.2 Une srie dappels descendants puis ascendants pour terminer le
programme dans de bonnes conditions.

Chaque fois quune fonction sappelle elle-mme, elle vous enfonce


dun niveau supplmentaire sous le programme principal qui constitue le
point de dpart de lopration. Pour que le programme principal puisse
reprendre son cours normal, litration la plus profonde doit un
moment donn remonter dun niveau, cest--dire redonner le contrle
litration qui la appele. Cette itration fera de mme, et ainsi de suite
jusqu revenir au premier appel, puis au programme principal.
La rcursivit est un outil puissant pour excuter du code de manire
rptitive lorsque vous ne connaissez pas lavance le nombre de boucles
parcourir. Il est idal pour effectuer des recherches dans des structures
arborescentes, des circuits lectroniques complexes ou encore des rseaux
de distribution possdant de multiples niveaux.

Quest-ce quune requte


rcursive ?
Une requte rcursive est une requte qui dpend fonctionnellement delle-
mme. La forme la plus simple de ce type de dpendance fonctionnelle est
la suivante : une requte Q1 inclut un appel elle-mme dans le corps de
son expression. La situation devient plus complexe lorsque la requte
Q1 dpend de la requte Q2, qui son tour dpend de la requte Q1. On
parle l encore de dpendance fonctionnelle et de rcursivit, quel que soit
le nombre de requtes intercales entre le premier et le second appel une
mme requte.

Quand utiliser une requte


rcursive ?
Les requtes rcursives vous permettent de gagner du temps et dviter bien
des frustrations lorsque vous essayez de rsoudre certains problmes.
Supposons par exemple que vous ayez gagn un passe qui vous permet de
voyager gratuitement avec la compagnie arienne Vannevar Airlines. La
premire question que vous vous posez est : O puis-je aller
gratuitement ? La table VOLS contient tous les vols proposs par
Vannevar. Le Tableau 13.1 vous indique leurs numros, le lieu de dpart et
le lieu de destination.

TABLEAU 13.1 Les vols proposs par Vannevar Airlines.

No de vol Dpart Arrive


3141 Portland Orange County

2173 Portland Charlotte

623 Portland Daytona Beach

5440 Orange County Montgomery

221 Charlotte Memphis

32 Memphis Champaign

981 Montgomery Memphis

La Figure 13.3 illustre ces routes sur une carte des tats-Unis.
Pour commencer, vous allez crer une table dans la base de donnes VOLS
de la manire suivante :

CREATE TABLE VOLS (


NoVol INTEGER NOT NULL,

Source CHARACTER (30),


FIGURE 13.3 La carte des vols de Vannevar Airlines.

Destination CHARACTER (30)


);

Vous pourrez ensuite la remplir laide des donnes listes dans le


Tableau 13.1.
Supposons alors que vous partiez de Portland pour rendre visite un ami
qui vit Montgomery. Vous vous demandez tout naturellement : Quelles
villes puis-je rejoindre depuis Portland par des vols de Vannevar ? et
Quelles villes puis-je rejoindre depuis Montgomery par des vols de la
mme compagnie arienne ? Vous pouvez relier certaines villes sans
escale et dautres pas. Pour obtenir la liste de toutes les destinations vers
lesquelles vous pouvez vous rendre partir dune ville donne (via les vols
de Vannevar, videmment), vous pouvez bien sr procder requte aprs
requte, comme ci-dessous. Sauf que vous irez peut-tre plus vite avec un
papier et un crayon...

La manire forte
Pour obtenir le rsultat escompt, et supposer que vous fassiez preuve de
patience, vous pouvez effectuer une srie de requtes en prenant Portland
comme point de dpart :
SELECT Destination FROM VOLS WHERE Source =
Portland ;

Cette premire requte va retourner Orange County, Charlotte et Daytona


Beach. Votre deuxime requte peut utiliser le premier de ces rsultats
comme point de dpart :

SELECT Destination FROM VOLS WHERE Source =


Orange Coun-
ty;

Cette deuxime requte renvoie Montgomery. Votre troisime requte va


revenir au rsultat de la premire requte et utiliser le deuxime rsultat
comme point de dpart :

SELECT Destination FROM VOLS WHERE Source =


Charlotte ;

La troisime requte donne Memphis. Votre quatrime requte revient au


rsultat de la premire requte et utilise le rsultat restant comme point de
dpart :

SELECT Destination FROM VOLS WHERE Source =


Daytona
Beach ;

Hlas ! Cette dernire requte procure un rsultat nul, car Vannevar ne


propose pas de vol au dpart de Daytona Beach. Mais la deuxime requte
a retourn une autre ville (Montgomery) qui peut servir de point de dpart
dans votre cinquime requte :

SELECT Destination FROM VOLS WHERE Source =


Montgomery
;

La rponse est cette fois Memphis. Ce rsultat est inutile, car vous savez
dj que Memphis est lune des villes o vous pouvez aller (dans ce cas,
via Charlotte). Par contre, vous pouvez lutiliser comme point de dpart
dune autre requte :

SELECT Destination FROM VOLS WHERE Source =


Memphis;

La requte retourne Champaign, que vous pouvez ajouter la liste des villes
joignables (mme sil faut deux escales pour vous y rendre). Si vous avez
envie de dcouvrir un maximum daroports, vous pouvez tout aussi bien
utiliser Champaign comme nouveau point de dpart :

SELECT Destination FROM VOLS WHERE Source =


Champaign;

Cette requte retourne une valeur nulle, car Vannevar ne propose pas de vol
au dpart de Champaign. (Sept requtes plus tard ! Tenez bon !) Vannevar ne
propose aucun vol au dpart de Daytona Beach, de sorte que si vous vous y
rendez, vous ne pourrez plus en partir ! Il ne vous restera plus qu vous
inscrire luniversit de lIllinois pour suivre quelques cours sur les bases
de donnes.
En appliquant cette mthode, vous finirez (normalement) par russir
rpondre la question : Quelles sont les villes que je peux rejoindre
depuis Portland ? Mais lenchanement de requtes dont le rsultat dpend
de la prcdente se rvle compliqu, pnible et trs coteux en temps de
calcul.

conomiser du temps avec une


requte rcursive
La solution bien plus simple consiste crire une seule requte rcursive
qui effectuera toute la recherche en une seule opration. Voici la syntaxe
dune telle requte :

WITH RECURSIVE
JoignableDepuis (Source, Destination)
AS (SELECT Source, Destination
FROM VOLS
UNION
SELECT sr.Source, dt.Destination
FROM JoignableDepuis sr, VOLS dt
WHERE sr.Destination = dt.Source
)
SELECT * FROM JoignableDepuis
WHERE Source = Portland ;

Lors du premier passage rcursif, VOLS contient sept lignes et


JOIGNABLEDEPUIS aucune. Loprateur UNION prend les sept lignes de
VOLS et les copie dans JOIGNABLEDEPUIS. ce stade,
JOIGNABLEDEPUIS contient les donnes indiques dans le Tableau 13.2.
Comme je lai dj dit, la rcursivit ne fait pas partie de SQL, et par
consquent certaines implmentations ne peuvent pas linclure.

TABLEAU 13.2 Le contenu de JOIGNABLEDEPUIS aprs un passage rcursif.

Dpart Arrive

Portland Orange County

Portland Charlotte

Portland Daytona Beach

Orange County Montgomery

Charlotte Memphis

Memphis Champaign

Montgomery Memphis

Au deuxime passage rcursif, les choses commencent devenir vraiment


intressantes. La clause WHERE (WHERE sr. Destination = dt.
Source) signifie que vous recherchez seulement les lignes dont le champ
Destination de la table JOIGNABLEDEPUIS est gal au champ
Source de la table VOLS. Pour chacune de ces lignes, vous prenez le
champ Source de la table JOIGNABLEDEPUIS et le champ Destination de
la table VOLS, puis vous ajoutez ces deux champs JOIGNABLEDEPUIS
pour former une nouvelle ligne. Le Tableau 13.3 vous prsente le rsultat
produit par cette itration.
Ces rsultats sont bien plus utiles. JOIGNABLEDEPUIS contient maintenant
toutes les villes Destination que vous pouvez rejoindre depuis nimporte
quelle ville Source, avec ou sans escale. Le passage rcursif suivant permet
de traiter tous les voyages deux escales et ainsi de suite jusqu ce que
toutes les villes de destination aient t atteintes.
Une fois la recherche rcursive termine, la troisime et dernire instruction
SELECT (qui se trouve hors de lappel rcursif) extrait de
JOIGNABLEDEPUIS les villes que vous pouvez rejoindre depuis Portland
par un vol Vannevar. Dans cet exemple, les six autres villes peuvent tre
jointes depuis Portland (ventuellement en quelques bonds ariens).

TABLEAU 13.3 Le contenu de JOIGNABLEDEPUIS aprs deux passages rcursifs.

Dpart Arrive

Portland Orange County

Portland Charlotte

Portland Daytona Beach

Orange County Montgomery

Charlotte Memphis

Memphis Champaign

Montgomery Memphis

Portland Montgomery

Portland Memphis

Orange County Memphis


Charlotte Champaign

Certes, le code de la requte rcursive ne parat pas plus simple que celui
des sept requtes quil remplace. Mais il prsente deux avantages :

Une fois son excution lance, il effectue toute la


recherche sans intervention externe.

Il peut faire le travail trs vite.

Supposez que vous traitiez avec une compagnie arienne relle qui dessert
bien plus de villes que Vannevar : plus il y aura de destinations, plus vous
aurez avantage utiliser la mthode rcursive.
En quoi cette requte est-elle rcursive ? Nous avons dfini
JOIGNABLEDEPUIS en faisant rfrence elle-mme. La partie rcursive
de la dfinition se trouve dans la deuxime instruction SELECT, celle qui
est juste aprs lappel UNION. JOIGNABLEDEPUIS est une table
temporaire qui se remplit progressivement de donnes tandis que se
succdent les passages rcursifs.
La recherche se poursuit jusqu ce que toutes les destinations possibles
aient t ajoutes JOIGNABLEDEPUIS. Les doublons sont tous limins,
car loprateur UNION nintgre pas les lignes redondantes dans la table
rsultat. Une fois la recherche rcursive acheve, JOIGNABLEDEPUIS
contient toutes les destinations que vous pouvez rejoindre depuis nimporte
quelle ville de dpart. La troisime et dernire instruction SELECT fournit
enfin la liste des villes accessibles depuis Portland. Bon voyage !

quoi dautre peut me servir une


requte rcursive ?
Tout problme que vous pouvez reprsenter sous la forme dune structure
arborescente peut ventuellement tre rsolu laide dune requte
rcursive. Une application industrielle des plus classiques est le processus
de conversion dune matire premire en produit fini. Supposez que votre
entreprise fabrique un nouveau modle de voiture moteur hybride essence
et lectrique. Un tel vhicule est compos de nombreuses parties (moteur,
batterie, etc.) qui sont leur tour composes de nombreuses pices plus
petites (lectrodes, etc.), qui sont leur tour composes de nombreux
lments encore plus petits.
Il est relativement difficile de grer correctement ces parties de parties dans
une base de donnes relationnelle qui ne sait pas utiliser la rcursivit.
Celle-ci vous permet de partir du vhicule complet et de vous frayer un
chemin jusquau plus minuscule des composants. En faisant appel la
structure WITH RECURSIVE, vous pourrez retrouver en peu de temps les
spcifications de la vis platine qui maintient llectrode ngative de la
batterie auxiliaire.
La rcursivit est galement un procd naturel pour rsoudre un problme
de type Et si ? . Dans lexemple de Vannevar Airlines, et si la direction
dcide de ne plus desservir Charlotte depuis Portland, en quoi cela
affectera-t-il la liste des villes que vous pouvez rejoindre depuis Portland ?
Une requte rcursive vous fournira rapidement la rponse.
IV
Contrler les oprations

DANS CETTE PARTIE :

Contrler laccs.

Protger les donnes de la corruption.

Appliquer des langages procduraux.


Chapitre 14
Protger une base de donnes
DANS CE CHAPITRE :
Contrler laccs aux tables dune base de donnes.

Spcifier qui a accs quoi.

Accorder des privilges daccs.

Retirer des privilges daccs.

Empcher les accs non autoriss.

Transmettre le pouvoir daccorder des privilges.

T
out administrateur systme qui se respecte doit connatre les divers
aspects du fonctionnement dune base de donnes. Cest pourquoi jai
trait dans les chapitres prcdents des parties de SQL qui servent
crer et manipuler des bases de donnes, puis (au Chapitre 3) prsent les
fonctions de SQL qui permettent de protger les bases de donnes de divers
sinistres. Dans ce chapitre, je vais examiner plus en dtail les dommages
susceptibles dtre engendrs par une mauvaise utilisation.
Le responsable en charge dune base de donnes peut dsigner les
personnes qui y ont accs, mais aussi spcifier le niveau de leurs
autorisations en leur accordant ou en leur retirant le droit daccder
certaines parties du systme. Ladministrateur systme a mme le pouvoir
de transmettre (ou de retirer) une partie de ses pouvoirs en dlguant (ou
refusant) dautres la possibilit daccorder (ou non) certains privilges
des utilisateurs. Pour peu que vous sachiez les utiliser correctement, les
outils de SQL lis la scurit se rvlent particulirement efficaces pour
protger des donnes importantes. Par contre, sils sont mal employs, ces
mmes outils peuvent empcher des utilisateurs lgitimes de faire leur
travail.
Les bases de donnes contiennent souvent des informations destines
rester confidentielles, ou du moins accessibles uniquement des utilisateurs
autoriss. Cest pourquoi SQL propose toute une palette de niveaux daccs.
Cela peut aller de tout rien, avec diffrents degrs intermdiaires. Comme
il a le pouvoir de contrler avec prcision les oprations auxquelles ont
accs les utilisateurs, ladministrateur de la base de donnes peut leur
accorder laccs toutes les donnes dont ils ont besoin pour travailler, tout
en leur interdisant de voir ou de manipuler certaines parties de la base de
donnes.

Le langage de contrle de donnes


de SQL (DCL)
Les instructions SQL que vous utilisez pour crer des bases de donnes
forment le langage de dfinition de donnes (DDL, Data Definition
Language). Une fois la base de donnes cre, vous pouvez utiliser un autre
ensemble dinstructions SQL connu sous le nom de langage de
manipulation de donnes (DML, Data Manipulation Language) pour
ajouter, supprimer ou modifier des donnes. SQL comprend galement une
srie dinstructions qui nappartiennent aucune de ces deux catgories.
Les programmeurs sy rfrent quelquefois en les dsignant collectivement
sous le nom de langage de contrle de donnes (DCL, Data Control
Language). Les instructions DCL servent principalement protger la base
de donnes contre les accs non autoriss, quils trouvent leur origine dans
une interaction fcheuse entre plusieurs utilisateurs de la base ou une panne
matrielle. Dans ce chapitre, je vais vous expliquer comment vous protger
de ces accs non autoriss.

Les niveaux daccs de lutilisateur


SQL permet de contrler laccs neuf fonctions de gestion de la base :
Cration, visualisation, modification, suppression : Ces
fonctions correspondent aux oprations INSERT, SELECT,
UPDATE et DELETE dont jai parl au Chapitre 6.
Rfrencement : Lutilisation du mot cl REFERENCES
(dont jai parl aux Chapitres 3 et 5) consiste appliquer
des contraintes dintgrit rfrentielle une table qui
dpend dune autre table de la base.

Utilisation : Le mot cl USAGE se rapporte aux domaines,


aux jeux de caractres, aux interclassements et aux
traductions (ces termes sont dfinis au Chapitre 5).

Dfinition de nouveaux types de donnes : Vous grez


les noms de types de donnes dfinis par lutilisateur via le
mot cl UNDER.

Rpondre un vnement : Lutilisation du mot cl


TRIGGER provoque lexcution dune instruction (ou dun
bloc dinstructions) SQL chaque fois quun vnement
prdtermin survient.

Excution : Le mot cl EXECUTE provoque lexcution


dun module de programme.

Ladministrateur de la base de
donnes
Lautorit suprme dune base de donnes utilise par plusieurs personnes
est ladministrateur de la base de donnes (DBA, DataBase Administrator).
Le DBA possde tous les droits et privilges pour accder toutes les
fonctionnalits de la base. tre DBA peut vous procurer un vritable
sentiment de puissance, mais vous investit galement dune lourde
responsabilit. tant donn ltendue de votre pouvoir, vous pouvez
facilement semer le dsordre dans votre base et dtruire des milliers
dheures de travail. Un DBA doit toujours rflchir clairement et
soigneusement aux consquences de ses actes.
Le DBA a tous les droits sur la base de donnes. Il contrle de plus tous les
droits des autres utilisateurs. De cette manire, des personnes hautement
dignes de confiance peuvent avoir accs des fonctions, et peut-tre des
tables, interdites la majorit des autres utilisateurs.
La meilleure faon de devenir DBA est dinstaller vous-mme un systme
de gestion de bases de donnes. Cette procdure vous donnera un compte,
ou login, et un mot de passe. Ce compte vous identifie comme tant un
utilisateur disposant de privilges spciaux. Le systme dsigne quelquefois
cet utilisateur par DBA, quelquefois par administrateur systme, voire par
superutilisateur (dsol, le costume de super-hros nest pas fourni par la
maison). Dans tous les cas, votre premire tche, une fois que vous serez
connect, sera de modifier votre mot de passe par dfaut pour le remplacer
par quelque chose de plus secret.
Si vous ne changez pas le mot de passe par dfaut, nimporte quelle
personne qui lirait le manuel serait en mesure dusurper lidentit du DBA.
Je vous conseille de communiquer votre nouveau mot de passe uniquement
un petit nombre de personnes totalement dignes de confiance. Aprs tout,
une mtorite pourrait vous dsintgrer demain matin, ou bien vous pourriez
gagner au Loto et prendre le premier avion pour trs loin au soleil, ou bien
encore tre dans limpossibilit de venir au bureau pour une quelconque
raison. Tout cela ne doit pas empcher vos collgues de travailler. Une
autre personne peut devenir son tour administrateur systme du moment
quelle connat le login et le mot de passe du DBA pour se connecter au
systme.
Si vous disposez des privilges du DBA, je vous conseille de ne vous
connecter sous cette identit que si vous devez effectuer une tche qui
requiert ce niveau de privilges. Une fois ce travail accompli, dconnectez-
vous. Puis reconnectez-vous en utilisant le login et le mot de passe dun
compte utilis pour accomplir toutes les autres oprations de routine. Cette
mthode pourra vous viter de commettre des erreurs susceptibles davoir
de fcheuses consquences pour les autres utilisateurs.

Les propritaires des objets de la


base de donnes
Une autre classe dutilisateurs privilgis, avec le DBA, est le propritaire
dobjets de la base de donnes. Par exemple, les tables et les vues sont des
objets de la base. Tout utilisateur qui cre de tels objets peut en dfinir le
propritaire. Le propritaire dune table bnficie de tous les privilges
associs celle-ci, y compris le droit dautoriser dautres utilisateurs y
accder. Du fait que les vues sappuient sur des tables sous-jacentes, une
personne autre que le propritaire dune table a la possibilit de crer une
vue base sur cette dernire. Mais le propritaire de cette vue ne pourra
jamais exercer sur la table sous-jacente que les droits qui lui sont accords.
Rappelez-vous donc quun utilisateur ne peut jamais contourner la
protection instaure par le propritaire dune table par lintermdiaire
dune simple vue.

Le public
Dans la terminologie rseau, le public dsigne tous les utilisateurs qui
ne sont pas spcialement privilgis (autrement dit, ni les DBA ni les
propritaires dobjets) et qui aucun utilisateur privilgi na accord de
droit particulier. Si un utilisateur privilgi accorde certains droits au
public, toute personne pouvant accder au systme est investie de ces
mmes droits.
Dans la plupart des installations, il existe une hirarchie des utilisateurs
base sur les privilges qui leur sont accords. Au sommet trne le DBA.
Le public forme la base de la pyramide. La Figure 14.1 illustre cette
hirarchie.

Accorder des privilges aux


utilisateurs
Par la vertu de sa position, le DBA bnficie de tous les privilges sur tous
les objets de la base de donnes. Aprs tout, le propritaire dun objet
possde tous les privilges portant sur cet objet, et la base de donnes est
elle-mme un objet. Par dfaut, toute autre personne ne dispose daucun
privilge sur aucun objet, moins que quelquun qui possde dj ces
privilges (ainsi que le droit de les transmettre) ne les lui ait explicitement
transmis. Vous pouvez accorder des privilges un utilisateur en utilisant
linstruction GRANT. Sa syntaxe se prsente de la manire suivante :
FIGURE 14.1 Hirarchie des utilisateurs en fonction des privilges daccs.

GRANT liste_privilges
ON objet
TO liste_utilisateurs
[WITH HIERARCHY OPTION]
[WITH GRANT OPTION]
[GRANTED BY auteur] ;

Dans cette instruction, liste_privilges est dfini ainsi :

privilge [, privilge]...

ou :

ALL PRIVILEGES

A son tour, privilge se dfinit comme suit :

SELECT
| DELETE

| INSERT [(nom_colonne[,nom_colonne]...)]
| UPDATE [(nom_colonne[,nom_colonne]...)]
| REFERENCES [(nom_colonne[,nom_colonne]...)]
| USAGE
| UNDER
| TRIGGER
| EXECUTE

Dans linstruction originale, objet reprsente :

[TABLE] nom_table
| DOMAIN nom_domaine
| CHARACTER SET nom_jeu_de_caractres
| COLLATION nom_interclassement
| TRANSLATION nom_traduction
| TYPE nom_type_utilisateur
| SEQUENCE nom_gnrateur_squence
| dsignateur_routine_spcifique

Enfin, liste_utilisateurs se prsente ainsi :

login [, login]...
| PUBLIC

Lauteur est soit CURRENT_USER, soit CURRENT_ROLE.


Dans la syntaxe prcdente, les vues sont considres comme tant des
tables. Les privilges SELECT, DELETE, INSERT, UPDATE, TRIGGER
et REFERENCES ne concernent que les tables et les vues. Le privilge
USAGE sapplique aux domaines, aux jeux de caractres, aux squences
dinterclassement et aux traductions. Le privilge UNDER regarde
uniquement les types. Quant EXECUTE, il sapplique en principe aux
modules de programmes. Les sections suivantes prsentent divers exemples
dutilisation de linstruction GRANT.

Rles
Un nom dutilisateur est un type didentificateur dautorisation, mais ce
nest pas le seul. Il identifie une personne (ou un programme) qui est
autorise effectuer une ou plusieurs actions sur la base de donnes. Dans
une grande entreprise, accorder des privilges particuliers chaque
employ peut vite se rvler fastidieux et coteux en temps. SQL rsout ce
problme en introduisant la notion de rle.
Un rle, identifi par un nom de rle, se compose dun ensemble de zros
ou plusieurs privilges pouvant tre accords un ensemble dindividus
ayant besoin du mme niveau daccs la base de donnes. Par exemple,
toutes les personnes qui ont le rle GARDE_SECURITE doivent possder
les mmes privilges. Ces privilges seront vraisemblablement diffrents
de ceux accords aux personnes qui ont le rle de VENDEUR_COMPTOIR.
Les rles ne font pas partie du noyau de la spcification de SQL. Cest
pourquoi certaines implmentations ne les proposent pas. Reportez-vous
la documentation de votre SGBD avant de tenter de les utiliser.
Vous pouvez crer des rles en utilisant la syntaxe suivante :

CREATE ROLE VENDEURS ;

Une fois le rle cr, vous pouvez accorder des privilges des utilisateurs
en faisant appel linstruction GRANT :

GRANT VENDEURS TO Charles ;

Lattribution de privilges un rle seffectue exactement comme avec les


utilisateurs individuels. une diffrence prs : le rle ne se plaint pas et il
naccuse pas le DBA de tous les maux.

Insrer des donnes


Pour accorder un rle le privilge dajouter des donnes dans une table,
suivez cet exemple :

GRANT INSERT
ON CLIENTS
TO VENDEURS ;
Ce privilge permet un vendeur dajouter de nouveaux clients dans la
table CLIENTS.

Consulter des donnes


Pour permettre un utilisateur de consulter les donnes dune table, servez-
vous de lexemple suivant :

GRANT SELECT
ON PRODUITS
TO PUBLIC ;

Ce privilge permet quiconque ayant accs au systme (PUBLIC) de


consulter le contenu de la table PRODUITS.
En ralit, accorder ce type de privilge est potentiellement dangereux. Les
colonnes de la table PRODUITS peuvent contenir des informations
confidentielles telles que PRIX_DE_GROS. Pour donner accs aux
principales informations tout en interdisant la consultation des donnes
sensibles, dfinissez une vue sur la table en liminant les colonnes
confidentielles. Accordez ensuite le privilge SELECT sur la vue et non
sur la table. Lexemple suivant illustre la syntaxe employer :

CREATE VIEW MARCHANDISES AS


SELECT MODELE, NOMPROD, DESCPROD, PRIX
FROM PRODUITS ;
GRANT SELECT
ON MARCHANDISES
TO PUBLIC ;

En utilisant la vue MARCHANDISES, le public ne peut pas voir la colonne


PRIX_DES_PRODUITS de la table PRODUIT ou toute autre colonne qui
nest pas mentionne dans CREATE VIEW. Seules les colonnes
explicitement dfinies dans la vue sont accessibles au public.

Modifier les donnes dune table


Dans toute organisation active, les donnes stockes dans une table voluent
au fil du temps. Vous devez accorder certaines personnes le droit et le
pouvoir deffectuer des modifications, tout en empchant dautres personnes
de le faire. Pour accorder des privilges de modification, suivez cet
exemple :

GRANT UPDATE (PRIMESVNT)


ON PRIMES
TO RESPONSABLE_COMMERCIAL ;

Le responsable commercial peut ajuster le pourcentage des primes verses


aux vendeurs (la colonne PRIMESVNT) en fonction des conditions du
march. Toutefois, il ne peut pas modifier les valeurs des colonnes
MONTANTMIN et MONTANTMAX qui correspondent au niveau des primes.
Pour autoriser la modification de toutes les colonnes, vous devez soit en
lister tous les noms, soit nen spcifier aucun, comme dans lexemple
suivant :

GRANT UPDATE
ON BONUS
TO DIRECTEUR_COMMERCIAL ;

Supprimer les lignes obsoltes


dune table
Des clients prennent leur retraite, changent dactivit ou choisissent un autre
fournisseur. Des employs dmissionnent, partent la retraite, sont
licencis ou meurent. Des produits deviennent obsoltes. Bref, des
informations dont vous conservez la trace peuvent perdre un jour leur
intrt. Quelquun doit donc supprimer les enregistrements devenus
obsoltes. Bien entendu, dlguer ce droit demande une rflexion pousse.
L encore, linstruction GRANT vous permet daccorder un privilge de
suppression une ou des tierces personnes de la manire suivante :

GRANT DELETE
ON EMPLOYES
TO RESPONSABLE_DRH ;
Le directeur des ressources humaines peut supprimer des enregistrements de
la table EMPLOYES, tout comme le DBA et le propritaire de la table
EMPLOYES (qui est probablement aussi le DBA). Aucune autre personne
ne peut effacer des enregistrements ( moins quune autre instruction
GRANT ne lui accorde ce pouvoir).

Rfrencer des tables lies


Si une table contient une cl trangre qui correspond la cl primaire
dune autre table, les donnes contenues dans la seconde table deviennent
accessibles aux utilisateurs de la premire. Cette situation cre
potentiellement une dangereuse porte de derrire par laquelle des
utilisateurs non autoriss pourraient passer pour extraire des informations
confidentielles. Dans ce cas, en effet, un utilisateur na pas besoin de
possder des droits daccs une table pour dcouvrir quelque chose sur
son contenu. Il lui suffit bien souvent davoir des droits daccs sur une
table qui rfrence cette cible pour pouvoir galement accder cette
dernire.
Par exemple, supposez que la table LICENCIES contienne les noms des
employs qui vont tre licencis le mois prochain. Seuls les responsables
autoriss ont un accs SELECT la table. Mais voil quun employ
dcouvre que la cl primaire de la table est EMPID. Il cre alors une
nouvelle table ESPION qui utilise EMPID comme cl trangre, ce qui lui
permet de jeter un coup dil sur LICENCIES. Jexplique comment crer
une cl trangre avec une clause REFERENCES au Chapitre 5. Cette
mthode mrite dtre place en tte de la liste des techniques que tout
administrateur systme se doit de connatre. Voyons cela de plus prs :

CREATE TABLE ESPION


(EMPID INTEGER REFERENCES LICENCIES) ;

Lemploy na plus qu insrer dans la table ESPION des lignes qui


correspondent aux identifiants de tous les employs. Toute insertion qui
choue signifie que lemploy nest pas licenci. Inversement, toute ligne
que la table accepte dajouter signifie que la personne a du souci se faire
pour son avenir immdiat.
Tout nest pas perdu. SQL permet de prvenir ce type dintrusion en
requrant dun utilisateur privilgi quil accorde explicitement le droit de
rfrencement aux autres utilisateurs. Par exemple :

GRANT REFERENCES (EMPID)


ON LICENCIEES
TO RESPONSABLE_DRH ;

Utiliser les domaines, les jeux de


caractres, les squences
dinterclassement et les
traductions
Les domaines, les jeux de caractres, les squences dinterclassement et les
traductions posent galement des problmes de scurit. Cest plus
particulirement le cas des domaines. Vous devez absolument viter quils
ne soient utiliss pour saper vos mesures de scurit.
Vous pouvez dfinir un domaine qui regroupe un ensemble de colonnes.
Vous voulez que toutes ces colonnes partagent le mme type et les mmes
contraintes. Les colonnes que vous numrez dans une instruction CREATE
DOMAIN hritent des types et contraintes du domaine. Si vous le voulez, il
reste possible de surcharger ces caractristiques pour certaines colonnes en
particulier. Pour autant, les domaines restent une solution lgante pour
attribuer les mmes caractristiques tout un ensemble de colonnes en une
seule dclaration.
Recourir aux domaines se rvle pratique si vous utilisez une srie de
tables contenant des colonnes dont les caractristiques sont identiques. Par
exemple, la base de donnes de votre socit peut comprendre plusieurs
tables, chacune possdant une colonne PRIX qui doit tre de type
DECIMAL (10,2) et ne contenir que des valeurs positives infrieures
10 000. Avant de crer vos tables, vous pourriez dfinir un domaine qui
spcifie les caractristiques de cette colonne de la manire suivante :

CREATE DOMAIN DOMAINE_TYPE_PRIX DECIMAL (10,2)


CHECK (VALUE >= 0 AND VALUE <= 10000) ;

Vous identifiez peut-tre vos produits en les dnommant CodeProduit


dans toutes vos tables. Ce code est toujours du type CHAR (5), le premier
caractre tant une lettre choisie dans la liste X, C, H, et le dernier lun des
deux chiffres 9 ou 0. Vous pouvez crer un domaine pour ces colonnes
comme suit :

CREATE DOMAIN DOMAINE_CODE_PRODUIT CHAR (5)


CHECK (SUBSTR (VALUE, 1,1) IN (X, C, H)
AND SUBSTR (VALUE, 5, 1) IN (9, 0) ) ;

Les domaines tant en place, vous pouvez maintenant crer vos tables de la
manire suivante :

CREATE TABLE PRODUITS


(CODE_PRODUIT DOMAINE_CODE_PRODUIT,
NOM_PRODUIT CHAR (30),
PRIX DOMAINE_TYPE_PRIX) ;

Au lieu de fournir explicitement le type de donnes pour CODE_


PRODUIT et PRIX dans la dfinition de la table, vous spcifiez leur
domaine, ce qui leur attribue le type adquat et les contraintes explicites
dans linstruction CREATE DOMAIN. Lorsque vous utilisez des domaines,
vous devez les prendre en compte dans la gestion de la scurit. Que se
passe-t-il si une personne veut utiliser un domaine que vous avez cr ? Est-
ce que cela peut poser des problmes ? Que se passe-t-il si une personne
cre une table dont une colonne a pour domaine DOMAINE_TYPE_
PRIX ? Cette personne pourra tester progressivement des valeurs de plus
en plus importantes sur la colonne jusqu ce quune entre soit rejete. Ce
faisant, elle sera capable de dterminer la limite suprieure du type PRIX
telle que vous lavez spcifie dans la clause CHECK de votre instruction
CREATE DOMAIN. Si cette information a un caractre confidentiel, vous
devez interdire aux autres laccs DOMAINE_TYPE_PRIX. Pour
protger vos tables de telles situations, SQL permet de limiter lutilisation
des domaines aux seules personnes explicitement autorises par leur
propritaire. Seuls ces propritaires (et le DBA) peuvent accorder une telle
permission. Si, aprs analyse, vous dcidez que cet agrment ne mettra pas
en pril votre scurit, il vous suffira dutiliser une instruction comme celle
de lexemple suivant :

GRANT USAGE ON DOMAINE_TYPE_PRIX TO


RESPONSABLE_COMMER-
CIAL ;

La suppression dun domaine par DROP peut engendrer diffrents


problmes de scurit. Si des tables contiennent des colonnes qui
appartiennent au domaine que vous souhaitez supprimer, vous devrez sans
doute dtruire au pralable ces tables, sans quoi vous ne pourrez pas
supprimer le domaine. Chaque implmentation gre la suppression dun
domaine dune manire particulire. SQL Server la traite dune certaine
faon, Oracle dune autre, et ainsi de suite. Dans tous les cas, il est plus
prudent de restreindre les possibilits de suppression des domaines, tout
comme celle des jeux de caractres, des squences dinterclassement et des
traductions.

Provoquer lexcution
dinstructions SQL
Il arrive parfois quune instruction SQL dclenche lexcution dune autre
instruction, voire dun bloc entier dinstructions.
Ce facteur dclenchant peut tre activ par trois types de phnomnes : un
vnement, un instant spcifique ou une certaine action.
Un vnement peut dclencher (trigger) une certaine
instruction ou un certain groupe dinstructions.

Un instant donn peut dterminer le moment o une


certaine action est dclenche (soit juste avant, soit juste
aprs lvnement).

Une action correspond simplement lexcution dune ou


plusieurs instructions SQL.
Par exemple, vous pouvez utiliser un facteur dclenchant pour excuter une
commande qui vrifie la validit dune nouvelle valeur avant dautoriser un
UPDATE. Si la nouvelle valeur nest pas valide, la mise jour naura pas
lieu.
Un utilisateur ou un rle doit possder le privilge TRIGGER pour avoir
le droit de dclencher une action. Par exemple :

CREATE TRIGGER SupprClient BEFORE DELETE


ON CLIENTS FOR EACH ROW
WHEN Deptt = 75
INSERT INTO LOGCLIENT VALUES (Client parisien
suppri-
m) ;

Chaque fois quun client habitant Paris est sur le point dtre supprim de la
table CLIENTS, une entre dans la table LOGCLIENT est ajoute afin de
mmoriser cet effacement.

Accorder des privilges entre


niveaux
Au Chapitre 2, je dcris les types structurs comme une forme de types
dfinis par lutilisateur (UDT). Lessentiel de larchitecture des types
structurs dcoule dides venant de la programmation oriente objet. Lune
de ces ides est la hirarchie, o un type peut avoir des sous-types, types
dont certains des attributs drivent de ceux du type dont eux-mmes drivent
(leur supertype). En plus dhriter de ces attributs, ils peuvent aussi
disposer dattributs qui leur sont propres. Une hirarchie de cette nature
peut comprendre de multiples niveaux, le type se trouvant tout en bas tant
dsign comme un type feuille, par analogie une arborescence.
Une table type est une table dans laquelle chaque ligne est une instance du
type structur associ. Une telle table comprend une colonne par attribut de
son type structur associ. Le nom et le type de donnes de la colonne sont
identiques ceux de lattribut.
Par exemple, supposons que vous soyez lauteur de peintures que vous
commercialisez dans des galeries. En plus de vos originaux, vous
commercialisez aussi des tirages limits numrots et signs, des tirages
non numrots, et des posters. Vous pouvez crer un type structur pour vos
uvres de la manire suivante :

CREATE TYPE Soeuvres (


artiste CHARACTER VARYING (30),
titre CHARACTER VARYING (50),
description CHARACTER VARYING (256),
support CHARACTER VARYING (20),
dateCreation DATE )
NOT FINAL

Cest encore une fonctionnalit que tous les produits de SGBD ne proposent
pas. Toutefois, PostgreSQL dispose de la commande CREATE TYPE, tout
comme Oracle 11g et SQL Server 2012.
En tant quartiste souhaitant conserver la trace de vos uvres, vous voulez
faire la distinction entre les originaux et les reproductions. Vous pourriez de
plus souhaiter distinguer les diffrents types de reproductions. La
Figure 14.2 vous prsente un exemple dutilisation dune hirarchie pour
faciliter ces distinctions. Le type uvre dispose de sous-types, qui peuvent
leur tour avoir des sous-types.
Il existe une correspondance un pour un entre les types dans la hirarchie
des types et les tables dans la hirarchie de la table type. Les tables
standard, dont il est question aux Chapitres 4 et 5, ne peuvent pas figurer
dans une hirarchie semblable celle voque ici pour les tables types.
FIGURE 14-2 La hirarchie des uvres.

Au lieu dutiliser une cl primaire, une table type dispose dune colonne
dauto-rfrence qui garantit lunicit dun enregistrement, non seulement
dans la supertable qui occupe le sommet de la hirarchie, mais dans toutes
ses sous-tables. La colonne dauto-rfrence est spcifie par une clause
REF IS dans la commande CREATE de la supertable. Lorsque ce
systme dauto-rfrencement est mis en place, lunicit est assure dans
toute la hirarchie.

Donner le pouvoir daccorder des


privilges
Le DBA peut accorder des privilges nimporte qui. Le propritaire dun
objet peut accorder des privilges sur cet objet nimporte qui. Mais les
utilisateurs bnficiant de ces privilges ne peuvent pas les rtrocder une
tierce personne.
Seules les personnes dsignes par le DBA ou le propritaire peuvent
bnficier de ces privilges. Histoire de matriser la situation...
Du strict point de vue de la scurit, restreindre la dlgation de privilges
est totalement justifi. Mais des utilisateurs ont souvent besoin de dlguer
leur autorit. Le travail ne peut pas sarrter parce quune personne est
malade, en vacances ou est sortie pour djeuner.
Vous devez accorder certains utilisateurs le pouvoir de transmettre leurs
privilges dautres personnes. Pour cela, utilisez linstruction GRANT
avec la clause WITH GRANT OPTION. Par exemple :

GRANT UPDATE (PRIMESVDT)


ON PRIMES
TO RESPONSABLE_COMMERCIAL
WITH GRANT OPTION ;

Le responsable commercial peut maintenant transmettre le privilge


UPDATE en utilisant linstruction suivante :

GRANT UPDATE (PRIMESVDT)


ON PRIMES
TO ASSISTANT_RESPONSABLE_COMMERCIAL ;

Une fois cette instruction excute, lassistant du responsable commercial


peut effectuer des modifications dans la colonne PRIMESVDT de la table
PRIMES, ce qui lui tait interdit auparavant.
Le fait de dlguer des droits reprsente toujours un compromis entre
scurit et commodit. Le propritaire de la table PRIMES octroie un
contrle considrable en accordant le privilge UPDATE lassistant du
responsable commercial via WITH GRANT OPTION. Ce propritaire fait
un pari sur le fait que son assistant prendra cur ses nouvelles
responsabilits et quil ne courra pas lui-mme le risque de dlguer son
tour ce privilge nimporte qui.

Retirer des privilges


Si vous avez le droit daccorder des privilges, vous devez galement tre
en mesure de les retirer. Les postes occups par les salaris de votre
entreprise peuvent voluer, et donc en mme temps leurs besoins daccs
aux donnes. Il peut mme arriver quun de vos employs quitte votre
socit pour aller travailler chez un concurrent. Dans ce cas, vous devez
pouvoir lui retirer immdiatement tout privilge daccs.
Linstruction REVOKE de SQL permet de supprimer des privilges. Elle
fonctionne comme linstruction GRANT, ceci prs quelle a leffet
inverse. Sa syntaxe est la suivante :

REVOKE [GRANT OPTION FOR] liste_privilges


ON objet
FROM liste_utilisateurs [RESTRICT|CASCADE] ;

Vous pouvez employer cette structure pour annuler des privilges


spcifiques tout en laissant intacts les autres. Linstruction REVOKE se
distingue principalement de GRANT par la prsence dun des mots cls
optionnels RESTRICT ou CASCADE.

Vous avez utilis WITH GRANT OPTION pour accorder des privilges
un utilisateur. Si vous voulez ventuellement annuler ces privilges, utilisez
loption CASCADE dans linstruction REVOKE. Vous supprimerez du mme
coup en cascade les privilges que cet utilisateur a pu accorder dautres
personnes.
Dun autre ct, loption RESTRICT de linstruction REVOKE ne
fonctionne que si le dlgataire na pas son tour transmis ces droits
spcifiques. En dautres termes, vous retirez certains privilges tel
utilisateur donn. Mais si celui-ci les a dj diffuss droite et gauche,
linstruction REVOKE accompagne de loption RESTRICT ne rvoquera
personne et se contentera de retourner un message derreur.
Vous pouvez utiliser linstruction REVOKE avec la clause GRANT
OPTION FOR pour annuler le droit pour une personne de transmettre des
privilges (tout en les conservant pour elle-mme).
Si la clause GRANT OPTION FOR et le mot cl CASCADE sont
prsents, vous rvoquez tous les privilges accords une personne
donne, de mme que tous les droits de cet individu rtrocder ses
privilges. Dans le meilleur des cas, cest en quelque sorte comme si vous
naviez jamais rien autoris. La prsence simultane de la clause GRANT
OPTION FOR et du mot cl CASCADE peut produire lune des situations
suivantes :
Si le bnficiaire de linstruction GRANT na jamais dlgu
les droits ainsi acquis dautres utilisateurs, linstruction
REVOKE est excute, et elle supprime le ou les privilges
concerns en cascade.

Si le bnficiaire de linstruction GRANT a dj dlgu au


moins lun des privilges dont il dispose, linstruction
REVOKE nest pas excute et elle renvoie un code derreur.

Le fait que vous puissiez accorder des privilges avec WITH GRANT
OPTION, puis que vous puissiez les rvoquer slectivement, rend la gestion
de la scurit plus complexe quil ny parat premire vue. Par exemple,
plusieurs personnes ayant des droits identiques pourraient accorder le
mme privilge un seul utilisateur. Si lun de ces dlgataires rvoque
ce privilge, lutilisateur continuera en bnficier encore via les droits
qui lui ont t accords par dautres. Si un privilge est transmis dun
utilisateur un autre avec WITH GRANT OPTION, cette situation cre une
chane de dpendance dans laquelle les privilges dun utilisateur
dpendent de ceux dun autre utilisateur. Si vous tes DBA ou propritaire
dun objet, veillez toujours, aprs avoir utilis WITH GRANT OPTION,
que le privilge ainsi dlgu ne puisse pas rapparatre l o vous ne
lattendez pas. Supprimer un privilge pour certains utilisateurs
indsirables, tout en le conservant pour ceux qui y ont lgitimement droit,
reprsente une tche particulirement dlicate. En rgle gnrale,
lutilisation des clauses GRANT OPTION et CASCADE engendre de
nombreuses et dlicates subtilits. Si vous utilisez ces clauses, lisez
soigneusement la documentation de votre produit et les spcifications du
standard SQL pour vous assurer que vous comprenez bien leur
fonctionnement.

Utiliser simultanment GRANT et


REVOKE pour gagner du temps et
des efforts
Accorder de multiples privilges sur des colonnes dune table de
nombreux utilisateurs peut reprsenter des masses de lignes dinstructions.
Considrez cet exemple : le directeur commercial souhaite que tous les
commerciaux puissent consulter la table CLIENTS. Mais seuls les
responsables commerciaux peuvent mettre jour, supprimer ou insrer des
lignes. Personne ne devrait modifier le champ CLIENT_ID. Les noms des
responsables commerciaux sont Tyson, Keith et David. Vous pouvez leur
accorder les privilges adquats avec des instructions GRANT de la
manire suivante :

GRANT SELECT, INSERT, DELETE


ON CLIENTS
TO TYSON, KEITH, DAVID ;
GRANT UPDATE
ON CLIENTS (SOCIETE, ADRESSE, VILLE,
ETAT, CODE_POSTAL, TELEPHONE)
TO TYSON, KEITH, DAVID ;
GRANT SELECT
ON CLIENTS
TO JENNY, VALERIE, MELODY, NEIL, ROBERT, SAM,
BRANDON, MICHELLE_T, ALLISON, ANDREW,
SCOTT, MICHELLE_B, JAIME, LINLEIGH, MATT, AMANDA
;

Ainsi chacun bnficie des droits SELECT sur la table CLIENTS. Les
responsables commerciaux bnficient en plus des droits INSERT et
DELETE complets sur cette table. Ils peuvent en particulier modifier toutes
les colonnes lexception de CLIENT_ID.
La solution suivante donne plus rapidement le mme rsultat :

GRANT SELECT
ON CLIENTS
TO RESPVENTES ;
GRANT INSERT, DELETE, UPDATE
ON CLIENTS
TO TYSON, KEITH, DAVID ;
REVOKE UPDATE
ON CLIENTS (CUST_ID)
FROM TYSON, KEITH, DAVID ;

Le nombre dinstructions est identique, et le niveau de protection galement.


Mais ces instructions sont bien plus simples saisir, car vous ne nommez
pas tous les utilisateurs du dpartement commercial ni toutes les colonnes
de la table. Le temps de saisie ainsi gagn est galement un gain de
productivit, ce qui est lide sous-jacente principale.
Chapitre 15
Protection des donnes
DANS CE CHAPITRE :
Prserver une base de donnes.

Comprendre les problmes dus des oprations concurrentes.

Grer les problmes de concurrence avec les mcanismes de SQL.

Protection sur mesure avec SET TRANSACTION.

Protger vos donnes sans nuire la productivit.

V
ous devez connatre la loi de Murphy en gros, si quelque chose peut
aller de travers, elle ira de travers. Cette pseudo-loi est un sujet de
plaisanterie, car, dans la plupart des cas, les choses se droulent comme
nous lavions prvu. Si un problme inattendu survient, vous serez
probablement en mesure de le dtecter et de le rsoudre.

Mais ce qui est vrai pour nous ne lest pas forcment pour des structures
complexes (un mathmaticien vous expliquerait que le risque crot
approximativement comme le carr de la complexit). Une base de donnes
multi-utilisateur est une structure complexe. De multiples problmes
peuvent se produire lors de son fonctionnement. De nombreuses mthodes
ont t dveloppes pour minimiser limpact de ces problmes, mais elles
nont jamais permis de les liminer compltement (ce qui doit rjouir les
professionnels de la maintenance des bases de donnes, car il semble
virtuellement impossible dautomatiser leur travail). Dans ce chapitre, nous
allons nous pencher sur les principaux risques qui menacent vos bases de
donnes, et nous tudierons les outils que fournit SQL pour traiter les
problmes susceptibles de se poser vous.

Menaces sur lintgrit des donnes


Le cyberespace (y compris votre rseau) est un bel endroit visiter, mais ce
nest pas tous les jours fte pour les donnes qui y rsident. Vos donnes
peuvent tre endommages ou corrompues de toutes sortes de manires. Au
Chapitre 5, jai abord les problmes lis une mauvaise saisie, aux
erreurs de manipulation et aux destructions intentionnelles. Des instructions
SQL mal formules ou des applications mal conues peuvent galement
endommager vos donnes. ces menaces sajoutent linstabilit de la
plate-forme et les ventuelles pannes du matriel. Je vais traiter de ces deux
derniers points dans les sections qui suivent, ainsi que des problmes lis
aux accs concurrents.

Instabilit de la plate-forme
Linstabilit de la plate-forme est une question qui ne devrait mme pas
exister. Malheureusement, elle se pose, et ce avec dautant plus dacuit que
votre systme fonctionne avec des composants qui nont pas t
srieusement tests. Un problme dinstabilit peut survenir aprs
linstallation dune nouvelle version du SGBD ou du systme
dexploitation, ou encore aprs lajout dun nouveau matriel. Vous tes
alors confront des situations totalement inattendues. Et cela se produit
videmment un moment critique pour votre travail. Votre systme se
plante, vos donnes sont endommages. Rien ne va plus. part insulter
votre ordinateur et ceux qui lont fabriqu, il ne vous reste gure dautre
solution que desprer que votre dernire sauvegarde soit la bonne.
Ne stockez jamais des donnes importantes sur un systme dans lequel un
composant quelconque na pas t test. Rsistez la tentation de vous jeter
sur la toute nouvelle version bta, pourtant si allchante, de votre SGBD ou
de votre systme dexploitation. Si vous avez limpression que vous devez
vous faire la main sur un nouvel outil, faites-le sur une machine totalement
isole de votre environnement de production.

Panne matrielle
Le plus moderne des quipements nest pas labri dune panne qui risque
de faire franchir le Styx vos donnes. Le risque nest jamais nul, mme
avec un ordinateur dernier cri et haut de gamme. Si un incident matriel se
produit alors que votre base de donnes est ouverte et active, vous pouvez
dvidence perdre des donnes, parfois mme sans vous en rendre compte.
Ce type de panne survient toujours un jour ou lautre. Et si ce jour-l la loi
de Murphy sapplique, ce sera pour vous le pire des moments.
Lune des solutions pour protger vos donnes des pannes matrielles est la
redondance. Conservez une copie de tout. Pour une scurit maximale,
procurez-vous une copie conforme de la configuration matrielle de votre
environnement de production (si tant est que cet investissement soit la
porte de votre organisation). Faites des sauvegardes de votre base de
donnes et de vos applications que vous pourrez charger sur le double de
votre environnement de production aussitt quune panne se produit. Si le
cot dune telle redondance vous parat exorbitant, faites a minima
rgulirement une sauvegarde de votre base de donnes et de vos
applications, de telle sorte que vous nayez pas ressaisir une trop grande
quantit de donnes en cas de panne.
Une autre solution pour vous prserver des pannes matrielles consiste
utiliser des transactions, dont il est question la fin de ce chapitre. Une
transaction est une unit indivisible de travail. Autrement dit, elle ne peut
tre excute quen entier ou pas du tout. Cette approche du tout ou rien peut
paratre drastique. Cela dit, les pires problmes apparaissent lorsquune
srie doprations sur la base est interrompue en cours de traitement. Les
transactions diminuent donc le risque de voir vos donnes corrompues ou
perdues, et ce mme en cas de dfaillance du matriel sur lequel rside la
base.

Accs concurrent
Supposez que vous utilisiez un logiciel et du matriel certifis, que vos
donnes soient bonnes, que vos applications soient exemptes de bogues et
que tout votre quipement soit parfaitement fiable. Le rve ? Pas encore.
Des problmes peuvent apparatre lorsque plusieurs personnes essaient
daccder simultanment la mme table dune base de donnes (cest
laccs concurrent), et que leurs ordinateurs tergiversent sur celui qui doit
passer en premier (cest la contention). Les systmes de bases de donnes
multi-utilisateurs doivent tre capables de grer efficacement une telle
situation.

Problme dinteraction de transaction


Des problmes de contention peuvent apparatre dans nimporte quelle
application. Considrez le cas suivant : vous crivez une application
destine passer des commandes qui fait intervenir quatre tables :
COMMANDES, CLIENTS, LIGNE_OB-JET et INVENTAIRE. Les
conditions suivantes sont appliques :
La table COMMANDES a NUMERO_COMMANDE comme
cl primaire et NUMERO_CLIENT comme cl trangre qui
rfrence la table CLIENTS.

La table LIGNES_COMMANDE a NUMERO_LIGNE comme


cl primaire et NUMERO_OBJET comme cl trangre qui
rfrence la table INVENTAIRE. Elle contient galement une
colonne QUANTITE.

La table INVENTAIRE a NUMERO_OBJET comme cl


primaire et contient galement un champ appel
QUANTITE_DISPO-NIBLE.

Ces trois tables possdent dautres colonnes qui ninterviennent pas dans
cet exemple. La stratgie de votre socit consiste traiter compltement
chaque commande ou pas du tout. Autrement dit, aucune commande partielle
nest autorise (pas de panique, ce nest quune situation hypothtique).
Vous allez crire une application TRAITER_COMMANDE qui traitera
chaque commande enregistre dans la table COMMANDES. Lapplication
va commencer par dterminer sil est possible dexpdier tous les objets
commands. Si cest le cas, elle crira la commande, puis dcrmentera
comme il convient la colonne QUANTITE_DISPONIBLE de la table
INVENTAIRE. Cette action supprimera au passage les entres concernes
des tables COMMANDES et LIGNES_COMMANDE.
Lapplication est conue pour traiter les commandes de lune des deux
manires suivantes lorsque plusieurs utilisateurs accdent simultanment
la base :
La premire mthode consiste traiter la ligne
dINVENTAIRE qui correspond chaque ligne de la table
LIGNES_COMMANDE. Si QUANTITE_DISPONIBLE est
suffisant, lapplication dcrmente ce champ. Si la valeur de
QUANTITE_DISPONIBLE nest pas assez grande, elle
annule la transaction et revient sur toutes les oprations
qui ont affect les autres objets LIGNES_COMMANDE de
cette commande.

La seconde mthode consiste vrifier chaque ligne


dINVENTAIRE correspondant une ligne
LIGNES_COMMANDE de la commande. Si toutes les
quantits sont suffisantes, lapplication les traite en les
dcrmentant.

En rgle gnrale, la premire mthode savre la plus efficace si le


traitement de la commande russit. Par contre, la seconde mthode est plus
efficace en cas dchec. Si la plus grande part des commandes est honore
la plupart du temps, il est prfrable demployer la premire mthode.
linverse, si une majorit de commandes a la fcheuse habitude dchouer,
il vaut mieux appliquer la seconde mthode. Supposons que cette
application hypothtique soit en cours dexploitation sur un systme multi-
utilisateur dpourvu dun contrle adquat des accs concurrents. Vous
entendez dj le sifflement des balles ? Voici un chantillon des problmes
qui peuvent alors survenir :

1. Un client contacte un vendeur (nous lappellerons


utilisateur 1). Il veut commander 10 scateurs (objet 1)
et cinq tondeuses (objet 37).

2. Lutilisateur 1 emploie la mthode 1 pour traiter la


commande. Il commence par les dix exemplaires de
lobjet 1 (les scateurs).

Comme il se doit, vous avez effectivement dix scateurs en


stock et lutilisateur 1 les prend tous.

La fonction de traitement des commandes dcrmente la


quantit en stock de lobjet 1 pour la passer zro. Et cest
ici que les choses deviennent intressantes. Un autre client
contacte votre entreprise pour passer une (toute petite)
commande. Cette fois, cest lutilisateur 2 qui lui rpond.

3. Lutilisateur 2 essaie denregistrer la commande dun


seul exemplaire de lobjet 1. Il constate alors quil ne
reste plus aucun scateur.

La commande de lutilisateur 2 est annule, car elle ne peut


pas tre honore.

4. Pendant ce temps, lutilisateur 1 continue traiter la


commande en soccupant des cinq exemplaires de
lobjet 37 (les tondeuses).

Malheureusement, il ny en a plus que quatre en stock. La


commande de lutilisateur 1 est donc annule, puisquelle ne
peut pas tre honore intgralement.

La table INVENTAIRE se retrouve prsent dans son tat


initial, car aucun utilisateur na pu traiter sa commande. Les
deux commandes sont perdues, bien que celle de
lutilisateur 2 aurait pu tre satisfaite. Votre socit est mal
partie...
La mthode 2 nest pas plus efficace, mais pour une raison diffrente.
Lutilisateur 1 pourrait vrifier la disponibilit de tous les objets quil
commande et dcider que ces objets sont disponibles. Puis
lutilisateur 2 intervient et passe commande de lun de ces produits avant
que lutilisateur 1 ait ralis la dcrmentation. La transaction de
lutilisateur 1 choue.

Srialiser pour viter les problmes


dinteraction
Aucun conflit ne se produit si les transactions sont excutes en srie et non
concurremment. Dans le premier exemple, si la transaction malheureuse de
lutilisateur 1 stait termine avant que ne dbute celle de lutilisateur 2, la
fonction ROLLBACK aurait rendu disponible la tondeuse commande par
lutilisateur 2. Rappelons que ROLLBACK est une machine remonter le
temps qui annule la totalit dune transaction.
Si les transactions avaient t traites en srie dans le second exemple,
lutilisateur 2 naurait jamais pu modifier la quantit disponible dun
produit tant que la transaction de lutilisateur 1 naurait pas t acheve. La
transaction de lutilisateur 1 se serait alors droule correctement (en se
concluant soit par une russite, soit par un chec), et lutilisateur 2 aurait pu
vrifier si lobjet quil souhaitait commander tait rellement disponible.
Si les transactions sont excutes en srie, lune aprs lautre, elles
ninterfreront jamais. Lexcution de transactions concurrentes est
ditesrialise si le rsultat obtenu est le mme que celui que produirait
lexcution en srie de ces transactions.
Srialiser des transactions concurrentes nest pas la panace. Entre se
protger des interactions malencontreuses et prserver les performances, il
faut trouver le juste milieu. Plus vous isolez les transactions les unes des
autres, plus il faut de temps pour les excuter. Contrler de manire trop
tatillonne les accs concurrents peut nuire aux performances gnrales du
systme. Se protger est indispensable, mais une surprotection ne fera que
dgrader les choses.

Rduire le risque de corruption des


donnes
Vous pouvez prendre des prcautions plusieurs niveaux pour viter de
perdre des donnes lors dune interaction inattendue ou dune panne. Il est
possible de configurer votre SGBD de telle sorte quil gre certaines de ces
prcautions votre place. Tel un ange gardien, il vous protgera du mal
sans que vous nen sachiez jamais rien. Vous ne verrez rien. Dailleurs,
vous ne voudrez sans doute mme pas savoir que le SGBD est en train de
vous aider. Votre administrateur de base de donnes (DBA) peut galement
tablir des prcautions sa discrtion. Et vous en serez ventuellement
inform ou non selon ce quil aura dcid. Enfin, en tant que dveloppeur,
vous vous devez de suivre la mme dmarche lorsque vous crivez votre
code.
Vous vous viterez un grand nombre de problmes en prenant lhabitude
dappliquer automatiquement ces quelques principes lmentaires (que ce
soit dans votre code ou dans vos interactions avec la base de donnes) :
Utilisez les transactions SQL.

Trouvez le juste milieu entre performances et protection.

Sachez quand et comment utiliser des transactions,


verrouiller des objets de la base de donnes et effectuer
des sauvegardes.

Dtaillons maintenant ces notions.

Utiliser les transactions SQL


La transaction est lun des principaux outils quoffre SQL pour maintenir
lintgrit dune base de donnes. Une transaction SQL englobe toutes les
instructions qui ont un effet sur la base. Elle se termine soit par une
instruction COMMIT, soit par une instruction ROLLBACK.
Si une transaction se termine par COMMIT, les effets de
toutes les instructions de cette transaction sont rpercuts
dans la base de donnes en une seule squence trs
rapide.

Si une transaction se termine par ROLLBACK, les effets de


toutes les instructions sont annuls et la base de donnes
retrouve ltat qui tait le sien avant que ne dbute cette
transaction.

Le terme application dsigne ici soit lexcution dun programme (quil soit
en Cobol, C++ ou tout autre langage), soit une srie dactions effectues
depuis un terminal lors dune seule session.
Une application peut comprendre plusieurs transactions SQL. La premire
transaction commence avec cette application, et la dernire transaction se
termine avec elle. Chaque COMMIT ou ROLLBACK effectu par
lapplication termine une transaction SQL et marque le dbut de la suivante.
Par exemple, une application qui contient trois transactions SQL pourrait
adopter la forme suivante :

Dbut de lapplication
Diverses instructions SQL(SQL transaction-1)
COMMIT ou ROLLBACK
Diverses instructions SQL(SQL transaction-2)
COMMIT ou ROLLBACK
Diverses instructions SQL(SQL transaction-3)
COMMIT ou ROLLBACK
Fin de lapplication

Jemploie le terme de transaction SQL , car lapplication peut faire


appel dautres sortes de fonctionnalits de mme type (par exemple lors
dun accs au rseau). Dans les pages suivantes, transaction sous-entend
donc transaction SQL .
Une transaction SQL normale a un mode daccs qui est soit READ_WRITE
(lecture et criture), soit READ_ONLY (criture seule). Elle a un niveau
disolation qui est soit SERIALIZABLE, soit REPEATABLE READ, soit
READ COMMITTED, soit READ UNCOMMITTED (reportez-vous plus
loin la section Niveaux disolation pour plus de dtails). Les
caractristiques par dfaut sont READ_WRITE et SERIALIZABLE. Si
vous voulez utiliser dautres rglages, vous devez les spcifier avec une
instruction SET TRANSACTION. Par exemple :

SET TRANSACTION READ ONLY ;

Ou encore :

SET TRANSACTION READ ONLY REPEATABLE READ ;

Ou bien :
SET TRANSACTION READ COMMITTED ;

Une application peut contenir plusieurs instructions SET TRANSACTION,


mais vous ne pouvez en utiliser quune seule par transaction, et il doit sagir
de la premire instruction excute dans le cadre de cette transaction. Il
vous faut donc la placer soit au dbut de lapplication, soit aprs COMMIT
ou ROLLBACK. Vous devez faire appel une instruction SET
TRANSACTION au dbut de toute transaction qui ne se contentera pas des
proprits par dfaut, car chaque nouvelle transaction suivant un COMMIT
ou un ROLLBACK adopte automatiquement ces proprits.
Une instruction SET TRANSACTION peut galement spcifier un
DIAGNOSTICS SIZE qui fixe le nombre de conditions derreur sur
lesquelles limplmentation devra conserver des informations (instaurer une
telle limite est indispensable, car une implmentation peut dtecter plus
dune erreur au cours dune mme instruction). La valeur SQL par dfaut de
cette limite dpend de limplmentation, mais elle est pratiquement toujours
adquate.

La transaction par dfaut


Les caractristiques de la transaction SQL par dfaut rpondent en rgle
gnrale aux besoins de la plupart des utilisateurs. Mais vous pouvez
spcifier dautres proprits via une instruction SET TRANSACTION
comme cela a t expliqu dans la section prcdente (il sera par ailleurs
question de SET TRANSACTION plus loin dans ce chapitre).
La transaction par dfaut sappuie par ailleurs sur deux suppositions
implicites :
La base de donnes va changer au fil du temps.

Il est toujours prfrable de travailler en scurit que de


regretter ses actes.

Cest pourquoi elle applique le mode READ-WRITE qui vous permet


dexcuter des instructions destines modifier la base de donnes. De
plus, elle utilise le niveau disolation SERIALIZABLE, qui correspond au
niveau le plus lev disolation (et donc le plus sr). DIAGNOSTICS
SIZE prend une valeur par dfaut qui dpend de limplmentation.
Reportez-vous la documentation SQL de votre systme pour en savoir
plus.

Niveaux disolation
Dans lidal, le travail accompli par votre transaction est totalement isol
du travail accompli par les autres transactions, mme si elles sexcutent de
manire concurrente. Mais, dans la ralit, il nest pas toujours possible
datteindre un niveau disolation parfait sur un systme multi-utilisateur,
moins de sacrifier les performances. La question est donc : Jusqu quel
point souhaitez-vous isoler les transactions les unes des autres et combien
tes-vous prt payer pour cela en termes de performances ?

Lecture sale
Le plus faible des niveaux disolation est appel READ UNCOMMITTED.
Il vous expose au problme de la lecture sale. Vous tes en lecture sale
lorsquun utilisateur peut consulter la valeur dune donne modifie par une
seconde personne avant que cette modification nait t valide par une
instruction COMMIT.
Le problme apparat lorsque le second utilisateur annule sa transaction.
Les oprations effectues ensuite par le premier utilisateur sont alors bases
sur une valeur incorrecte. Lexemple classique est celui dune application
dinventaire : un utilisateur dcrmente linventaire, un second lit la
nouvelle valeur. Le premier utilisateur annule sa transaction (ce qui rend
linventaire sa valeur initiale). Le second utilisateur, qui croit que le stock
est presque puis, passe une commande pour le renouveler, alors quen
ralit vous navez besoin de rien.
Nutilisez jamais le niveau disolation READ UNCOMMITTED, moins
que votre but ne soit pas de rcuprer des rsultats prcis.

Vous pouvez vous placer au niveau READ UNCOMMITTED si vous voulez


gnrer des statistiques telles que :
Le dlai maximal entre le passage de deux commandes.
La moyenne dge des commerciaux qui natteignent pas
leur objectif de vente.

La moyenne dge des nouveaux employs.

Dans de tels cas, des informations approximatives suffisent. Le prix payer


en termes de performances pour un renforcement du contrle des accs
concurrents nen vaut sans doute pas la chandelle (dailleurs, celle-ci ne
vous aiderait pas faire fonctionner votre rseau en cas de panne de
courant...).

La lecture non rptable


Le niveau disolation suivant est READ COMMITTED. Une modification
effectue dans le cadre dune autre transaction nest pas vue par la vtre
tant que le second utilisateur na pas finalis son opration en mettant un
COMMIT. Ce niveau donne de meilleurs rsultats que READ
UNCOMMITTED, mais il pose le problme de la lecture qui ne peut tre
rpte. Cela ressemble un titre de comdie, mais cest un problme
srieux.
Reprenons lexemple de linventaire. Lutilisateur 1 interroge la base de
donnes pour connatre le nombre dexemplaires disponibles dun certain
produit. La rponse est 10. Quasiment en mme temps, lutilisateur 2 entame
puis valide une transaction qui passe une commande de 10 exemplaires de
ce produit. Le stock est videmment dcrment, et passe donc zro.
Lutilisateur 1, qui a vu que 10 exemplaires taient disponibles, essaie den
commander cinq. Mais il nen reste mme plus cinq. La premire lecture de
lutilisateur 1 ne peut tre rpte. La quantit a chang sans quil en soit
averti. Toutes les dcisions quil va prendre en fonction de sa premire
lecture sont invalides.

La lecture fantme
Le niveau disolation REPEATABLE READ vite le problme prcdent.
Toutefois, ce niveau disolation est son tour hant par le problme de la
lecture fantme, qui survient lorsque la donne que cet utilisateur est en
train de lire est modifie en rponse une autre transaction et quil nen est
pas immdiatement inform lcran.
Supposons par exemple que notre utilisateur 1 passe une commande dont les
critres de recherche (clauses WHERE et HAVING) dsignent un ensemble
de lignes. Immdiatement aprs, un utilisateur 2 modifie des donnes dans
quelques-unes de ces lignes. Ces dernires rpondaient peut-tre aux
critres de recherche de lutilisateur 1 avant lintervention de lutilisateur 2,
mais ce nest plus le cas prsent. Il est mme possible que des lignes qui
ne vrifiaient pas les critres de recherche initiaux y rpondent maintenant.
Lutilisateur 1, dont la transaction est toujours active, nest pas inform des
modifications apportes par lutilisateur 2. Lapplication se comporte
comme si de rien ntait. Si lutilisateur 1 effectue nouveau la mme
recherche, il va rcuprer des lignes diffrentes de celles qui lui avaient t
retournes la premire fois. La fiabilit des rsultats a t vampirise par la
lecture fantme.

Obtenir une lecture efficace (et sans


doute plus lente)
Le niveau disolation SERIALIZABLE vite tous les problmes dcrits
ci-dessus. ce niveau, les transactions concurrentes peuvent tre excutes
sans aucune interfrence entre elles, et les rsultats produits seront les
mmes que si elles avaient t excutes en srie (lune aprs lautre) et
non en parallle. Mme ce niveau disolation, des problmes de logiciel
et de matriel peuvent certes toujours provoquer lchec de vos
transactions. Mais vous naurez plus vous inquiter de la validit des
rsultats si vous tes certain que votre systme fonctionne correctement.
Naturellement, cette fiabilit suprieure a un prix en termes de
performances. Le Tableau 15.1 fait le point sur les niveaux disolation et les
problmes quils rsolvent.

TABLEAU 15.1 Niveaux disolation et problmes rsolus.

Niveau Problmes Lecture qui ne Lecture qui ne Lecture


disolation rsolus peut tre peut tre fantme
rpte rpte
READ Aucun Non Non Non
UNCOMMITTED
READ Lecture Oui Non Non
COMMITTED sale
REPEATABLE Lecture Oui Oui Non
READ sale
SERIALIZABLE Lecture Non Oui Oui
sale

Instruction implicite de dbut de


transaction
Certaines implmentations de SQL exigent que vous leur signaliez le dbut
dune transaction laide dune instruction explicite telle que BEGIN ou
BEGIN TRAN. Mais le standard SQL ne limpose pas. Si vous ntes pas
dans le cadre dune transaction active, mais excutez une instruction qui en
requiert une, SQL initiera pour vous une transaction par dfaut. CREATE
TABLE, SELECT et UPDATE sont autant dexemples dinstructions qui
ont besoin pour fonctionner du contexte dune transaction. Lancez une de ces
instructions, et SQL ouvrira une transaction votre place.

SET TRANSACTION
loccasion, vous pouvez avoir utiliser une transaction dont les
caractristiques sont diffrentes des valeurs par dfaut. Il est alors possible
de spcifier ces proprits laide de linstruction SET TRANSACTION
(et ce, avant dexcuter la premire instruction qui requiert une transaction).
SET TRANSACTION vous permet de spcifier un mode, un niveau
disolation et une limite de diagnostic.
Pour changer par exemple ces trois caractristiques la fois, vous pouvez
utiliser linstruction suivante :

SET TRANSACTION
READ ONLY,
ISOLATION LEVEL READ UNCOMMITTED,
DIAGNOSTICS SIZE 4 ;

Avec ce paramtrage, vous ne pourrez pas excuter dinstructions qui


modifient la base de donnes (READ ONLY) et vous aurez spcifi le
niveau disolation le plus bas (READ UNCOMMITTED). La limite de
diagnostic est de 4. Vous utilisez donc le minimum des ressources du
systme.
Regardez maintenant cette instruction :

SET TRANSACTION
READ WRITE,
ISOLATION LEVEL SERIALIZABLE,
DIAGNOSTICS SIZE 8 ;

Ces caractristiques vous permettent de modifier la base de donnes. Elles


vous donnent le plus haut niveau disolation et repoussent la limite de
diagnostic la valeur 8. Ces paramtres mobilisent davantage les
ressources du systme. En fonction de la nature de limplmentation que
vous utilisez, ces proprits peuvent (ou non) tre identiques celles de la
transaction par dfaut. Naturellement, toutes les combinaisons possibles
sont a priori envisageables.
Utilisez toujours le niveau disolation qui correspond vos besoins.
Lutilisation constante du niveau SERIALIZABLE peut sembler une bonne
solution, mais ce nest pas vrai pour tous les systmes. Selon votre
implmentation et ce que vous faites, elle peut en effet pnaliser les
performances de faon significative. Si vous ne comptez pas modifier votre
base de donnes au cours de la transaction, passez au mode READ ONLY.
Respectez la rgle dor : ne jamais sapproprier les ressources du systme
dont vous navez pas besoin.

COMMIT
Le standard SQL ne possde pas de mot cl explicite pour signaler le dbut
dune transaction. Par contre, il en contient deux qui spcifient la fin dune
transaction : COMMIT et ROLLBACK. Utilisez COMMIT si vous souhaitez
valider les modifications apportes la base de donnes. Vous disposez
aussi du mot cl optionnel WORK (COMMIT WORK). Sil se produit une
erreur dans la base, ou si le systme plante lors de lexcution de COMMIT,
vous devrez certainement annuler la transaction, puis essayer de la
recommencer nouveau.

ROLLBACK
Lorsquune transaction se termine, vous pouvez dcider dinvalider les
modifications apportes la base lors de cette transaction. En fait, le but est
alors de restaurer la base dans ltat qui tait le sien avant que la
transaction ne dbute. Pour cela, excutez une instruction ROLLBACK.
ROLLBACK est un mcanisme rsistant aux erreurs.
Mme si le systme se plante lors de lexcution de ROLLBACK, vous
pourrez relancer cette instruction une fois le systme rtabli. Elle reprendra
son travail et restaurera la base de donnes dans son tat prtransactionnel.

Verrouiller les objets de la base de


donnes
Le niveau disolation spcifi par dfaut (ou par une instruction SET
TRANSACTION) dtermine le degr de zle dont doit faire preuve votre
SGBD pour protger votre travail des interactions avec celui des autres
utilisateurs. La principale protection que vous offre le SGBD contre des
transactions dangereuses est la possibilit de verrouiller les objets de la
base de donnes que vous utilisez. Voici quelques exemples :

UNE BASE ACID

Il arrive que certains concepteurs disent quils veulent que leurs bases
de donnes soient ACID. Cela ne signifie pas du tout quils souhaitent
les dissoudre dans un bouillon fumant. ACID est simplement un
acronyme qui signifie Atomicit, Consistance, Isolation, Durabilit. Ces
quatre caractristiques sont ncessaires pour protger une base de
donnes contre la corruption :
Atomicit : Une transaction devrait tre atomique au sens
classique du terme, autrement dit tre traite comme une
unit indivisible. Soit elle est excute en totalit (COMMIT),
soit la base est restaure dans son tat antrieur, comme si
la transaction navait jamais exist (ROLLBACK).

Consistance : Curieusement, la signification de la


consistance nest pas particulirement cohrente (ou
linverse). Elle varie en effet dune application une autre. Si
vous transfrez par exemple des fonds entre deux comptes
bancaires, le total de largent sur lensemble des deux
comptes ne devrait pas varier entre le dbut et la fin de la
transaction. Dans une autre situation, votre critre de
consistance pourrait trs bien tre diffrent.

Isolation : Dans lidal, toutes les transactions qui


sexcutent simultanment sur une base de donnes
devraient tre totalement isoles les unes des autres. Cette
condition est remplie si ces transactions sont srialisables.
Mais lorsquun systme a traiter un ensemble de
transactions avec un trs haut dbit, abaisser le niveau
disolation peut tre utile pour amliorer les performances.

Durabilit : Une fois votre transaction termine (soit par


COMMIT, soit par ROLLBACK), vous devez avoir la certitude que
la base se trouve dans ltat voulu : avec des donnes
parfaitement enregistres, non corrompues, fiables, jour.
Mme si votre systme vous lche brutalement aprs un
COMMIT (mais avant que les rsultats de la transaction soient
enregistrs sur le disque), un SGBD durable doit tre en
mesure de garantir que la base sera bien restaure dans ltat
qui vient dtre dcrit.
La ligne de la table sur laquelle vous tes en train de
travailler est verrouille. Les autres utilisateurs ne peuvent
pas accder cet enregistrement.

Une table est verrouille dans sa totalit si vous effectuez


une opration susceptible de laffecter globalement.

Laccs en lecture est autoris, mais pas lcriture. Parfois,


cest linverse.

Chaque implmentation dispose dun systme de verrouillage qui lui est


propre. Certaines sont plus sres que dautres. Mais la majorit des
systmes rcents vous protgent des problmes les plus graves susceptibles
de survenir lors daccs concurrents.

Sauvegarder vos donnes


Votre DBA devrait effectuer rgulirement des sauvegardes. Il est
indispensable de sauvegarder tous les lments du systme au bout dun
certain laps de temps qui est fonction de la frquence de leur utilisation. Si
vous mettez jour quotidiennement votre base de donnes, il faut la
sauvegarder tous les jours. Vos applications, formulaires et rapports
peuvent aussi voluer, mais moins souvent. Chaque fois quils seront
actualiss, votre DBA devra en sauvegarder les nouvelles versions.
Conservez plusieurs gnrations de sauvegarde. Un problme survenu dans
la base de donnes peut ntre diagnostiqu que bien plus tard. Pour
restaurer la dernire bonne version, vous devrez revenir en arrire de
plusieurs sauvegardes.
Il existe plusieurs mthodes de sauvegarde :
Utiliser SQL pour crer des tables de sauvegarde et y
copier les donnes.

Utiliser un mcanisme spcifique limplmentation qui


sauvegarde tout ou partie du contenu de la base de
donnes. Cette solution est en rgle gnrale bien plus
efficace et plus simple mettre en uvre que faire appel
SQL.

Votre installation peut comporter un mcanisme capable de tout


sauvegarder, y compris les bases de donnes, les documents, les feuilles de
calcul, les utilitaires et les jeux vido. Dans ce cas, il ne vous reste plus
qu vrifier si les sauvegardes sont effectues assez rgulirement pour
vous protger.

Points de sauvegarde et sous-


transactions
Dans lidal, les transactions devraient tre atomiques, aussi indivisibles
que les Grecs le pensaient des plus petits lments de la matire.
Cependant, les atomes ne sont pas vraiment indivisibles. On a dcouvert
depuis longtemps quils sont constitus de parties plus petites, lectrons,
protons et neutrons, dont on sait aujourdhui quelles ne sont mme pas
atomiques puisquelles sont constitues de quarks et de gluons.
Depuis la version SQL:1999, les transactions sur les bases de donnes ne
sont pas non plus rellement atomiques. Une transaction peut tre
subdivise en plusieurs sous-transactions. Chaque sous-transaction se
termine par une instruction SAVEPOINT, qui est utilise conjointement
avec linstruction ROLLBACK. Avant la cration des points de sauvegarde
(lendroit du programme o linstruction SAVEPOINT prend effet),
linstruction ROLLBACK tait utilise uniquement pour annuler lintgralit
de la transaction. prsent, vous pouvez en annuler seulement une partie.
La principale utilit de linstruction ROLLBACK est de prvenir toute
corruption des donnes quand une transaction est interrompue par une
condition derreur. Annuler une transaction jusqu un certain point de
sauvegarde na aucun sens si lerreur sest produite pendant le droulement
de la transaction. Dans ce cas, vous voulez videmment restaurer la base de
donnes dans ltat qui tait le sien avant le dbut de cette transaction. Mais
vous pouvez avoir dautres raisons pour oprer une annulation partielle.
Supposons que vous effectuiez une srie doprations complexes sur vos
donnes. En cours de route, vous rcuprez des rsultats qui vous font
comprendre que vous vous tes engag dans une mauvaise voie. Si vous
avez plac une instruction SAVEPOINT juste avant demprunter cette
piste, vous pouvez annuler la transaction jusquau point de sauvegarde et
essayer une autre direction. En supposant que le code tait bon jusquau
point de sauvegarde, cette solution sera bien plus efficace que deffacer la
totalit de la transaction pour tout recommencer zro.
Pour insrer un point de sauvegarde dans votre code SQL, utilisez la
syntaxe suivante :

SAVEPOINT nom_pointsauve;

Vous pouvez dclencher lannulation jusqu un point de sauvegarde


laide du code suivant :

ROLLBACK TO SAVEPOINT nom_pointsauve;

Linstruction SAVEPOINT nest pas propose dans toutes les


implmentations. Vrifiez ce quen dit votre documentation.

Contraintes et transactions
Il ne suffit pas de vrifier que les donnes sont du bon type pour garantir
quune base est valide. Par exemple, les valeurs nulles sont interdites dans
certaines colonnes, tandis que dautres doivent contenir uniquement des
valeurs qui appartiennent une certaine plage. Jaborde ces restrictions,
galement appeles contraintes, au Chapitre 5.
Les contraintes concernent naturellement les transactions, car elles peuvent
vous empcher de faire ce que vous voulez (aprs tout, elles sont dailleurs
l aussi pour cela). Vous comptez par exemple ajouter des donnes une
table qui contient des colonnes sur lesquelles pse la contrainte NOT
NULL. Une mthode courante consiste ajouter une ligne vide la table,
puis y insrer plus tard des valeurs. Mais la contrainte NOT NULL qui
pse sur une colonne vous interdit demployer cette stratgie. SQL ne
permet pas dajouter une ligne qui contient une valeur nulle dans une
colonne sur laquelle pse une contrainte NOT NULL, et ce mme si vous
comptez y stocker une valeur avant la fin de votre transaction. Pour
contourner ce problme, SQL vous permet de dsigner les contraintes
comme tant soit DEFERRABLE, soit NOT DEFERRABLE.
Les contraintes NOT DEFERRABLE sont immdiatement appliques. Vous
pouvez spcifier quune contrainte DEFERRABLE est ou bien DEFERRED
ou bien IMMEDIATE. Si une contrainte DEFERRABLE est IMMEDIATE,
elle fonctionne comme une contrainte NOT DEFERRABLE (elle est donc
applique immdiatement). Si une contrainte DEFERRABLE est
DEFERRED, elle nest pas applique tout de suite.
Pour ajouter des enregistrements vides ou effectuer toute autre opration qui
peut violer des contraintes DEFERRABLE, vous pouvez utiliser une
instruction comme celle-ci :

SET CONSTRAINTS ALL DEFERRED ;

Cette instruction change toutes les contraintes DEFERRABLE en condition


DEFERRED sans affecter les contraintes NOT DEFERRABLE. Une fois
que vous avez effectu toutes les oprations susceptibles de violer vos
contraintes, et que la table atteint un tat qui ne les viole pas, vous pouvez
les appliquer nouveau laide de linstruction suivante :

SET CONSTRAINTS ALL IMMEDIATE ;

Si vous avez fait une erreur et que lune de vos contraintes est actuellement
viole, vous le saurez ds lexcution de cette instruction.
Si vous ne spcifiez pas explicitement que vos contraintes DEFERRED
sont IMMEDIATE, SQL le fera votre place lorsque vous essaierez de
valider votre transaction par une COMMIT. Si une violation est dtecte
ce moment, la transaction ne sera pas valide et SQL vous renverra un
message derreur.
La gestion des contraintes SQL vous protge contre la saisie de valeurs
invalides tout en vous permettant den violer temporairement certaines dans
le cadre dune transaction active.
Lexemple qui suit vous montre combien il est important de pouvoir diffrer
lapplication des contraintes.
Supposez quune table EMPLOYES contienne les colonnes EMP_ NO,
EMP_NOM, DEPT_NO et SALAIRE. DEPT_NO est une cl trangre qui
rfrence la table DEPT. Cette table DEPT est forme des colonnes
DEPT_NO et DEPT_NOM ; DEPT_NO est sa cl primaire.
En plus, vous voulez disposer dune table semblable DEPT qui contienne
une colonne TOTALPAIE, afin dy enregistrer le total des valeurs
SALAIRE pour les employs de chaque dpartement.
Vous pouvez crer lquivalent de cette table sous forme dune vue, comme
ceci :

CREATE VIEW DEPT2 AS


SELECT D.*, SUM(E.SALAIRE) AS TOTALPAIE
FROM DEPT D, EMPLOYES E
WHERE D.DEPT_NO = E.DEPT_NO
GROUP BY D.DEPT_NO ;

Il est galement possible de dfinir cette vue ainsi :

CREATE VIEW DEPT3 AS


SELECT D.*,
(SELECT SUM(E.SALAIRE)
FROM EMPLOYES E
WHERE D.DEPT_NO = E.DEPT_NO)
AS TO-
TALPAIE
FROM DEPT D ;

Mais supposons maintenant que, pour des raisons defficacit, vous ne


souhaitiez pas calculer le total chaque fois que vous rfrencez DEPT.
TOTALPAIE. En ralit, vous voudriez plutt ajouter une vraie colonne
TOTALPAIE dans la table DEPT. Cette colonne serait mise jour lors de
chaque modification de salaire.
Pour vous assurer que la colonne SALAIRE est fiable, appliquez-lui une
contrainte dans la dfinition de la table :
CREATE TABLE DEPT
(DEPT_NO CHAR(5),
DEPT_NOM CHAR(20),
TOTALPAIE DECIMAL(15,2),
CHECK (TOTALPAIE = (SELECT SUM(SALAIRE)
FROM EMPLOYES E WHERE E.DEPT_NO =
DEPT.DEPT_NO)));

prsent, vous voulez augmenter le SALAIRE de lemploy 123


de 100 units. Vous allez par exemple utiliser linstruction suivante :

UPDATE EMPLOYES
SET SALAIRE = SALAIRE + 100
WHERE EMP_NO = 123 ;

Vous ne devez pas non plus oublier dactualiser la table DEPT :

UPDATE DEPT D
SET TOTALPAIE = TOTALPAIE + 100
WHERE D.DEPT_NO = (SELECT E.DEPT_NO
FROM EMPLOYES E
WHERE E.EMP_NO = 123) ;

(Vous utilisez une sous-requte pour rfrencer le DEPT_NO de


lemploy 123.)
Mais il reste un problme. Les contraintes sont contrles aprs chaque
instruction. En principe, toutes les contraintes sont vrifies. Dans la
pratique, les implmentations ne testent que les contraintes qui rfrencent
des valeurs modifies par linstruction.
Aprs le premier UPDATE ci-dessus, limplmentation vrifie toutes les
rfrences dont les valeurs sont modifies par linstruction, ce qui inclut
celle qui est dfinie dans la table DEPT. En effet, cette contrainte rfrence
la colonne SALAIRE de la table EMPLOYE et linstruction UPDATE
modifie cette colonne. La contrainte est viole aprs le premier UPDATE.
Vous supposez que la base de donnes est dans un tat correct avant
lexcution de linstruction UPDATE, et que chaque valeur TOTALPAIE
de la table DEPT est gale la somme des SALAIRE correspondants de la
table EMPLOYES. Mais cette galit nest plus vraie ds que le premier
UPDATE incrmente une valeur SALAIRE. La seconde instruction
UPDATE corrige cette anomalie et remet la base de donnes dans un tat
o la contrainte est vrifie. Mais entre les deux instructions, cette
contrainte est bel et bien viole.
Linstruction SET CONSTRAINTS DEFERRED vous permet de
dsactiver ou de suspendre temporairement toutes ou certaines contraintes.
La vrification de ces contraintes est diffre jusqu lexcution dun SET
CONSTRAINTS IMMEDIATE ou dune instruction COMMIT ou
ROLLBACK. Vous pouvez donc dlimiter les deux UPDATE prcdents par
des instructions SET CONSTRAINTS. Le code se prsente alors ainsi :

SET CONSTRAINTS DEFERRED ;


UPDATE EMPLOYES
SET SALAIRE = SALAIRE + 100
WHERE EMP_NO = 123 ;
UPDATE DEPT D
SET TOTALPAIE = TOTALPAIE + 100
WHERE D.DEPT_NO = (SELECT E.DEPT_NO
FROM EMPLOYES E
WHERE E.EMP_NO = 123) ;
SET CONSTRAINTS IMMEDIATE ;

Cette procdure diffre lapplication de toutes les contraintes. Si vous


insrez de nouvelles lignes dans DEPT, les cls primaires ne seront pas
vrifies. Vous venez donc de supprimer une protection dont vous pouvez
avoir besoin. Par consquent, il vaut mieux nommer explicitement les
contraintes que vous voulez diffrer :

CREATE TABLE DEPT


(DEPT_NO CHAR(5),
DEPT_NAME CHAR(20),
TOTALPAIE DECIMAL(15,2),
CONSTRAINT PAIE_CONTRAINTE
CHECK (TOTALPAIE = SELECT SUM(SALAIRE)
FROM EMPLOYES E
WHERE E.DEPT_NO = DEPT.DEPT_NO)) ;

Vous pouvez ensuite rfrencer individuellement vos contraintes :

SET CONSTRAINTS PAIE_CONTRAINTE DEFERRED ;


UPDATE EMPLOYES

SET SALAIRE = SALAIRE + 100


WHERE EMP_NO = 123 ;
UPDATE DEPT D
SET TOTALPAIE = TOTALPAIE + 100
WHERE D.DEPT_NO = (SELECT E.DEPT_NO
FROM EMPLOYES E
WHERE E.EMP_NO = 123) ;
SET CONSTRAINTS PAY_EQ_SUMSAL IMMEDIATE;

Si linstruction CREATE ne contient aucun nom de contrainte, SQL en


gnre un implicitement. Ce nom implicite est stock dans les tables du
schma (cest--dire dans le catalogue). Toutefois, il vaut mieux employer
des noms explicites. Supposez maintenant que, dans la seconde instruction
UPDATE, vous avez spcifi par erreur une valeur dincrment de 1 000.
Cette valeur est autorise dans linstruction UPDATE, car lapplication de
la contrainte a t diffre. Mais, lors de lexcution de SET
CONSTRAINTS IMMEDIATE, les contraintes spcifies sont contrles.
En cas dchec, SET CONSTRAINTS provoque une exception. Si vous
excutez une instruction COMMIT la place de SET CONSTRAINTS
IMMEDIATE et que les contraintes ne sont pas values comme tant
toutes vrifies, linstruction COMMIT effectuera un ROLLBACK.
Rappelez-vous que vous ne pouvez diffrer lapplication des contraintes
que dans le cadre dune transaction. Ds que cette dernire se termine soit
par ROLLBACK, soit par COMMIT, les contraintes sont ractives et
vrifies. Si vous utilisez correctement cette mthode, vous ne crerez pas
de donnes qui violeraient une contrainte disponible pour dautres
transactions.
Chapitre 16
Utiliser SQL dans des applications
DANS CE CHAPITRE :
Utiliser SQL dans une application.

Combiner SQL avec des langages procduraux.

Faire face aux incompatibilits de langage.

Intgrer SQL dans un code procdural.

Appeler des modules SQL depuis un code procdural.

Invoquer SQL depuis un outil RAD.

L
es prcdents chapitres nont trait que de SQL. Des questions relatives
la manipulation des donnes ont t souleves et des requtes SQL
dveloppes pour y rpondre. Cette mthode de travail, cest--dire le
SQL interactif, permet dapprendre tout ce que SQL peut faire mais ne
correspond pas du tout la manire dont SQL est utilis gnralement.

Mme si la syntaxe de SQL est proche de celle dun langage naturel (en
loccurrence langlais), ce langage nest pas facile matriser. La grande
majorit des utilisateurs dordinateurs ne sait toujours pas utiliser SQL. Et
il est probable que cette situation perdurera, mme si ce livre devient un
best-seller. Ds quun utilisateur lambda se pose une question au sujet des
bases de donnes, il ne pense certainement pas sasseoir devant son
terminal pour saisir une instruction SELECT. Ce travail est rserv aux
analystes et aux dveloppeurs dapplications, lesquels ne font gnralement
pas carrire en saisissant des requtes ad hoc dans des bases de donnes
longueur de journe. Ils dveloppent des applications qui gnrent ces
requtes leur place.
Si vous comptez effectuer une mme tche de manire rptitive, vous
navez aucune envie de la saisir chaque fois via la console. Vous prfrerez
crire une application qui excute cette tche de sorte que vous puissiez
lexcuter immdiatement chaque fois que vous le souhaitez. SQL peut ainsi
tre intgr dans une application, mais il fonctionne alors dune manire
lgrement diffrente de celle que nous avons pu voir jusqu prsent.

SQL dans une application


Au Chapitre 2, SQL est prsent comme un langage de programmation
incomplet. Pour lutiliser dans une application, vous devez le combiner un
langage procdural tel que Visual Basic, C, C++, C#, Java, COBOL ou
encore Python. La structure particulire de SQL lui confre des avantages et
des inconvnients. Les langages procduraux, quant eux, ont une structure
diffrente, et donc diffrents avantages et inconvnients.
Fort heureusement, les avantages de SQL tendent compenser les
inconvnients des langages procduraux. De mme, les avantages des
langages procduraux rsident justement l o SQL est faible. En combinant
les deux, vous serez en mesure de crer des applications particulirement
efficaces. Il existe maintenant des environnements de dveloppement
dapplication rapide orients objet (RAD, Rapid Application
Development), tels que Visual Studio de Microsoft ou lenvironnement
gratuit Eclipse, qui incorporent du code SQL dans vos applications via la
manipulation dobjets plutt que lcriture de code procdural.

Gardez un il sur lastrisque


Dans les prcdents chapitres, nous avons utilis lastrisque (*) comme
notation abrge signifiant toutes les colonnes de la table . Lastrisque
est particulirement utile si une table contient de nombreuses colonnes.
Mais lusage de ce caractre peut poser des problmes lorsque vous
intgrez du SQL dans une application.
Une fois lapplication crite, une tierce personne (ou vous-mme) peut
ajouter de nouvelles colonnes dans une table et/ ou en supprimer
danciennes. Cela peut changer la signification de toutes les colonnes .
Lapplication qui utilise lastrisque peut alors rcuprer des colonnes bien
diffrentes de celles quelle attendait.
Ce type de modification dune table naffecte pas les programmes existants
tant quils nont pas t recompils soit pour corriger un bogue, soit pour en
modifier certaines fonctionnalits (ce qui peut ne se produire que plusieurs
mois plus tard). Leffet du caractre * est alors tendu toutes les
colonnes actuelles de la table, ce qui peut provoquer un plantage de
lapplication pour une tout autre raison que lobjet de la recompilation. Et
le cauchemar commence...
Pour viter ce type de problme, nutilisez pas lastrisque et spcifiez
explicitement le nom de toutes les colonnes dans lapplication.

Forces et faiblesses de SQL


SQL est parfaitement adapt la rcupration des donnes. Si des
informations importantes sont enterres quelque part dans une table dune
base de donnes, SQL vous fournira tous les outils dont vous avez besoin
pour les retrouver. Vous navez pas besoin de connatre lordre des lignes et
des colonnes dans une table, car SQL ne manipule pas ces objets
individuellement. Les fonctionnalits transactionnelles de SQL vous
garantissent que vos oprations sur la base de donnes ne seront pas
affectes par des accs simultans aux tables que vous tes en train de
manipuler.
Par contre, lun des principaux inconvnients de SQL est la rusticit de son
interface utilisateur. SQL ne propose rien pour prsenter agrablement des
crans de saisie ou des rapports. Il accepte des commandes en mode
console et retourne des valeurs sur lcran du terminal ligne aprs ligne.
Parfois, une force dans un certain contexte peut savrer une faiblesse dans
un autre. Lun des avantages de SQL est sa capacit oprer sur une table
entire en une fois. Une seule instruction SELECT peut traiter toutes les
donnes dune table, que celle-ci contienne une ligne ou des centaines,
voire des milliers de lignes. Cependant, SQL nest pas trs laise lorsquil
sagit de manipuler une ligne en particulier, ce qui peut constituer un
problme si cest ce que vous souhaitez faire. Dans ce cas, vous pouvez
utiliser les curseurs de SQL ou faire appel un langage procdural hte.

Forces et faiblesses des langages


procduraux
Contrairement SQL, les langages procduraux sont conus pour raliser
des oprations ligne par ligne, ce qui permet au dveloppeur de
lapplication de contrler trs prcisment le traitement appliqu une
table. Ce contrle fin est une des grandes forces des langages procduraux.
Toutefois, cest aussi lun de leurs principaux inconvnients. Le
dveloppeur doit en effet savoir exactement o sont stockes les tables dans
la base de donnes. Lordre des lignes et des colonnes est important et doit
tre pris en compte.
Du fait de leur nature tape par tape , les langages procduraux offrent
une grande souplesse quant la cration dcrans de saisie et de
visualisation des donnes. Ils vous permettent galement de procder des
impressions sophistiques de rapports.

Problmes lis la combinaison de


SQL et dun langage procdural
tant donn que les forces de SQL compensent les faiblesses des langages
procduraux et vice versa, il parat cohrent dassocier les deux pour
additionner leurs avantages sans tre pnalis par leurs faiblesses
respectives. Mais aussi intressante que soit cette combinaison, elle est loin
dtre simple mettre en uvre. Vous devrez surmonter certains challenges
avant den arriver au mariage parfait.

Diffrence des modes opratoires


Un des grands problmes poss par la combinaison de SQL et dun langage
procdural est que SQL manipule des tables entires tandis quun langage
procdural traite une ligne la fois. Parfois, ce problme est mineur. Vous
pouvez diffrencier les oprations qui sappliquent des tables de celles
qui concernent des lignes en faisant appel aux outils appropris.
Mais vous risquez davoir un problme si vous voulez rechercher dans une
table les enregistrements qui rpondent certains critres, puis traiter ces
enregistrements de diffrentes manires selon quils rpondent ou non aux
conditions. Un tel processus requiert la fois la puissance de SQL pour
rcuprer les donnes et les fonctionnalits du langage procdural pour
traiter les conditions. Vous pouvez simplement intgrer des instructions SQL
des emplacements stratgiques dun programme que vous avez crit dans
un langage procdural (nous allons revenir un peu plus loin sur cette
question).

Incompatibilits des types de donnes


Lintgration de SQL dans un langage procdural est confronte un autre
problme : les types de donnes de SQL sont diffrents de ceux qui sont
utiliss par les langages procduraux les plus rpandus. Cela na rien en soi
de trs surprenant, puisque les types de donnes diffrent de toute manire
dun langage procdural un autre.
Il nexiste aucune standardisation des types de donnes pour les langages de
programmation. Avant la version 92 de SQL, lincompatibilit des types de
donnes posait un problme majeur. Mais depuis SQL-92 (et ses
successeurs), linstruction CAST permet de rsoudre cette difficult. Le
Chapitre 9 explique en dtail comment vous pouvez utiliser CAST pour
convertir des types de donnes dun langage procdural en un type reconnu
par SQL, pourvu quil y ait compatibilit entre la source et la destination.

Utiliser SQL dans des langages


procduraux
Mme si lintgration de SQL dans des langages procduraux se heurte de
nombreuses difficults, elle nen reste pas moins possible. En fait, vous
devez mme procder de cette manire dans de nombreux cas, ds lors quil
vous faut produire les rsultats voulus dans le temps imparti. Vous disposez
mme pour cela de plusieurs mthodes. La section suivante en propose
trois : SQL intgr, le langage de module et les outils RAD.

SQL intgr
La solution adopte pour combiner du code SQL et du code crit dans un
langage procdural est le SQL intgr. Vous vous demandez comment cela
peut fonctionner ? Cest aussi simple que ce que vous lisez : les instructions
SQL sont parachutes en plein milieu du langage procdural l o il y en a
besoin.
Comme vous le savez, une instruction SQL qui surgit soudainement au beau
milieu dun programme C peut poser un problme au compilateur qui ne sy
attend pas. Cest pourquoi les programmes qui contiennent du SQL intgr
sont gnralement traits par un prprocesseur avant dtre compils ou
interprts. Le prprocesseur est averti de la prsence de code SQL par la
directive EXEC SQL.
Examinons un programme crit dans la version Pro*C dOracle du langage
C. Cette petite application accde la table des employs dune socit,
demande lutilisateur de saisir un nom, puis affiche le salaire et la
commission de cet employ. Elle propose alors lutilisateur de saisir de
nouvelles valeurs pour le salaire et la commission, aprs quoi elle met
jour la table avec les valeurs actualises :

EXEC SQL BEGIN DECLARE SECTION;


VARCHAR uid[20];
VARCHAR pwd[20];
VARCHAR enom[10];
FLOAT salaire, comm;
SHORT salaire_ind, comm_ind;
EXEC SQL END DECLARE SECTION;
main()
{
int sret; /* code retour de scanf */
/* Connexion */
strcpy(uid.arr,FRED); /* Copier le nom de
lutilisateur
*/
uid.len=strlen(uid.arr);
strcpy(pwd.arr,TOWER); /* Copier le mot de
passe */
pwd.len=strlen(pwd.arr);

EXEC SQL WHENEVER SQLERROR STOP;


EXEC SQL WHENEVER NOT FOUND STOP;
EXEC SQL CONNECT :uid;
printf(Utilisateur connect : \n , uid.arr);
printf(Saisissez le nom de lemploy modifier
: );
scanf(%s,ename.arr);
ename.len=strlen(ename.arr);
EXEC SQL SELECT SALAIRE,COMM INTO :salaire,:comm
FROM EMPLOYES
WHERE ENOM=:enom;
printf(Employe: pourcentages salaire: %6.2f
comm: %6.2f
\n,
enom.arr, salaire, comm);
printf(Saisissez le nouveau salaire : );
sret=scanf(%f,&salaire);
salaire_ind = 0;
if (sret == EOF ! ! sret == 0) /* Positionner
lindicateur
*/
salaire_ind =-1; /* Positionner lindicateur pour
NULL */
printf(Saisissez la nouvelle commission : );
sret=scanf(%f,&comm);
comm_ind = 0; /* Positionner lindicateur */
if (sret == EOF ! ! sret == 0)
comm_ind=-1; /* Positionner lindicateur pour
NULL */
EXEC SQL UPDATE EMPLOYES
SET SALARIE=:salaire:salaire_ind
SET COMM=:comm:comm_ind
WHERE ENOM=:enom;
printf(Employ %s modifi. \n,enom.arr);
EXEC SQL COMMIT WORK;
exit(0);
}

Nul besoin dtre un expert en C pour comprendre quoi sert ce code et


comment il le fait. Rsumons tout de mme le droulement des instructions
ci-dessus :

1. SQL commence par dclarer des variables htes.

2. Le code C contrle la squence de connexion de


lutilisateur.

3. SQL met alors en place la gestion derreurs et se connecte


la base de donnes.

4. Le code C demande le nom dun employ et le stocke dans


une variable.

5. Une instruction SQL SELECT rcupre le salaire et la


commission de lemploy ainsi dsign et les stocke dans
les variables htes : salaire et : com.

6. Le code C reprend la main et affiche le nom de lemploy,


son salaire et sa commission, puis demande lutilisateur
de saisir les nouvelles valeurs du salaire et de la
commission. Il vrifie que la saisie a t effectue. Si elle ne
la pas t, il positionne un indicateur.

7. Le SQL met jour la base de donnes avec les nouvelles


valeurs.

8. Le C affiche alors le message indiquant que lopration est


termine.

9. Enfin, le SQL valide la transaction et le C met fin au


programme.
Le prprocesseur vous permet de combiner des commandes des deux
langages. Il spare les instructions SQL des instructions du langage hte en
les stockant dans une routine externe. Chaque instruction SQL est remplace
par un appel (CALL) du langage hte vers cette routine externe. Le
compilateur du langage peut alors faire son travail.
La manire dont le code SQL est transmis la base de donnes dpend de
limplmentation. En tant que dveloppeur, vous navez pas vous
proccuper de cette question. Cest le prprocesseur qui sen charge.

Dclarer des variables htes


Le programme crit dans le langage hte et les segments SQL ont besoin
dchanger des informations. Pour cela, il vous faut utiliser des variables
htes que vous devez dclarer avant dy faire appel, sans quoi SQL ne les
reconnatra pas. Ces dclarations sont incluses dans un segment dclaratif
qui prcde le segment programme. Elles sont annonces par la directive
suivante :

EXEC SQL BEGIN DECLARE SECTION ;

La fin du segment dclaratif est signale par :

EXEC SQL END DECLARE SECTION ;

Toute instruction SQL doit tre prcde de la directive SQL EXEC. La fin
dun segment dclaratif peut ventuellement tre signale par une directive
de terminaison. En COBOL, cette directive de terminaison est END-EXEC.
En C, il sagit dun point-virgule.

Convertir des types de donnes


En fonction du degr de compatibilit des types de donnes du langage hte
et ceux de SQL, vous allez recourir si ncessaire CAST pour raliser
certaines conversions. Vous pouvez utiliser pour cela des variables htes
qui ont t dclares dans DECLARE SECTION. Noubliez pas de faire
prcder le nom de la variable hte dun deux-points ( : ) lorsque vous
lemployez dans des instructions SQL. Par exemple :

INSERT INTO ALIMENTS


(NOM, CALORIES, PROTEINES, GRAISSES,
HYDRATECARBONE)
VALUES
(:nom, :calories, :protines, :graisses,
:carbo) ;

Langage de module
Le langage de module est une autre solution pour utiliser SQL avec un
langage procdural. Avec ce type de langage, vous stockez explicitement
toutes vos instructions SQL dans un module distinct.
Un module SQL est tout simplement une liste dinstructions SQL. Chaque
instruction est incluse dans une procdure SQL et est prcde dune
spcification du nom de la procdure ainsi que du nombre et du type de ses
paramtres.
Chaque procdure SQL contient une seule instruction SQL. Dans le
programme hte, vous appelez explicitement la procdure l o vous
comptez excuter linstruction SQL quelle contient. Tout se passe donc
comme sil sagissait dun sous-programme crit dans le langage hte.
Lutilisation de modules SQL revient en quelque sorte effectuer la main
le travail du prprocesseur.
Le SQL intgr est bien plus souvent utilis que la mthode langage de
module . La plupart des diteurs proposent une forme de langage de
module, mais peu insistent sur le sujet dans leur documentation. Les
langages de module prsentent plusieurs avantages :
Les programmeurs en SQL nont pas besoin dtre en
plus des spcialistes dun langage procdural. Comme
SQL est compltement isol du langage procdural, vous
pouvez louer les services des meilleurs dveloppeurs SQL
pour crire le code de vos modules (quils soient ou non
familiariss avec votre langage procdural). En fait, il est
mme possible de diffrer le choix dun langage procdural
jusqu ce que vos modules SQL soient crits et dbogus.
Vous pouvez louer les services des meilleurs
dveloppeurs pour votre langage procdural, mme
sils ny connaissent rien en SQL. Lide est simple : si vos
technogourous SQL nont pas besoin dtre des experts du
langage procdural, la rciproque est aussi vraie.

SQL nest pas mlang au code procdural, si bien que


vous pouvez utiliser le dbogueur de votre langage
procdural. Cela peut vous faire gagner un temps
considrable de dveloppement.

Encore une fois, un avantage vu sous un certain angle peut savrer un


inconvnient dun autre point de vue. Comme les modules SQL sont spars
du code procdural, il nest pas si facile de suivre le fil logique de
lapplication lorsque vous essayez den comprendre le fonctionnement.

Dclarations dans un module


La syntaxe des dclarations dans un module employer est la suivante :

MODULE [nom-module]
[NAMES ARE nom-jeu-caractres]
LANGUAGE
{ADA|C|COBOL|FORTRAN|MUMPS|PASCAL|PLI|SQL}
[SCHEMA nom-schma]
[AUTHORIZATION id-autorisation]
[declarations-tables-temporaires...]
[declarations-curseurs...]
[declarations-curseurs-dynamiques...]
procdures...

Comme lindiquent les crochets, le nom du module est optionnel. Toutefois,


il est prfrable de le nommer, ne serait-ce que pour viter toute confusion
dans le code.
La clause optionnelle NAMES ARE spcifie un jeu de caractres. Si vous
ne spcifiez pas cette clause, cest le jeu de caractres par dfaut de votre
implmentation SQL qui sera utilis. La clause LANGUAGE indique au
module quel est le langage qui lappellera. Le compilateur doit disposer de
cette information, car il doit faire croire au programme appelant que les
instructions SQL ne sont quun sous-programme crit dans son propre
langage.
Bien que les clauses SCHEMA et AUTHORIZATION soient facultatives,
vous devez spcifier au moins lune dentre elles (ou les deux). La clause
SCHEMA spcifie le schma par dfaut et la clause AUTHORIZATION
concerne lidentifiant de lautorisation. Cet identifiant tablit les privilges
dont vous disposez. Si vous ne prcisez rien, le SGBD utilisera lidentifiant
associ votre session pour dterminer les privilges attribus votre
module. Si vous navez pas les privilges requis pour effectuer lopration
appele par votre procdure, cette dernire ne sera pas excute.
Si votre procdure doit utiliser des tables temporaires, spcifiez-les avec
une clause de dclaration de table temporaire. Dclarez de mme les
curseurs et les curseurs dynamiques avant toute procdure qui les utilise.
Dclarer un curseur aprs une procdure est autoris partir du moment o
ladite procdure nutilise pas ledit curseur.

Les procdures du module


Enfin, aprs toutes ces dclarations se trouve une liste de procdures. Il
sagit de la partie fonctionnelle du module. Une procdure comporte un
nom, des dclarations de paramtres et des instructions SQL excutables. Le
langage procdural appelle la procdure par son nom et lui passe des
valeurs par lintermdiaire des paramtres dclars. La syntaxe dune
procdure est la suivante :

PROCEDURE nom-procdure
(dclaration-paramtre [, dclaration-paramtre
]... )
SQL instruction;
[SQL instructions ] ;

La dclaration dun paramtre doit prendre la forme suivante :


nom-paramtre type-de-donnes

ou :

SQLSTATE

Les paramtres que vous dclarez peuvent tre des paramtres dentre, des
paramtres de sortie ou les deux la fois. SQLS-TATE est un paramtre
de statut servant rapporter les erreurs.

Outils RAD orients objets


Si vous utilisez des outils RAD volus, vous pouvez dvelopper des
applications complexes sans avoir crire une ligne de code en C++, C#,
Python, Java ou tout autre langage procdural. Il vous suffit de choisir des
objets dans une librairie et de les placer visuellement lcran.
Les objets possdent des proprits qui les caractrisent et sont associs
des vnements appropris leur type. Vous pouvez galement associer une
mthode un objet. Une mthode est une procdure crite dans un langage
procdural. Mais vous pouvez construire des applications utiles sans crire
une seule mthode.
Bien que vous puissiez crer des applications complexes sans recourir un
langage procdural, vous aurez probablement tt ou tard besoin de SQL. En
effet, il est difficile, voire impossible, de reproduire la richesse
dexpression de SQL dans un monde orient objet. Cest pourquoi les outils
RAD labors proposent un mcanisme pour injecter des instructions SQL
dans vos applications orientes objet. Visual Studio de Microsoft en est un
exemple. Access de Microsoft est un autre environnement de
dveloppement dapplications qui vous permet dutiliser SQL en
combinaison avec son langage procdural, VBA.
Le Chapitre 4 vous montre comment crer des tables de bases de donnes
avec Access. Naturellement, cette opration ne reprsente quune faible
partie des possibilits dAccess. Celui-ci est un outil qui sert avant tout
raliser des applications destines traiter les donnes extraites des tables
de vos bases de donnes. En utilisant Access, le dveloppeur positionne
des objets sur des formulaires, puis personnalise ces objets en leur donnant
des proprits, des vnements et des mthodes. Ces formulaires et
mthodes sont ensuite manipuls par du code VBA capable dintgrer des
instructions SQL.
Bien que les outils RAD tels quAccess puissent permettre de produire en
peu de temps des applications de grande qualit, ils sont gnralement
spcifiques une plate-forme. Par exemple, Access ne fonctionne que sous
le systme dexploitation Windows de Microsoft. Ne loubliez pas si vous
envisagez un jour dcrire des fonctionnalits indpendantes du support, ou
encore de migrer vos applications vers dautres plates-formes.
Les outils RAD tels quAccess sont les premiers fruits dun possible
rapprochement entre les approches relationnelles et orientes objet des
bases de donnes. SQL et les avantages offerts par les structures
relationnelles survivront tous deux. Ils bnficieront des capacits de
dveloppement rapide (et comparativement moins sujet aux erreurs)
apportes par la programmation oriente objet.

Utiliser SQL avec Microsoft Access


Microsoft Access cible essentiellement les personnes qui souhaitent
dvelopper des applications relativement simples sans se soucier
particulirement de programmation. Si tel est votre cas, vous trouverez dans
la collection Pour les Nuls de quoi rpondre vos besoins ! Si vous
voulez aller plus loin en associant le langage procdural dAccess (VBA) et
SQL, la remarque prcdente est encore plus vraie, tant la documentation
livre par Microsoft est limite sur ce sujet. Mais attention :
limplmentation SQL que vous trouvez dans Access est loin dtre
complte, et il vous faudra tout le flair dun Sherlock Holmes pour la
dbusquer.
Dans le Chapitre 3, jai dcrit les trois composants de SQL:le langage de
dfinition de donnes (DDL), le langage de manipulation de donnes (DML)
et le langage de contrle des donnes (DCL). Le sous-ensemble de SQL
contenu dans Access implmente uniquement la partie DML. Les oprations
de cration des tables sont ralises laide de loutil RAD prsent au
Chapitre 4. La mme technique est employe pour limplmentation des
mesures de scurit (elles sont traites au Chapitre 14).
Pour voir un coin de SQL sous Access, il est ncessaire de soulever
quelque peu le voile pos par le RAD. Prenons titre dexemple une base
de donnes cense tre gre par une organisation non gouvernementale
(fictive) : la SEL (Socit pour lcologie lunaire). Cette organisation
comprend plusieurs quipes de recherche, dont notamment la clbre
ERBALU (Equipe de recherche de la base lunaire). Une grave question se
pose : quelles sont les communications savantes crites par les membres de
cette quipe ? Pour y rpondre, une requte a t formule en faisant appel
au mode QBE dAccess (requte par lexemple). Cette requte, qui est
illustre sur la Figure 16.1, rcupre les informations voulues partir des
tables EQUIPES-RECHERCHE, AUTEURS et ARTICLES, avec laide de
tables de recoupage (AUT_ART et AUT_RECH) qui ont t ajoutes afin
de couper les relations plusieurs plusieurs.
Aprs avoir cliqu sur longlet Accueil pour accder la barre doutils,
vous pouvez cliquer sur le menu droulant de licne Vue dans langle
suprieur gauche de la fentre pour rvler les autres types de vues
disponibles lors de la cration de requtes. Lun des choix proposs est le
mode SQL (voir la Figure 16.2). Lorsque vous activez ce mode, la fentre
de lditeur SQL apparat. Elle affiche linstruction SQL gnre par
Access partir des choix oprs dans linterface graphique.

FIGURE 16.1 Conception de la requte Articles ERBALU en mode Cration.


FIGURE 16.2 La vue SQL est propose dans la liste des affichages.

Linstruction SQL montre sur la Figure 16.3 est celle qui est effectivement
envoye au moteur de la base de donnes. Ce moteur, qui sinterface
directement avec la base, ne comprend que le langage SQL. Tout ce que
vous entrez dans le mode dit Cration dAccess est traduit en SQL avant
envoi pour traitement au moteur de la base de donnes.

FIGURE 16.3 Une instruction SQL qui sert retrouver les noms de tous les articles
crits par des membres de lquipe ERBALU.
Vous avez peut-tre remarqu que la syntaxe de linstruction illustre sur la
Figure 16.3 diffre quelque peu de celle du standard SQL ANSI/ISO.
Souvenez-vous du proverbe : Quand tu es Rome, vis comme les
Romains. Lorsque vous travaillez avec Access, utilisez son dialecte SQL.
Ce conseil vaut dailleurs quel que soit lenvironnement dans lequel vous
travaillez. Toutes les implmentations SQL divergent du standard sur tel ou
tel aspect.
Si vous voulez crire directement une requte dans le SQL dAccess
(autrement dit, sans passer par le mode de cration graphique), il vous suffit
deffacer le contenu courant de la fentre ddition et de saisir une nouvelle
instruction SELECT. Cliquez ensuite sur le bouton de la barre doutils qui
affiche un point dexclamation pour excuter votre requte. Le rsultat va
apparatre par dfaut sous la forme dune feuille de donnes.
V
Utiliser SQL dans le monde rel

DANS CETTE PARTIE :

Utiliser ODBC.

Utiliser JDBC.

Travailler sur des donnes XML.


Chapitre 17
ODBC et JDBC
DANS CE CHAPITRE :
Dfinition dODBC.

Description des diverses parties dODBC.

Utilisation dODBC dans un environnement client/serveur.

Utiliser ODBC sur Internet.

Utiliser ODBC sur un intranet.

Utiliser JDBC.

C
es dernires annes, linterconnexion des ordinateurs sest massivement
dveloppe, aussi bien dans les organisations quentre elles. Cette
connectivit frntique a engendr le besoin de partager sur les rseaux
les informations fournies par les bases de donnes. Le principal obstacle au
libre partage de linformation sur les rseaux est lincompatibilit des
systmes dexploitation et des applications qui fonctionnent sur diffrentes
machines. Cet obstacle a t en partie contourn par la cration de SQL,
puis par les volutions qui lont fait progresser au fil des annes.
Hlas ! Le SQL standard nest pas vritablement un standard. Mme les
diteurs de SGBD, qui se disent conformes au standard international SQL,
ont inclus dans leur implmentation de SQL des fonctionnalits qui les
rendent incompatibles avec les extensions propritaires des
implmentations dautres diteurs. Et tous rechignent abandonner leurs
propres extensions, car leurs clients les utilisent dans leurs applications et
en sont devenus dpendants. Il faut donc trouver une autre voie pour assurer
la communication entre SGBD, un outil qui noblige pas les diteurs
niveler par le bas leurs implmentations jusqu atteindre un plus petit
dnominateur commun. Cette solution, cest ODBC (Open DataBase
Connectivity).
ODBC
ODBC est une interface standard entre une base de donnes et une
application qui accde au contenu de cette base. Recourir ce standard
permet un front end applicatif daccder nimporte quelle base de
donnes en utilisant SQL. La seule condition est que front end et back end
adhrent tous deux au standard ODBC, dont la version courante est
ODBC 4.0.
Une application accde une base en utilisant un pilote (ou driver)
spcifiquement conu pour sinterfacer avec cette dernire. Le front end du
pilote, cest--dire la partie qui se connecte lapplication, se conforme
scrupuleusement au standard ODBC. Il prsente toujours la mme interface
lapplication, et ce quel que soit le moteur de la base de donnes quil
permet dattaquer. Le back end du pilote est conu pour dialoguer avec un
type spcifique de moteur de base de donnes. Grce cette architecture,
les applications nont plus besoin dtre modifies en fonction du moteur de
base de donnes qui contrle les donnes que ces applications manipulent.
Toute la machinerie interne est masque.

Linterface ODBC
Linterface ODBC est essentiellement un ensemble de dfinitions reconnu
comme tant un standard. Ces dfinitions concernent tout ce qui doit tre
pris en compte pour tablir une communication entre lapplication et la base
de donnes.
Linterface ODBC dfinit les lments suivants :
Une librairie dappels de fonction.

Une syntaxe SQL standard.

Des types de donnes SQL standard.

Un protocole standard pour se connecter un moteur


de base de donnes.

Des codes derreur standard.


Les appels de fonction ODBC permettent de se connecter un moteur de
base de donnes, dexcuter des instructions SQL et de renvoyer les
rsultats produits lapplication.
Pour effectuer une opration sur la base de donnes, vous devez transmettre
en argument linstruction SQL approprie un appel de fonction ODBC.
Tant que vous utilisez la syntaxe SQL standard comprise par ODBC,
lopration fonctionne, indpendamment du moteur de base de donnes que
vous attaquez.

Les composants dODBC


Linterface ODBC est compose de quatre couches fonctionnelles qui
sintercalent de la manire suivante entre lutilisateur et les donnes sur
lesquelles il souhaite travailler (le but tant dassurer une communication
transparente entre nimporte quel front end compatible et nimporte quel
back end compatible) :
Lapplication : Cest la partie de linterface ODBC la plus
proche de lutilisateur. Lapplication doit tre informe
quelle communique avec une source de donnes via
ODBC. Elle doit se connecter en douceur au pilote ODBC en
respectant scrupuleusement ce standard.

Le gestionnaire du pilote : Il sagit dune DLL (Dynamic


Link Library) gnralement fournie par Microsoft. Le
gestionnaire charge les pilotes qui correspondent aux
sources de donnes du systme (il peut y en avoir
plusieurs) et dirige les appels de fonction provenant de
lapplication vers les sources de donnes adquates via les
pilotes adapts. Ce gestionnaire traite aussi directement
certains appels de fonction ODBC. Enfin, il dtecte et gre
certains types derreurs.

Le pilote : Comme les sources de donnes peuvent tre


diffrentes les unes des autres (et souvent trs diffrentes),
vous devez trouver un moyen de traduire les appels de
fonction ODBC dans le langage natif que comprend chaque
source. Cette traduction est assure par la DLL du pilote.
Chaque DLL de pilote reoit des appels de fonction via
linterface standard ODBC et les transcrit dans un code que
sa source de donnes peut comprendre. Lorsque cette
source retourne un rsultat, le pilote le reformate dans
lautre sens afin de produite un rsultat conforme au
standard ODBC. Le pilote est llment cl qui permet aux
applications compatibles ODBC de manipuler la structure
et le contenu de sources de donnes elles-mmes
compatibles ODBC.

La source de donnes : Elle peut tre de nature


diffrente. Ce peut tre un SGBD relationnel (et sa base de
donnes associe) qui rside sur le mme ordinateur que
lapplication. Ce peut tre galement une base de donnes
sur un ordinateur distant. Il peut aussi sagir dun fichier
ISAM (Indexed Sequential Access Method, mthode daccs
squentielle indexe) sans SGBD associ, et qui se trouve
soit sur un ordinateur local, soit sur un systme distant.
Quelle que soit la forme que prend la source de donnes,
vous devez disposer dun pilote spcifique pour
communiquer avec elle.

ODBC dans un environnement


client/serveur
Dans un environnement client/serveur, linterface entre le client et le
serveur est appele API (Application Programming Interface, interface de
programmation dapplication). Un pilote ODBC, par exemple, contient une
API. Une API peut tre propritaire ou standard. Dans le cas dune API
propritaire, la partie client de linterface a t spcifiquement conue pour
fonctionner avec un back end particulier sur le serveur. Le code qui
constitue cette interface est un pilote, galement appel pilote natif sur un
systme propritaire. Un pilote natif est optimis pour ne fonctionner
quavec un client spcifique et sa source de donnes associe. Du fait de
cette spcialisation, les pilotes natifs ont tendance transmettre commandes
et informations beaucoup plus vite, avec un minimum de dlai dattente lors
de chaque opration.
Si votre systme client/serveur accde toujours au mme type de source de
donnes, et que vous tes certain de ne jamais avoir dautres besoins, vous
pouvez utiliser le pilote natif fourni avec votre SGBD. Par contre, si vous
pensez que vous devrez un jour accder des sources de donnes dun type
diffrent, utilisez une API ODBC pour viter de devoir recommencer plus
tard votre travail.
Les pilotes ODBC sont galement optimiss pour travailler avec des
sources de donnes spcifiques, mais ils prsentent tous la mme interface
au gestionnaire de pilote. Un pilote qui na pas t optimis pour un front
end particulier nest probablement pas aussi rapide quun pilote natif
spcialement conu pour ce front end. Lun des inconvnients des pilotes
ODBC de premire gnration tait quils taient peu performants compars
aux pilotes natifs. Toutefois, des tests rcents ont dmontr que les pilotes
ODBC 4.0 sont devenus bien plus comptitifs. La technologie ODBC est
ce point mature quil nest plus ncessaire de sacrifier la standardisation
sur lautel des performances.

ODBC et Internet
Les oprations sur une base de donnes sont trs diffrentes sur Internet et
sur un systme client/serveur. Du point de vue de lutilisateur, la diffrence
la plus visible rside dans la partie client du systme (qui comprend
linterface utilisateur). Dans le cas dun systme client/serveur, cette
interface est la partie dune application qui communique avec la source de
donnes hberge par le serveur via des instructions SQL compatibles
ODBC. Sur le World Wide Web, la partie client du systme est un
navigateur Web qui communique avec la source de donnes hberge sur le
serveur via HTML (HyperText Markup Language, langage de balises
hypertexte).
De nos jours, HTML nest plus le seul langage du Web. Mais cela ne change
en rien notre propos.

Toute personne pourvue dun navigateur Web peut accder des donnes
disponibles sur le Web. Le fait de mettre en ligne une base de donnes (on
dit aussi publier) offre de nombreux avantages, surtout si vous voulez
partager des informations en dehors de votre rseau local.
Malheureusement, vous ne disposez gnralement pas dun contrle trs
strict sur la personnalit des internautes Cest pourquoi mettre en ligne
des bases de donnes revient plus publier des informations sous-entendu
pour le monde entier qu les partager sous-entendu avec quelques
collgues de travail. Pour autant, ce nest pas parce que votre navigateur est
capable daccder des donnes sur le Web quil sait quoi en faire. Pour
plus de prcisions sur ce point, voyez un peu plus loin la section Les
extensions client . La Figure 17.1 illustre la comparaison entre systmes
client/serveur et systmes sappuyant sur le Web.

FIGURE 17.1 Systme client/serveur versus systme de base de donnes sur le Web.

Les extensions serveur


Dans un systme Web, la communication entre le navigateur qui se trouve
sur le poste client et le serveur Web qui se trouve sur une machine distante
seffectue en HTML. Un composant systme appel extension serveur
traduit le HTML en SQL compatible ODBC. Le serveur de base de donnes
agit sur ce code SQL, qui attaque son tour directement la source de
donnes. Dans la direction inverse, la source de donnes renvoie le rsultat
gnr par une requte lextension serveur via le serveur de base de
donnes. Lextension se charge de transformer ce rsultat dans une forme
que le serveur Web est capable de grer. Les rponses sont alors envoyes
via le Web au navigateur qui se trouve sur la machine client. Enfin, le
navigateur affiche ces rsultats sur lcran de lutilisateur. La Figure 17.2
illustre larchitecture de ce type de systme.

FIGURE 17.2 Systme daccs une base de donnes sur le Web dote dune
extension serveur.

Les extensions client


Certes, les navigateurs Web sont conus et optimiss pour tre faciles
demploi et pour se connecter toutes sortes de sites Web. Mais les
navigateurs les plus rpandus (Microsoft Internet Explorer, Mozilla Firefox
ou encore Apple Safari) nont t ni conus ni optimiss pour servir
dinterface des bases de donnes. Pour manipuler une base de donnes via
Internet, le client a besoin dune fonctionnalit que le navigateur ne fournit
pas. Pour pallier ce problme, diffrents types dextensions client ont t
dvelopps. Ces extensions sont soit des applications dites dassistance
(helper), soit des contrles ActiveX, soit des applettes Java, soit encore
des scripts. Gnralement, les extensions communiquent avec le serveur via
HTML, le principal langage du Web. Un code HTML qui a besoin
daccder une base de donnes est traduit par lextension serveur en SQL
compatible ODBC avant dtre transmis la source de donnes.

Les contrles ActiveX


Les contrles ActiveX de Microsoft fonctionnent avec Internet Explorer, de
trs loin le plus rpandu des navigateurs Web (quoique Chrome et Mozilla
Firefox commencent lui faire un peu dombre).

Les scripts
Les scripts sont les outils les plus souples pour crer des extensions client.
Lemploi dun langage de scripts, comme le polyvalent JavaScript ou
VBScript de Microsoft, vous permet de contrler trs prcisment ce qui se
passe ct client. Vous pouvez mettre en place des validations des champs
de saisie, ce qui permet de rejeter ou corriger des donnes errones sans
avoir les transmettre sur le Web. Cela peut vous faire gagner du temps tout
en diminuant le trafic sur le Web, ce dont les autres utilisateurs vous
remercieront. linstar des applettes Java, les scripts sont intgrs dans
des pages HTML et sexcutent lorsque lutilisateur interagit avec ces
pages.

ODBC sur un intranet


Un intranet est un rseau local ou tendu qui fonctionne exactement comme
une version simplifie dInternet. Comme un intranet se limite une
organisation, vous navez pas besoin de mettre en place des systmes de
scurit labors tels que des pare-feu. Tous les outils conus pour le
dveloppement dapplications sur le Web permettent galement de crer des
applications pour un intranet.
ODBC fonctionne de la mme manire sur un intranet que sur Internet. Si
vous grez plusieurs sources de donnes, les clients qui utilisent des
navigateurs Web ainsi que les extensions appropries peuvent communiquer
avec ces sources via du code SQL qui traverse les tages HTML et ODBC
de la fuse. Au niveau du pilote, le SQL compatible ODBC est traduit dans
le langage de commandes natif de la base de donnes, puis excut.

JDBC
JDBC (Java DataBase Connectivity, connectivit aux bases de donnes pour
Java) ressemble beaucoup ODBC, mais il en diffre sur certains points
importants. Comme ODBC, JDBC est une interface de bases de donnes qui
se prsente toujours de la mme manire un programme client, et ce quelle
que soit la source avec laquelle il sinterface. Comme le laisse entendre son
nom, une des divergences de fond avec ODBC est que JDBC fonctionne
uniquement avec des applications crites en Java et non en C++ ou en
Visual Basic. Une autre diffrence est que JDBC et Java ont tous deux t
conus ds le dpart pour fonctionner sur le Web ou sur un intranet.
Java est un langage qui ressemble au C++. Il a t conu par Sun
Microsystems dans le but spcifique de dvelopper des programmes client
pour le Web. Une fois la connexion tablie entre un serveur et un client via
le Web, lapplette Java approprie est tlcharge sur le poste client,
partir de quoi elle commence sexcuter. Lapplette, qui est intgre dans
une page HTML, fournit au client les fonctionnalits dont il a besoin pour
accder aux donnes hberges sur le serveur. La Figure 17.3 est une
reprsentation schmatique dune application de base de donnes pour le
Web utilisant une applette Java excute sur la machine client.
Une applette est une petite application qui rside sur un serveur. Lorsquun
client se connecte ce serveur via le Web, lapplette est tlcharge et
commence son excution sur lordinateur client. Les applettes Java sont
spcifiquement conues pour fonctionner dans un bac sable. Un bac
sable est une zone de mmoire parfaitement dlimite sur lordinateur client
et dans laquelle lapplette peut sexcuter. Elle nest pas autorise
dborder de son bac sable personnel, ce qui permet de protger la
machine client dapplettes hostiles qui tenteraient de lui soustraire des
informations sensibles ou de lendommager.
FIGURE 17.3 Application de base de donnes pour le Web utilisant une applette Java.

Un des principaux avantages apports par lutilisation des applettes Java est
quelles sont systmatiquement jour. En effet, elles sont tlcharges
depuis le serveur lors de chaque utilisation (et non conserves sur le poste
du client), si bien que le client dispose toujours de la dernire version
dune applette.
Si vous tes responsable de la maintenance dun serveur, vous navez
jamais besoin de vous soucier des questions de compatibilit avec vos
clients lorsque vous mettez jour le logiciel du serveur. Il vous suffit de
vrifier que lapplette Java tlchargeable est compatible avec la nouvelle
configuration du serveur. Si leurs navigateurs Web sont correctement
configurs pour excuter des applettes Java, tous vos clients resteront
automatiquement et parfaitement compatibles. Java est un langage de
programmation complet qui permet dcrire des applications robustes
servant accder des bases de donnes sur toutes sortes de systmes
client/serveur. Ainsi utilise, une application Java qui accde une base de
donnes via JDBC est semblable une application C++ qui accde une
base de donnes via ODBC. Par contre, les diffrences de fonctionnement
apparaissent ds lors quil est uniquement question dInternet (ou dun
intranet).
Si le systme auquel vous comptez accder se trouve sur Internet, les
conditions de travail ne sont plus du tout les mmes que sur un systme
client/serveur. La partie client dune application qui fonctionne sur Internet
est un navigateur dont les capacits de traitement sont trs rduites. Ces
capacits doivent tre tendues pour pouvoir accder une base de
donnes. Cest ce que permettent les applettes Java.
Il est toujours risqu de tlcharger quoi que ce soit sur un serveur qui nest
pas totalement digne de confiance. Le risque est minime dans le cas dune
applette Java, mais il nest pas compltement limin. Faites trs attention
avant dinstaller du code excutable sur votre machine lorsquil provient
dun serveur potentiellement suspect.
Comme ODBC, JDBC transmet la source de donnes qui se trouve sur le
back end les instructions SQL provenant de lapplication front end
(lapplette). Il transmet galement les rsultats et les messages derreur de
la source de donnes vers lapplication. Tout lintrt dutiliser JDBC est
que le dveloppeur dune applette peut crire son programme en sappuyant
sur linterface standard JDBC, sans avoir tenir compte de la nature de la
base de donnes situe sur le back end. JDBC effectue toutes les
conversions requises pour assurer une communication bidirectionnelle entre
le client et la source de donnes.
Chapitre 18
SQL et donnes XML
DANS CE CHAPITRE :
Utiliser SQL avec XML.

XML, bases de donnes et lInternet.


partir de SQL:2008, le standard SQL de lISO/IEC supporte XML. Les
fichiers XML (eXtensible Markup Language) sont rapidement devenus
un standard universellement accept pour lchange de donnes entre
plates-formes diffrentes. Avec XML, il nest plus important de savoir si la
personne avec laquelle vous changez des donnes a ou non un
environnement diffrent, un systme dexploitation diffrent ou mme un
matriel diffrent. XML est le pont qui vous permet dchanger des
donnes.

Liens entre SQL et XML


Comme HTML, XML est un langage de balises. Autrement dit, ce nest pas
un langage complet, linstar du C++ ou de Java. Il ne sagit mme pas dun
sous-langage, comme SQL. Par contre, linverse des autres, il
comprend le contenu des donnes quil transporte. HTML ne soccupe
que du formatage du texte et des graphismes. XML ne sen soucie pas. Pour
grer la mise en forme dun document, il faut lui associer une feuille de
style (HTML utilisant dailleurs lui aussi cette mthode).
La structure dun document XML est dcrite par son schma XML, exemple
de mtadonnes (donnes qui dcrivent des donnes). Un schma XML
dcrit o les lments se trouvent dans un document et dans quel ordre ils
peuvent apparatre. Il peut aussi dcrire le type de donnes dun lment et
contraindre les valeurs que ce type peut recouvrir.
SQL et XML fournissent deux manires diffrentes permettant de structurer
des donnes afin de les enregistrer et dy retrouver les informations
voulues :
SQL est un excellent outil pour grer des donnes
numriques et textuelles pouvant tre groupes par type et
possdant une longueur dfinie.

SQL a t cr dans le but de standardiser le traitement et


la gestion dinformations prsentes dans une base de
donnes relationnelle.

XML est meilleur pour travailler sur des donnes dont la


forme nest pas prdfinie et qui ne peuvent tre
facilement ranges dans des catgories prcises.

Ce qui a motiv la cration de XML, cest essentiellement le


besoin de possder un standard universel pour le transfert
de donnes entre plates-formes diffrentes et pour
laffichage sur le World Wide Web.

Les forces et les faiblesses de SQL et de XML sont complmentaires.


Chacun rgne en matre sur son propre domaine et forme des alliances avec
lautre afin de donner aux utilisateurs les informations qui les intressent,
quand ils le veulent et l o ils le veulent.

Le type de donne XML


Le type XML a t introduit dans SQL:2003. Cela signifie que les
implmentations conformes au standard peuvent directement enregistrer et
traiter des donnes au format XML, sans quil soit besoin de les convertir
au pralable dans lun des types de SQL.
Le type XML, y compris ses sous-types, fonctionne comme un type de
donne dfini par lutilisateur (tout en tant intrinsque chaque
implmentation). Les sous-types sont :
XML(DOCUMENT(UNTYPED))
XML(DOCUMENT(ANY))

XML(DOCUMENT(XMLSCHEMA))

XML(CONTENT(UNTYPED))

XML(CONTENT(ANY))

XML(CONTENT(XMLSCHEMA))

XML(SEQUENCE)

Le type XML met SQL et XML en contact troit, car il permet aux
applications deffectuer des oprations SQL sur du contenu XML, et
linverse des oprations XML sur du contenu SQL. Vous pouvez inclure une
colonne du type XML au milieu de colonnes possdant lun des types
dcrits dans le Chapitre 2 dans une jointure. Avec une base de donnes
vritablement relationnelle, votre SGBD dterminera la manire optimale
dexcuter la requte.

Quand utiliser le type XML


Dcider si vous devriez ou non enregistrer des donnes au format XML
dpend de lusage que vous comptez en faire. Voici quelques circonstances
dans lesquelles cette technique peut tre intressante :
Lorsque vous voulez enregistrer un bloc entier de
donnes, puis le retrouver plus tard.

Lorsque vous voulez pouvoir interroger lensemble du


document XML. Certaines implmentations ont tendu la
porte de loprateur EXTRACT pour permettre lextraction
du contenu dsir dans un document XML.

Lorsque vous avez besoin dun typage fort de donnes


dans des instructions SQL. En utilisant le type XML, vous
tes certain que vous disposez de valeurs valides, et pas
simplement de chanes de caractres arbitraires.
Lorsque vous voulez assurer la compatibilit avec de
futurs (et donc pas encore dfinis) systmes de stockage
qui pourraient ne pas supporter des types actuels, tels que
CHARACTER LARGE OBJECT, ou CLOB (voyez le Chapitre 2
pour plus dinformations sur cet objet).

Si vous voulez profiter de futures optimisations qui ne


supporteront plus que le type XML.

Voici un exemple montrant comment vous pourriez utiliser le type XML :

CREATE TABLE CLIENTS (


NOM_CLIENT CHARACTER (30) NOT NULL,
ADRESSE_1 CHARACTER (30),
ADRESSE_2 CHARACTER (30),
VILLE CHARACTER (25),
ETAT CHARACTER (2),
CODE_POSTAL CHARACTER (10),
TELEPHONE CHARACTER (13),
FAX CHARACTER (13),
CONTACT CHARACTER (30),
Commentaires XML(SEQUENCE) ) ;

Linstruction SQL qui suit va enregistrer un document XML dans la colonne


Commentaires de la table CLIENT. Le document rsultant pourrait
ressembler ceci :

<Comments>S
<Comment>
<CommentNo>1</CommentNo>
<MessageText>Est-ce que VetLab est
quip pour
analyser
du sang de pingouin ?</MessageText>

<ResponseRequested>Oui</ResponseRequested>
</Comment>
<Comment>
<CommentNo>2</CommentNo>
<MessageText>Merci pour la clrit de
lenvoi
des rsultats
Concernant le prlvement de phoque
gris</Mes-
sageText>

<ResponseRequested>Non</ResponseRequested>
</Comment>
</Comments>

Quand ne pas utiliser le type XML


Ce nest pas parce que SQL:2003 vous permet dutiliser le type XML que
vous devez toujours le faire. En fait, cela na mme aucun sens dans de
nombreuses circonstances. La plupart des donnes des bases relationnelles
actuelles ont un format qui leur convient parfaitement. Voici quelques
exemples de cas dans lesquels le type XML na aucune utilit :
Lorsque les donnes se dcomposent naturellement en
une structure relationnelle, avec des tables, des lignes et
des colonnes.

Lorsque vous avez besoin de mettre jour des parties dun


document et non pas de traiter globalement ce document.

Associer SQL et XML, XML et SQL


Pour changer des donnes entre des bases SQL et des documents XML, il
faut que les divers lments de la base puissent tre transcrits en lments
quivalents du document XML. Et rciproquement. Dans les sections qui
suivent, jexplique quels lments ont besoin dtre convertis.

Jeux de caractres
En SQL, le support des jeux de caractres dpend de votre implmentation.
Cela signifie que DB2 (IBM) peut supporter des jeux de caractres que
Microsoft SQL Server naccepte pas. De mme, SQL Server peut supporter
des jeux de caractres qui ne le sont pas par Oracle. Certes, les jeux de
caractres les plus courants sont universellement reconnus. Mais, dans le
cas de besoins spcifiques, migrer une base de donnes et ses applications
dun SGBD un autre peut tre difficile.
XML ne connat pas ces problmes de compatibilit. Il ne se sert en effet
que dun seul jeu de caractres : Unicode. Du point de vue de lchange de
donnes entre XML et une implmentation SQL quelconque, cest une bonne
nouvelle. Tous les vendeurs de SGBD doivent dfinir une correspondance
bidirectionnelle entre les chanes de chacun de leurs jeux de caractres et
Unicode. Le travail sarrte l, prcisment puisque XML naccepte aucun
autre jeu de caractres. Sinon, le problme deviendrait beaucoup plus
complexe.

Identificateurs
XML est plus strict que SQL quant aux caractres autoriss dans les
identificateurs. Les signes lgaux dans SQL, mais illgaux pour XML,
doivent tre transforms en quelque chose dacceptable avant de pouvoir
tre utiliss dans un document XML. SQL supporte des identificateurs
dlimits. Cela signifie que toutes sortes de caractres bizarrodes,
comme %, $ et &, sont lgaux ds lors quils sont placs entre des
guillemets. Du point de vue de XML, de tels signes sont illgaux. De plus,
les noms XML qui commencent par XML (quelle que soit la combinaison de
majuscules et de minuscules) sont des mots rservs, et donc ne peuvent pas
tre employs en toute impunit.
Si, par le plus grand des hasards, vous avez utilis ces lettres au dbut
didentificateurs SQL, vous devrez changer leurs noms.
Certaines rgles permettent de crer un pont entre SQL et XML. En passant
XML, tous les identificateurs SQL sont convertis en Unicode. partir de
l, ceux qui sont aussi lgaux pour XML demeurent inchangs. Les autres
sont remplacs par un code hexadcimal prenant pour forme _xNNNN_
ou xNNNNNNNN_ , o N reprsente un chiffre hexadcimal en
majuscule. Par exemple, le trait de soulignement (_) sera reprsent par
_x005F_ . De mme, _x003A_ correspond la virgule. Les
valeurs hexadcimales prcdentes sont prcisment les codes du trait de
soulignement et de la virgule en Unicode. Le cas didentificateurs SQL
dbutant par les caractres x, m et l est rgl en prfixant ce genre
dinstance par un code de la forme xFFFF .
Les conversions sont plus simples dans lautre sens (de XML vers SQL).
Tout ce quil y a faire est de scanner les caractres dun nom XML pour y
chercher la prsence dune squence xNNNN_ ou _xNNNNNNNN .
Il suffit alors de la remplacer par le caractre Unicode correspondant. Si un
nom XML dbute par la squence xFFFF_ , elle doit simplement tre
ignore.
En suivant ces quelques rgles, vous pouvez convertir un identificateur SQL
en un nom XML, puis revenir un identificateur SQL. Par contre, la
situation est moins confortable quand il sagit de convertir un nom XML en
identificateur SQL et retour.

Types de donnes
Le standard SQL spcifie quun type de donne SQL doit tre converti dans
le type XML Schema le plus proche possible. Lexpression le plus proche
possible signifie que toutes les valeurs autorises par le type SQL le
seront aussi par le type XML Schema, et quun minimum de valeurs non
permises par le type SQL sera autoris par le type XML Schema. Dans
certains cas, il est possible de rduire ltendue des valeurs XML la plage
autorise par le type SQL correspondant. Prenons par exemple une valeur
SQL de type INTEGER. Elle appartient lintervalle ferm -2157483648,
2157483647. Sous XML, la valeur maxInclusive peut tre dfinie
comme tant gale 2157483647, et la valeur minInclusive comme
tant gale - 2157483648. Voici un exemple mettant en uvre une telle
correspondance :
<xsd:simpleType>
<xsd:restriction base=xsd:integer>
<xsd:maxInclusive valeur=2157483647 />
<xsd:minInclusive valeur=-2157483648 />
<xsd:annotation>
<sqlxml:sqltype name=INTEGER />
</xsd:annotation>
</xsd:restriction>
</xsd:simpleType>

La section annotation contient des informations sur la dfinition du


type SQL. Elle nest pas utilise par XML, mais elle peut tre intressante
si le document est reconverti plus tard vers SQL.

Tables
Vous pouvez associer une table un document XML. Cela vaut galement
pour toutes les tables dun schma ou dun catalogue. Cette opration
conserve les privilges. Une personne possdant un privilge SELECT
restreint certaines colonnes dune table ne pourra associer que ces
colonnes au document XML. La procdure produit en ralit deux
documents : lun contient les donnes de la table, lautre le schma XML
qui dcrit le premier document. Voici par exemple ce que peut donner ce
genre dopration :

<CLIENTS>
<row>
<PRENOM>Abe</PRENOM>
<NOM>Abelson</NOM>
<VILLE>Springfield</VILLE>
<CODE>714</CODE>
<TELEPHONE>555-1111</TELEPHONE >
</row>
<row>
<PRENOM>Bill</PRENOM>
<NOM>Bailey</NOM>
<VILLE>Decatur</VILLE>
<CODE>714</CODE>
<TELEPHONE>555-2222</TELEPHONE >
</row>
.
.
.
</CLIENTS>

Llment racine du document a pris le nom de la table. Chaque ligne de


celle-ci est contenue dans un lment <row>. Cet lment dcrit une suite
de colonnes provenant de la table et portant le mme nom que dans celle-ci.
Enfin, chaque lment de colonne contient une valeur de donne.

Grer les valeurs nulles


Les donnes SQL peuvent tre nulles (vides, non dfinies ou encore
indtermines). Vous devez dcider de la faon de les reprsenter dans un
document XML. Vous disposez pour cela de deux options : nil ou absent. Si
vous choisissez la mthode nil, lattribut xsi : nil= true
marque les lments de colonnes dont la valeur dans la table est nulle. Il
peut tre utilis de la manire suivante :

<row>
<PRENOM>Abe</PRENOM>
<NOM>Abelson</NOM>
<VILLE xsi:nil=true />
<CODE>714</CODE>
<TELEPHONE>555-1111</TELEPHONE >
</row>

Loption absent pourrait tre implmente ainsi :

<row>
<PRENOM>Abe</PRENOM>
<NOM>Abelson</NOM>
<CODE>714</CODE>
<TELEPHONE>555-1111</TELEPHONE >
</row>

Dans ce cas, la ligne contenant la valeur nulle est tout simplement omise.

Gnrer le schma XML


Dans une association entre SQL et XML, le premier document gnr est
celui qui contient les donnes. Le second concerne les informations de
schma. titre dexemple, considrons le schma pour le document
CLIENTS utilis plus haut dans la section Tables :

<xsd:schema>
<xsd:simpleType name=CHAR_15>
<xsd:restriction base=xsd:string>
<xsd:length value = 15 />
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name=CHAR_25>
<xsd:restriction base=xsd:string>
<xsd:length value = 25 />
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name=CHAR_3>
<xsd:restriction base=xsd:string>
<xsd:length value = 3 />
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name=CHAR_8>
<xsd:restriction base=xsd:string>
<xsd:length value = 8 />
</xsd:restriction>
</xsd:simpleType>
<xsd:sequence>
<xsd:element name=PRENOM
type=CHAR_15 />
<xsd:element name=NOM type=CHAR_25
/>
<xsd:element name=VILLE
type=CHAR_25 nil-
lable=true />
<xsd:element name=CODE type=CHAR_3
nil-
lable=true />
<xsd:element name=TELEPHONE
type=CHAR_8
nillable=true />

</xsd:sequence>
</xsd:schema>

Ce schma est appropri si lapproche nil est utilise pour grer les valeurs
SQL nulles. Lapproche absent impose une dfinition des lments
lgrement diffrente. Par exemple :

<xsd:element name=VILLE type=CHAR_25


minOccurs=0 />

Fonctions SQL oprant sur des


donnes XML
Le standard SQL dfinit une srie doprateurs, fonctions et
pseudo- fonctions qui produisent un rsultat XML quand on les applique
une base de donnes SQL, ou qui linverse produisent un rsultat au
format SQL standard lorsquon les applique des donnes XML. Dans les
sections qui suivent, je donne une brve description des fonctions les plus
courantes que sont XMLELEMENT, XMLFOREST, XMLCONCAT et
XMLAGG, ainsi que de plusieurs autres qui sont frquemment employes
pour publier sur le Web. Certaines dentre elles reposent fortement sur
XQuery, un nouveau langage de requte standard spcifiquement conu pour
interroger des donnes XML. XQuery est en lui-mme un vaste sujet, qui
dpasse videmment le cadre de ce livre.

XMLDOCUMENT
Loprateur XMLDOCUMENT prend une valeur XML en entre et retourne
une autre valeur XML en sortie. La nouvelle valeur XML est un nud
document construit selon les rgles du constructeur dun document dans
XQuery.

XMLELEMENT
Loprateur XMLELEMENT traduit une valeur relationnelle en un lment
XML. Vous pouvez lutiliser dans une instruction SELECT pour mettre des
donnes provenant de la base SQL au format XML en vue de les publier sur
le Web. Par exemple :

SELECT c.NOM
XMLELEMENT (NAME VILLE, c.VILLE) AS Resultat
FROM CLIENTS c
WHERE NOM=Abelson ;

Voici le rsultat renvoy :

Nom Rsultat
Abelson <VILLE>Springfield</VILLE>

XMLFOREST
Loprateur XMLFOREST produit une liste, ou fort, dlments XML
partir de valeurs relationnelles. Chacune des valeurs de loprateur gnre
un nouvel lment. En voici un exemple :

SELECT c.NOM
XMLFOREST (c.VILLE,
c.CODE,
c.TELEPHONE) AS Resultat
FROM CLIENTS c
WHERE NOM = Abelson OR NOM = Bailey ;

Ce fragment de code donnera la sortie suivante :

Nom Rsultat
Abelson <VILLE>Springfield</VILLE> <CODE>714</CODE>
<TELEPHONE>555-1111</TELEPHONE>
Bailey <VILLE>Decatur</VILLE>
<CODE>714</CODE>
<TELEPHONE>555-2222</TELEPHONE>

XMLCONCAT
XMLCONCAT reprsente une autre manire de produire une fort
dlments en concatnant ses arguments XML. Par exemple, le code ci-
dessous :

SELECT c.NOM
XMLCONCAT (
XMLELEMENT ( NOM prenom, c.PRENOM)
XMLELEMENT ( NOM nom, c.NOM)
) AS Resultat
FROM CLIENTS c ;

produit ces rsultats :


Nom Rsultat
Abelson <prenom>Abe</prenom>
<nom>Abelson</nom>
Bailey <prenom>Bill</prenom>
<nom>Bailey</nom>

XMLAGG
La fonction dagrgation XMLAGG prend des documents XML (ou des
fragments de documents) et produit un nouveau document unique comme
sortie dune requte GROUP BY. Lagrgation contient une fort dlments.
Voyons un exemple qui illustre ce concept :

SELECT XMLELEMENT
( NAME Ville
XMLATTRIBUTES ( c.VILLE AS name )
XMLAGG ( XMLELEMENT (NAME nom c.NOM
))
) AS ListeVilles
FROM CLIENTS c
GROUP BY VILLE ;

Lorsquelle est excute sur notre table CLIENTS, cette requte fournit le
rsultat suivant :

ListeVilles
<Ville name=Decatur>
<nom>Bailey</nom>
</Ville>
<Ville name=Philo>
<nom>Stetson</nom>
<nom>Stetson</nom>
<nom>Wood</nom>
</Ville>
<Ville name=Springfield>
<nom>Abelson</nom>
</Ville>

XMLCOMMENT
La fonction XMLCOMMENT permet une application de crer un
commentaire XML. Sa syntaxe est la suivante :

SXMLCOMMENT ( contenu du commentaire


[RETURNING
{CONTENT | SEQUENCE} ] )

Par exemple :

XMLCOMMENT (Sauvegarder la base tous les jours


2h du
matin.)

cre un commentaire XML semblable celui-ci :

<!--Sauvegarder la base tous les jours 2h du


matin. -->

XMLPARSE
La fonction XMLPARSE produit une valeur XML en effectuant une analyse
sans validation dune chane. Vous pourriez lutiliser de cette manire :

XMLPARSE (DOCUMENT Beau travail !


PRESERVE WHITESPACE )

Le code ci-dessus renverrait une valeur XML du type XML (UNTYPED


DOCUMENT) ou XML (DOCUMENT). Le sous-type choisi dpend de
limplmentation que vous utilisez.
XMLPI
La fonction XMLPI permet aux applications de crer des instructions de
traitement XML. Sa syntaxe se prsente ainsi :

XMLPI NAME cible


[, expression-chane ]
[ RETURNING
{ CONTENT | SEQUENCE } ] )

Le container cible dsigne lidentificateur de la cible vise par


linstruction de traitement. expression-chane reprsente le contenu
de cette instruction. Cette fonction cre un commentaire XML de la forme :

<? cible expression-chane ?>

XMLQUERY
La fonction XMLQUERY value une expression XQuery et renvoie le
rsultat de la requte lapplication SQL. La syntaxe de XMLQUERY est la
suivante :

XMLQUERY ( expression-XQuery
[ PASSING { BY REF | BY VALUE }
liste-arguments ]
[ RETURNING { CONTENT | SEQUENCE }
{ BY REF | BY VALUE } )

Voici un exemple dutilisation de XMLQUERY :

SELECT moyenne_max,
XMLQUERY (
for $moyenne_batteur in
/joueur/moyenne_batteur
where /joueur/nom = $var1
return $moyenne_batteur
PASSING BY VALUE
Mantle AS var1
RETURNING SEQUENCE BY VALUE )
FROM stats_attaque ;

XMLCAST
La fonction XMLCAST est semblable au CAST de SQL, mais avec
quelques restrictions supplmentaires. Elle permet une application de
pratiquer le transtypage dune valeur dun type XML vers un autre type
XML ou vers un type SQL. Elle peut aussi servir dans lautre sens, pour
transformer un type SQL en un type XML. Mais il y a quelques contraintes
respecter :
Au moins un des types invoqus (la source ou la
destination) doit tre un type XML.

Les types SQL invoqus ne peuvent tre ni une collection,


ni une ligne, ni un type structur, ni une rfrence.

Seules les valeurs possdant lun des types XML ou le type


SQL nul peuvent tre transformes en XML (UNTYPED
DOCUMENT) ou XML (DOCUMENT).

Voici un exemple :

XMLCAST ( CLIENTS.NomClient AS XML (UNTYPED


DOCUMENT)

La fonction XMLCAST est transforme en un CAST SQL ordinaire. La


seule raison qui justifie lemploi dun mot cl diffrent est la ncessit de
respecter les contraintes ci-dessus.

Prdicats
Un prdicat renvoie une valeur vraie (True) ou fausse (False). De nouveaux
prdicats ont t ajouts pour les besoins de linterconnexion entre SQL et
XML.

DOCUMENT
Lobjet du prdicat DOCUMENT est de dterminer si une valeur XML est un
document. Il teste cette valeur pour vrifier si elle est une instance du type
XML (UNTYPED DOCUMENT) ou XML (ALL DOCUMENT). Sa
syntaxe est la suivante :

XML-valeur IS [NOT]
[ANY | UNTYPED] DOCUMENT

Si lexpression est value comme tant vraie, le prdicat retourne True.


Sinon, il renvoie False. Si la valeur XML est nulle, le prdicat retourne
UNKNOWN. Si ANY ou UNTYPED ne sont pas spcifis, le prdicat
suppose par dfaut quil sagit dANY.

CONTENT
Le prdicat CONTENT sert dterminer si une valeur XML est une
instance de XML (ANY CONTENT) ou XML (UNTYPED CONTENT).
En voici la syntaxe :

XML-valeur IS [NOT]
[ANY | UNTYPED] CONTENT

Si ANY ou UNTYPED ne sont pas spcifis, le prdicat suppose par dfaut


quil sagit dANY.

XMLEXISTS
Comme son nom lindique, le prdicat XMLEXISTS a pour but de
dterminer si une valeur existe. Sa syntaxe se prsente ainsi :
XMLEXISTS (expression-XQuery
[ liste-arguments ] )

Lexpression XQuery utilise les valeurs fournies dans la liste des


arguments. Si cette expression renvoie une valeur SQL nulle, le rsultat
fourni par le prdicat est UNKNOWN. Si lvaluation retourne une squence
XQuery vide, le prdicat vaut FALSE. Sinon, il est vrai (TRUE). Ce
prdicat peut servir dterminer si un document XML contient un contenu
spcifique avant dutiliser une partie de ce contenu dans une expression.

VALID
Le prdicat VALID a pour but dvaluer une valeur XML afin de voir si
elle est valide dans le contexte dun schma XML enregistr. Sa syntaxe est
plus complexe que celle des autres prdicats :

XML-valeur IS [NOT] VALID


[XML option de contrainte didentit valide]
[XML clause de correspondance valide]

Le prdicat contrle si la valeur possde bien lun des cinq types XML :
XML (SEQUENCE), XML (ANY CONTENT), XML (UNTYPED
CONTENT), XML (ANY DOCUMENT), XML (UNTYPED DOCUMENT).
De plus, il peut vrifier de manire facultative si la validit de la valeur
XML sappuie sur des contraintes didentit, et si cette validit est
conforme un schma XML particulier.
Le composant option de contrainte didentit offre quatre possibilits :

WITHOUT IDENTITY CONSTRAINTS : Cest la supposition


qui est faite par dfaut si aucune autre option de contrainte
didentit nest utilise. Si DOCUMENT est spcifi, elle
fonctionne comme une combinaison des prdicats
DOCUMENT et VALID WITH IDENTITY CONSTRAINTS
GLOBAL.
WITH IDENTITY CONSTRAINTS GLOBAL : Ce composant
demande vrifier la conformit de la valeur avec le
schma XML ainsi quavec les rgles XML pour les relations
ID/ IDREF.

ID et IDREF sont des types dattributs XML qui identifient les


lments dun document.

WITH IDENTITY CONSTRAINTS LOCAL : Ce composant


demande vrifier la conformit de la valeur avec le
schma XML, mais pas avec les rgles XML pour les
relations ID/ IDREF ou les rgles du schma XML pour les
contraintes didentit.

DOCUMENT : Ce composant signifie que la valeur est un


document et quelle respecte le mode WITH IDENTITY
CONSTRAINTS GLOBAL avec une clause de
correspondance valide. Celle-ci identifie le schma pour
lequel la valeur doit tre valide.

Transformer des donnes XML en


tables SQL
Jusqu une priode rcente, la rflexion sur les relations entre SQL et XML
tournaient essentiellement autour de la question suivante : Comment
convertir des donnes dune table SQL au format XML pour les rendre
accessibles sur lInternet ? Les plus rcents ajouts au standard SQL
traitent aussi du problme inverse : Comment convertir des donnes XML
en tables SQL pour pouvoir les interroger facilement laide dinstructions
SQL standard ?
La pseudo-fonction XMLTABLE est charge deffectuer cette opration. Sa
syntaxe est la suivante :
XMLTABLE ( [dclaration-espace-noms, ]
expression-XQuery
[ PASSING liste-arguments ]
COLUMNS dfinitions-colonnes-tableXML

o la liste darguments se prsente ainsi :

expression-valeur AS identificateur

Tandis que dfinitions-colonnes-tableXML est une liste de


dfinitions de colonnes spares par une virgule et qui peut contenir :

nom-colonne FOR ORDINALITY

et/ou :

nom-colonne type-donne
[BY REF | BY VALUE]
[clause-par-dfaut]
[PATH expression-XQuery]

Voici un exemple vous montrant comment il est possible dutiliser


XMLTABLE pour extraire des donnes dun document XML et les envoyer
vers une pseudo-table SQL. Une telle table a une dure de vie phmre,
mais elle se comporte pour le reste comme une table SQL tout fait
normale. Si vous voulez que les donnes soient permanentes, vous pouvez
faire appel une instruction CREATE TABLE puis insrer les donnes
XML dans la table nouvellement cre :

SELECT telephoneclient.*
FROM
clients_xml ,
XMLTABLE (
for $m in
ol/client
return
$m
PASSING clients_xml.client AS col
COLUMNS
Nom_Client CHARACTER (30) PATH
Nom_Client ,
Telephone CHARACTER (13) PATH
Telephone
) AS telephoneclient ;

Lexcution de cette instruction fournira un rsultat de ce style :

Nom_Client Telephone
Abe Abelson (714) 555-1111
Bill Bailey (714) 555-2222
Chuck Wood (714) 555-3333

Types de donnes non prdfinis et


XML
Dans le standard SQL, les types de donnes non prdfinis comprennent les
domaines, les types utilisateurs distincts, les tableaux et les multisets
(ensembles multiples). Vous pouvez tous les transformer en donnes
formates pour XML en utilisant le code appropri. Les quelques sections
qui suivent vous proposent des exemples simples.

Domaine
Pour convertir un domaine SQL vers XML, vous devez tout dabord
disposer dun domaine. Pour cet exemple, nous allons en crer un grce
linstruction CREATE DOMAIN :

CREATE DOMAIN CoteOuest AS CHAR (2)


CHECK (Etat IN (CA, OR, WA, AK) ) ;

Dfinissons maintenant une table qui utilise ce domaine :


CREATE TABLE RegionOuest (
NomClient Character (20) NOT NULL,
Etat CoteOuest NOT NULL
) ;

Voici le schma XML permettant de transcrire notre domaine en XML :

<xsd:simpleType>
Name = DOMAIN.Ventes.RegionOuest>

<xsd:annotation>
<xsd:appinfo>
<sqlxml:sqltype kind = DOMAIN
schemaName = Ventes
typeName = CoteOuest
mappedType = CHAR_2
final = true />
</xsd:appinfo>
</xsd:annotation>

<xsd:restriction base = CHAR_2 />

</xsd:simpleType>

Lorsque ce mappage est appliqu, il en rsulte un document XML qui


contient quelque chose comme :

<RegionOuest>
<row>
.
.
.
<Etat>AK</Etat>
.
.
.
</row>
.
.
.
</RegionOuest>

Type dfini par lutilisateur distinct


Le travail est peu prs le mme que pour un domaine, ainsi que le montre
lexemple suivant :

CREATE TYPE CoteOuest AS CHARACTER (2) FINAL ;

Voici le schma XML permettant de transcrire notre type en XML :

<xsd:simpleType>
Name = UDT.Ventes.RegionOuest>

<xsd:annotation>
<xsd:appinfo>
<sqlxml:sqltype kind = DISTINCT
schemaName = Ventes
typeName = CoteOuest
mappedType = CHAR_2
final = true />
</xsd:appinfo>
</xsd:annotation>

<xsd:restriction base = CHAR_2 />

</xsd:simpleType>

Il cre un lment identique celui obtenu avec le domaine prcdent.


Ligne
Le type ROW vous permet de rcuprer dun coup lensemble des
informations dune ligne dans un seul champ. Vous pouvez crer un type
ROW dans une dfinition de table en procdant comme suit :

CREATE TABLE InfoContact (


Nom Character (30) ,
Telephone ROW (Maison CHAR (13), Travail CHAR
(13))
) ;

Il est maintenant possible deffectuer un mappage de ce type vers XML avec


le schma suivant :

<xsd:complexType Name=ROW.1>

<xsd:annotation>
<xsd:appinfo>
<sqlxml:sqltype kind = ROW
<sqlxml:field name = Maison
mappedType =
CHAR_13 />
<sqlxml:field name =
Travail
mappedType =
CHAR_13 />
</sqlxml:sqltype>
</xsd:appinfo>
</xsd:annotation>

<xsd:sequence>
<xsd:element Name= Maison nillable=
true
Type= CHAR_13 />
<xsd:element Name= Travail nillable=
true
Type= CHAR_13 />
</xsd:sequence>

</xsd:complexType>

Ce schma pourrait gnrer la squence XML suivante pour une colonne :

<Telephone>
<Maison>(888) 555-1111</Maison>
<Travail>(888) 555-1111</Travail>
</Telephone>

Tableau
Il est possible de placer plusieurs lments dans un seul champ en utilisant
le type ARRAY la place de ROW. Reprenons lexemple de la table
InfoContact en dclarant la colonne TELEPHONE comme tant un
tableau :

CREATE TABLE InfoContact (


Nom Character (30) ,
Telephone Character (13) ARRAY [4]
) ;

Il est maintenant possible deffectuer un mappage de ce type vers XML avec


le schma suivant :

<xsd:complexType Name=ARRAY_4.CHAR_13>
<xsd:annotation>
<xsd:appinfo>
<sqlxml:sqltype kind =
ARRAY
maxElements= 4
mappedElementType=
CHAR_13
/>
</xsd:appinfo>
</xsd:annotation>

<xsd:sequence>
<xsd:element Name= element
minOccurs= 0 maxOccurs= 4
nillable= true Type= CHAR_13 />
</xsd:sequence>
</xsd:complexType>

Ce schma gnrerait quelque chose comme :

<Telephone>
<element>(888) 555-1111</element>
<element>xsi:nil= true />
<element>(888) 555-3434</element>
</Telephone>

Llment du tableau qui contient xsi : nil= true reflte le fait


que le second numro de tlphone contient une valeur nulle dans la table
source.

Multiset
Les numros de tlphone de lexemple prcdent pourraient tre
enregistrs dans un multiset (un ensemble multiple) la place dun tableau.
La dfinition de notre table se prsenterait alors ainsi :

CREATE TABLE InfoContact (


Nom Character (30) ,
Telephone Character (13) MULTISET
) ;

Il est maintenant possible deffectuer un mappage de ce type vers XML avec


le schma suivant :

<xsd:complexType Name=MULTISET.CHAR_13>

<xsd:annotation>
<xsd:appinfo>
<sqlxml:sqltype kind =
MULTISET
mappedElementType=
CHAR_13
/>
</xsd:appinfo>
</xsd:annotation>

<xsd:sequence>
<xsd:element Name= element
minOccurs= 0 maxOccurs= unbounded
nillable= true Type= CHAR_13 />
</xsd:sequence>

</xsd:complexType>

Ce schma gnrerait quelque chose comme ceci :

<Telephone>
<element>(888) 555-1111</element>
<element>xsi:nil= true />
<element>(888) 555-3434</element>
</Telephone>

Le mariage de SQL et de XML


SQL fournit une mthode standard universelle pour le stockage de donnes
dune manire hautement structure. La structure permet lutilisateur de
grer des donnes de type et de taille trs diffrents, ainsi que dextraire de
ces banques de donnes les informations dont il a besoin. XML est devenu
un standard officiel pour le transport de donnes entre plates-formes
incompatibles, en particulier sur lInternet. En associant ces deux mthodes,
leur valeur individuelle sen trouve dmultiplie.
Sommaire

Couverture
SQL Poche Pour les Nuls, 3e
Copyright
Introduction
Au sujet de ce livre
Qui devrait lire ce livre ?
Icnes utilises dans ce livre
Pour commencer

I. Dbuter en SQL
Chapitre 1 - Les bases de donnes relationnelles
Conserver la trace des choses

Quest-ce quune base de donnes ?

Volume et complexit dune base de donnes

Quest-ce quun systme de gestion de bases de donnes ?

Les fichiers plein texte

Les modles de base de donnes

Chapitre 2 - Les bases de SQL


Ce que SQL nest pas

Un (tout) petit peu dhistoire

Les commandes SQL

Les mots rservs

Les types de donnes


Les valeurs nulles

Les contraintes

Utiliser SQL sur un systme client/serveur

Utiliser SQL sur lInternet ou un intranet

Chapitre 3 - Les composants de SQL


Le langage de dfinition de donnes (DDL)

Le langage de contrle de donnes (DCL)

II. Utiliser SQL pour crer des bases de donnes


Chapitre 4 - Crer et maintenir une simple structure de base de donnes
Crer une simple base de donnes en utilisant un outil RAD

Crer une table avec le DDL de SQL

De la portabilit

Chapitre 5 - Crer une base de donnes relationnelle multitable


Concevoir la base de donnes

Travailler avec des index

Maintenir lintgrit

Normaliser la base de donnes

III. Enregistrer et extraire des donnes


Chapitre 6 - Manipuler les donnes dune base
Extraire des donnes

Crer des vues

Modifier les vues

Ajouter de nouvelles donnes

Modifier des donnes existantes

Transfrer des donnes

Supprimer des donnes obsoltes

Chapitre 7 - Grer lhistorique des donnes


Comprendre les priodes dans SQL:2011
Travailler avec des tables de priodes de temps-application

Travailler avec des tables de versions systmes

Tracer encore plus les donnes avec des tables bitemporelles

Chapitre 8 - Spcifier des valeurs


Valeurs

Les expressions de valeur

Les fonctions

Chapitre 9 - Expressions SQL avances


Les expressions conditionnelles CASE

Conversions de types de donnes (CAST)

Les expressions valeur de ligne

Chapitre 10 - Isoler les donnes dont vous avez besoin


Clauses modificatrices

Clauses FROM

Les clauses WHERE

Connecteurs logiques

Les limites de Fetch

Regarder par une fentre pour crer un jeu de rsultats

Chapitre 11 - Les oprateurs relationnels


UNION

INTERSECT

EXCEPT

Les oprateurs JOIN

ON et WHERE

Chapitre 12 - Effectuer des recherches approfondies avec des requtes


imbriques
Que fait une sous-requte ?

Chapitre 13 - Requtes rcursives


Quest-ce que la rcursivit ?

Quest-ce quune requte rcursive ?

Quand utiliser une requte rcursive ?

quoi dautre peut me servir une requte rcursive ?

IV. Contrler les oprations


Chapitre 14 - Protger une base de donnes
Le langage de contrle de donnes de SQL (DCL)

Les niveaux daccs de lutilisateur

Accorder des privilges aux utilisateurs

Accorder des privilges entre niveaux

Donner le pouvoir daccorder des privilges

Retirer des privilges

Utiliser simultanment GRANT et REVOKE pour gagner du temps et des efforts

Chapitre 15 - Protection des donnes


Menaces sur lintgrit des donnes

Rduire le risque de corruption des donnes

Contraintes et transactions

Chapitre 16 - Utiliser SQL dans des applications


SQL dans une application

Utiliser SQL dans des langages procduraux

V. Utiliser SQL dans le monde rel


Chapitre 17 - ODBC et JDBC
ODBC

ODBC sur un intranet

JDBC

Chapitre 18 - SQL et donnes XML


Liens entre SQL et XML

Le type de donne XML


Associer SQL et XML, XML et SQL

Fonctions SQL oprant sur des donnes XML

Prdicats

Transformer des donnes XML en tables SQL

Types de donnes non prdfinis et XML

Le mariage de SQL et de XML