Administration de Base de Donnees
Administration de Base de Donnees
UNIVERSITE DUBURUNDI
Technologies de l’Information et
de la Communication
CHAPITRE I. Introduction
Les bases de données ont pris aujourd’hui une place essentielle dans l’informatique, plus
particulièrement en gestion. Au cours des cinquante dernières années, des concepts,
méthodes et algorithmes ont été développés pour gérer des données sur mémoires
secondaires ; ils constituent aujourd’hui l’essentiel de la discipline « Bases de Données
» (BD). Cette discipline est utilisée dans de nombreuses applications. Il existe un grand
nombre de Systèmes de Gestion de Bases de Données (SGBD) qui permettent de gérer
efficacement de grandes bases de données. De plus, une théorie fondamentale sur les
techniques de modélisation des données et les algorithmes de traitement a vu le jour. Les
bases de données constituent donc une discipline s’appuyant sur une théorie solide et
offrant de nombreux débouchés pratiques.
Le mot base de données est souvent utilisé pour désigner n’importe quel ensemble de
données ; il s’agit là d’un abus de langage qu’il faut éviter. Une base de données est un
ensemble de données modélisant les objets d’une partie du monde réel et servant de
support à une application informatique. Pour mériter le terme de base de données, un
ensemble de données non indépendantes doit être interrogeable par le contenu, c’est-à-
dire que l’on doit pouvoir retrouver tous les objets qui satisfont à un certain critère, par
exemple tous les produits qui coûtent moins de 1000 francs. Les données doivent être
interrogeables selon n’importe quel critère. Il doit être possible aussi de retrouver leur
structure, par exemple le fait qu’un produit possède un nom, un prix et une quantité.
Plutôt que de disserter longuement sur le concept de bases de données, précisons ce
qu’est un SGBD. Un SGBD peut être perçu comme un ensemble de logiciels systèmes
permettant aux utilisateurs d’insérer, de modifier et de rechercher efficacement des
données spécifiques dans une grande masse d’informations (pouvant atteindre quelques
milliards d’octets) partagée par de multiples utilisateurs. Les informations sont stockées
sur mémoires secondaires, en général des disques magnétiques. Les recherches peuvent
être exécutées à partir de la valeur d’une donnée désignée par un nom dans un ensemble
d’objets (par exemple, les produits de prix inférieur à 1000 francs), mais aussi à partir
de relations entre objets (par exemple, les produits commandés par un client habitant
Bujumbura). Les données sont partagées, aussi bien en interrogation qu’en mise à jour.
Le SGBD rend transparent le partage, à savoir donne l’illusion à chaque utilisateur qu’il
est seul à travailler avec les données.
2
L’accès à des données stockées sur un périphérique, par contraste avec les applications
qui manipulent des données en mémoire centrale, est une des caractéristiques
essentielles d’un SGBD. Elle implique notamment des problèmes potentiels de
performance puisque le temps de lecture d’une information sur un disque est
considérablement plus élevé qu’un accès en mémoire principale. L’organisation des
données sur un disque, les structures d’indexation mises en œuvre et les algorithmes de
recherche utilisés constituent donc des aspects très importants des SGBD. Un bon
système se doit d’utiliser au mieux les techniques disponibles afin de minimiser les
temps d’accès. Il doit aussi offrir à l’administrateur des outils de paramétrage et de
contrôle qui vont lui permettre d’exploiter au mieux les ressources matérielles et
logicielles d’un environnement donné.
3
II.1.1. Supports
D’une manière générale, plus une mémoire est rapide, plus elle est chère et –
conséquence directe – plus sa capacité est réduite. Les différentes mémoires utilisées par
un ordinateur constituent donc une hiérarchie (figure 1), allant de la mémoire la plus
petite mais la plus efficace à la mémoire la plus volumineuse mais la plus lente.
1. la mémoire cache est utilisée par le processeur pour stocker ses données et ses
instructions ;
2. la mémoire vive, ou mémoire principale stocke les données et les processus
constituant l’espace de travail de la machine ; toute donnée ou tout programme doit
d’abord être chargé en mémoire principale avant de pouvoir être traité par un
processeur ;
3. les disques magnétiques constituent le principal périphérique de type mémoire ; ils
offrent une grande capacité de stockage tout en gardant des accès en lecture et en
écriture relativement efficaces ;
4. enfin les bandes magnétiques sont des supports très économiques mais leur lenteur
les destine plutôt aux sauvegardes.
II.1.3. Dispositif
La petite information stockée sur un disque est un bit qui peut valoir 0 ou 1. Les bits sont
groupés par 8 pour former des octets, et une suite d’octets forme un cercle ou piste sur
la surface du disque.
Un disque est entraîné dans un mouvement de rotation régulier par un axe. Une tête de
lecture (deux si le disque est double-face) vient se positionner sur une des pistes du
disque et y lit ou écrit les données. Le nombre minimal d’octets lus par une tête de lecture
est physiquement défini par la taille d’un secteur (en général 512K). Cela étant le
système d’exploitation peut choisir, au moment de l’initialisation du disque, de fixer
une unité d’entrée/sortie supérieure à la taille d’un secteur, et multiple de cette dernière.
On obtient des blocs, dont la taille est typiquement 512K (un secteur), 1024K (deux
secteurs) ou 4096K (huit secteurs).
5
Chaque piste est donc divisée en blocs (ou pages) qui constituent l’unité d’échange entre
le disque et la mémoire principale.
Toute lecture ou toute écriture sur les disques s’effectue par blocs. Même si la lecture ne
concerne qu’une donnée occupant 4 octets, tout le bloc contenant ces 4 octets sera
transmis en mémoire centrale.
La tête de lecture n’est pas entraînée dans le mouvement de rotation. Elle se déplace
dans un plan fixe qui lui permet de se rapprocher ou de s’éloigner de l’axe de rotation
des disques, et d’accéder à une des pistes. Pour limiter le coût de l’ensemble de ce
dispositif et augmenter la capacité de stockage, les disques sont empilés et partagent le
même axe de rotation (voir figure 2). Il y a autant de têtes de lectures que de disques
(deux fois plus si les disques sont à double face) et toutes les têtes sont positionnées
solidairement dans leur plan de déplacement. À tout moment, les pistes accessibles par
les têtes sont donc les mêmes pour tous les disques de la pile, ce qui constitue une
contrainte dont il faut savoir tenir compte quand on cherche à optimiser le placement
des données.
6
La lecture d’un bloc, étant donné son adresse, se décompose en trois étapes :
- positionnement de la tête de lecture sur la piste contenant le bloc ;
- rotation du disque pour attendre que le bloc passe sous la tête de lecture
(rappelons que les têtes sont fixe, c’est le disque qui tourne) ;
- transfert du bloc.
La durée d’une opération de lecture est donc la somme des temps consacrés à chacune
des trois opérations, ces temps étant désignés respectivement par les termes délai de
positionnement, délai de latence et temps de transfert. Le temps de transfert est
négligeable pour un bloc, mais peu devenir important quand des milliers de blocs
doivent être lus. Le mécanisme d’écriture est à peu près semblable à la lecture, mais
peu prendre un peu plus de temps si le contrôleur vérifie que l’écriture s’est faite
correctement.
7
II.2. Optimisation
SQL étant un langage déclaratif dans lequel on n’indique ni les algorithmes à appliquer,
ni les chemins d’accès aux données, le système a toute latitude pour déterminer ces
derniers et les combiner de manière à obtenir les meilleures performances.
Le module chargé de cette tâche, l’optimiseur de requêtes, tient donc un rôle
extrêmement important puisque l’efficacité d’un SGBD est fonction, pour une grande
part, du temps d’exécution des requêtes. Ce module est complexe. Il applique d’une part
des techniques éprouvées, d’autre part des heuristiques propres à chaque système. Il est
en effet reconnu qu’il est très difficile de trouver en un temps raisonnable
l’algorithme optimal pour exécuter une requête donnée. Afin d’éviter de consacrer des
ressources considérables à l’optimisation, ce qui se ferait au détriment des autres tâches
du système, les SGBD s’emploient donc à trouver, en un temps limité, un algorithme
raisonnablement bon.
En base de données, le programme qui évalue une requête a une forme très particulière.
On l’appelle plan d’exécution. Il a la forme d’un arbre constitué d’opérateurs qui
échangent des données. Chaque opérateur effectue une tâche précise et restreinte:
transformation, filtrage, combinaisons diverses. Cela permet au système de construire
très rapidement, à la volée, un plan et de commencer à l’exécuter.
Il faut ici élargir le schéma: à chaque étape, 1 ou 2, plusieurs options sont possibles.
Pour l’étape 1 : c’est la capacité des opérateurs de l’algèbre à fournir plusieurs
expressions équivalentes. La Figure 6 montre par exemple deux combinaisons
possibles issues de la même requête SQL.
Pour l’étape 2 les options sont liées au choix de l’algorithmique, des opérateurs à
exécuter.
Considérons par exemple la requête suivante qui calcule le film le mieux ancien:
select titre from Film where annee = (select min (annee) from Film)
Cette méthode peut s’avérer très inefficace et il est préférable de transformer la requête
avec imbrication en une requête équivalente sans imbrication (un seul bloc) quand cette
équivalence existe. Malheureusement, les systèmes relationnels ne sont pas toujours
capables de déceler ce type d’équivalence. Le choix de la syntaxe de la requête SQL a
donc une influence sur les possibilités d’optimisation laissées au SGBD.
Cette requête est en un seul « bloc », mais il est tout à fait possible – question de style ?
– de l’écrire de la manière suivante:
Au lieu d’utiliser in, on peut également effectuer une requête corrélée avec exists.
Dans les deux dernier cas on a trois blocs. La requête est peut-être plus facile à
comprendre, mais le système a très peu de choix sur l’exécution: on doit parcourir tous
les films parus en 1958, pour chacun on prend tous les rôles, et pour chacun de ces rôles
on va voir s’il s’agit bien de James Stewart.
S’il n’y a pas d’index sur le champ annee de Film, il faudra balayer toute la table,
puis pour chaque film, c’est la catastrophe: il faut parcourir tous les rôles pour garder
ceux du film courant car aucun index n’est disponible. Enfin pour chacun de ces rôles
il faut utiliser l’index sur Artiste.
12
2. Traduction et réécriture
Nous nous concentrons maintenant sur le traitement d’un bloc, étant entendu que ce
traitement doit être effectué autant de fois qu’il y a de blocs dans une requête. Il
comprend plusieurs phases. Tout d’abord une analyse syntaxique est effectuée, puis
une traduction algébrique permettant d’exprimer la requête sous la forme d’un
ensemble d’opérations sur les tables. Enfin l’optimisation consiste à trouver les
meilleurs chemins d’accès aux données et à choisir les meilleurs algorithmes possibles
pour effectuer ces opérations.
L’analyse syntaxique vérifie la validité (syntaxique) de la requête. On vérifie
notamment l’existence des relations (arguments de la clause from) et des attributs
(clauses select et where). On vérifie également la correction grammaticale
(notamment de la clause where). D’autres transformations sémantiques simples sont
faites au delà de l’analyse syntaxique. Par exemple, on peut détecter des contradictions
comme année = 1998 and année = 2003. Enfin un certain nombre de
simplifications sont effectuées. À l’issue de cette phase, le système considère que la
requête est bien formée.
L’étape suivante consiste à traduire la requête en une expression algébrique. Nous
allons prendre pour commencer une requête un peu plus simple que la précédente:
13
trouver le titre du film paru en 1958, où l’un des acteurs joue le rôle de John Ferguson.
Voici la requête SQL:
Cette requête correspond aux opérations suivantes: une jointure entre les rôles et les
films, une sélection sur les films (année=1958), une sélection sur les rôles (‘John
Ferguson’), enfin une projection (titre) pour éliminer les colonnes non désirées.
Dans l’arbre, les feuilles correspondent aux tables de l’expression algébrique, et les
nœuds internes aux opérateurs. Un arc entre un nœud et son nœud père indique que
l’« opération s’applique au résultat de l’opération ».
Il existe plusieurs niveaux RAID (de 0 à 6), chacun correspondant à une organisation
différente des données et donc à des caractéristiques différentes. Le niveau 0 est
simplement celui du stockage sur un seul disque. Nous présentons ci-dessous les
caractéristiques des principaux niveaux.
1. Duplication (RAID 1)
Le RAID 1 applique une solution brutale : toutes les entrées/sorties s’effectuent en
parallèle sur deux disques. Les écritures ne sont pas simultanées afin d’éviter qu’une
panne électrique ne vienne interrompre les têtes de lecture au moment où elles écrivent
le même bloc, qui serait alors perdu. L’écriture a donc d’abord lieu sur le disque
principal, puisque sur le second (dit « disque miroir »).
15
Le RAID 1 est coûteux puisqu’il nécessite deux fois plus d’espace que de données. Il
permet certaines optimisations en lecture : par exemple la demande d’accès à un bloc
peut être transmise au disque dont la tête de lecture est la plus proche de la piste
contenant le bloc.
Les performances sont également améliorées en écriture car deux demandes de deux
processus distincts peuvent être satisfaites en parallèle. En revanche il n’y a pas
d’amélioration du taux de transfert puisque les données ne sont pas réparties sur les
disques.
fonction des autres disques. En d’autres termes, pour la reconstruction après une panne,
la distinction disque de contrôle/disque de données n’est pas pertinente.
Le rôle d’un index est d’accélérer la recherche d’information (lors d’un SELECT) dans
une base une base de données.
Par défaut, TOUS les SGBD entretiennent un index primaire qui est l’index crée sur la
clé primaire (PK). Cependant les développeurs peuvent décider de créer d’autres index
sur des colonnes qui ne sont pas des PK.
Créer des index sur les colonnes de Foreign KEY pour accélérer les jointures,
sauf si la combinaison de FK forme une clé primaire (redondance d’index).
Créer des index sur les colonnes de la clause WHERE sauf si le WHERE contient
un like de fin (WHERE nom like ‘%CHE’), ou si le WHERE contient une
fonction.
Créer des index sur des colonnes utilisées dans un ORDER BY, un GROUP BY,
un HAVING.
Créer des index sur une colonne ayant une petite plage de valeurs inutiles. (NULL)
Créer des index une fois que les insertions sont complétées.
Attention : Même si les index sont des accélérateurs, trop d’index ralenti le SGBD. Il
ne faudrait pas que le SGBD passe son temps à maintenir TOUS les index. Les index
ralentissent le système durant les insertions, car la table des index doit être mise à jour.
18
1. Clustered index
Il existe un seul clustered index par table. Ces index stockent les lignes de données de la
table en fonction de leurs valeurs de clé. Les index clustérisés trient et stockent les lignes
de données dans la table ou la vue en fonction de leurs valeurs de clé. En principe, toutes
les tables devraient avoir un index cluster défini sur la ou les colonnes ayant la propriété
d’unicité ou de clé primaire. Par défaut lorsque SQL server crée une table avec clé
primaire, il y ajoute un CLUSTERD index.
Si vous voulez mettre un autre index Cluster sur votre table il faudra :
1. A la création de table indique que la PK n’est pas un index Cluster
Create table personnages(id int identity(1,1) not null primary key
nonclustered, alias varchar(10) NOT NULL, nom varchar(30) not null,
descriptions varchar(60) not null, typ char(1) not null );
Dans les index Clustérisés le système est organisé sous forme d’arborescence binaire
parfaitement équilibré, B-Arbre. Le parcours de l’arbre est suffisant pour obtenir toute
l’information désirée.
En général :
CREATE [CLUSTERED] INDEX nom_de_index ON nom_table (nom_colonne)
IV.1. Préliminaires
Commençons dès maintenant par un exemple illustrant le problème. Supposons que
l’application Officiel des spectacles propose une réservation des places pour une
séance. Voici le programme de réservation:
ProgrammeRESERVATION
Entrée
Une séance s
Le nombre de places souhaité NbPlaces
Le client c
debut
Lire la séance s
si (nombre de places libres> NbPlaces)
Lire le compte du spectateur c
Débiter le compte du client
Soustraire NbPlaces au nombre de places vides
Ecrire la séance s
Ecrire le compte du client c
finsi
fin
22
De plus, la nature des informations manipulées est indifférente : les règles pour le contrôle
de la concurrence sont les mêmes pour des films, des comptes en banques, des stocks
industriels, etc. Tout ceci mène à représenter un programme de manière simplifiée
comme une suite de lectures et d’écritures opérant sur des données désignées
abstraitement par des variables (généralement x, y, z, ...).
Le programme RSERVATION se représente donc simplement par la séquence
𝒓[𝒔] 𝒓[𝒄] 𝒘[𝒄] 𝒘[𝒔]
Exemple
Voici un exemple de deux exécutions concurrentes du programme RSERVATION
𝑷𝟏 et 𝑷𝟐. Chaque programme veut réserver des places dans la même séance, pour
deux clients distincts 𝑪𝟏et 𝑪𝟐
𝑟1(𝑠)𝑟1(𝑐1)𝑟2(𝑠)𝑟2(𝑐2)𝑤2(𝑠)𝑤2(𝑐2)𝑤1(𝑠)𝑤1(𝑐1)
23
Donc on effectue d’abord les lectures pour 𝑃1, puis les lectures pour 𝑃2 enfin les
écritures pour 𝑃2 et 𝑃1 dans cet ordre. Imaginons maintenant que l’on se trouve dans
la situation suivante :
1. Il reste 50 places libres pour la séance 𝑺.
2. 𝑃1 veut réserver 5 places pour la séance 𝑺.
3. 𝑃2 veut réserver 2 places pour la séance 𝑺.
Voici le déroulement imbriqué des deux exécutions 𝑃1(𝑠, 5, 𝑐1)𝑒𝑡 𝑃2(𝑠, 2, 𝑐2), en
supposant que la séquence des opérations est celle donnée ci-dessus. On se concentre
pour l’instant sur les évolutions du nombre de places vides.
1. 𝑃1 lit 𝑺 et 𝑐1. Nb places vides : 50.
2. 𝑃2 lit 𝑺 et 𝑐2. Nb places vides : 50.
3. 𝑃2 écrit 𝑺 avec nb places =50-2=48.
4. 𝑃2 écrit le nouveau compte de 𝑐2.
5. 𝑃1 écrit 𝑺 avec nb places =50-5=45.
6. 𝑃1 écrit le nouveau compte de 𝑐1.
On est assuré dans ce cas qu’il n’y a pas de problème : 𝑃2 lit une donnée écrite par
𝑃1 qui a fini de s’exécuter et ne créera donc plus d’interférence.
Cela étant cette solution de “concurrence zéro” n’est pas viable : on ne peut se
permettre de bloquer tous les utilisateurs sauf un, en attente d’un programme qui peut
durer extrêmement longtemps. Heureusement l’exécution en série est une contrainte
trop forte, comme le montre l’exemple suivant.
Cette exécution est correcte. On obtient un résultat strictement semblable à celui issu
d’une exécution en série. Il existe donc des exécutions imbriquées qui sont aussi
correctes qu’une exécution en série et qui permettent une meilleure concurrence. On
parle d’exécutions sérialisables pour indiquer qu’elles sont équivalentes à des
exécutions en série. Les techniques qui permettent d’obtenir de telles exécutions
relèvent de la sérialisabilité.
25
Commit A(a=20) t5
use exemple
declare @v int
begin tran
begin tran
select @v = A.a from A where id=1
set @v = @v-10
print @v
--select * from A
if @v<=15
rollback
--select * from A
commit
--select * from A
commit
IV.5. Verrous
Le verrouillage est un mécanisme utilisé par le Moteur de base de données SQL Server
pour synchroniser l'accès simultané de plusieurs utilisateurs à la même donnée.
Avant qu'une transaction acquière une dépendance sur l'état actuel d'un élément de
données, par exemple par sa lecture ou la modification d'une donnée, elle doit se protéger
des effets d'une autre transaction qui modifie la même donnée. Pour ce faire, la
transaction demande un verrou sur l'élément de données. Le verrou possède plusieurs
modes, par exemple partagé ou exclusif. Le mode de verrouillage définit le niveau de
dépendance de la transaction sur les données.
28
Le tableau suivant illustre les modes de verrouillage des ressources utilisés par le Moteur
de base de données.
Mise à jour (U) Utilisé pour les ressources pouvant être mises à jour.
Empêche une forme de blocage courante qui se produit
lorsque plusieurs sessions lisent, verrouillent et mettent
à jour des ressources ultérieurement.
Ces trois catégories combinées permettent que le langage T-SQL prenne en compte
des fonctionnalités algorithmiques, et admette la programmabilité. Le T-SQL est non
seulement un langage de requêtage, mais aussi un vrai langage de programmation à
part entière. Sa capacité à écrire des procédures stockées et des déclencheurs
30
(Triggers), lui permet d’être utilisé dans un environnement client de type .NET, au
travers d’une application en C#, en [Link] ou JAVA.
V.1. Expressions
Dans le T-SQL, nous pouvons utiliser des expressions, permettant de mettre en œuvre
l’aspect algorithmique du langage. Les expressions peuvent prendre plusieurs formes.
- Les constantes : une constante est une variable, dont la valeur ne peut être
changée lors de l’exécution d’instructions T-SQL.
- Les noms de colonnes : ils pourront être utilisés comme expressions. La valeur
de l’expression étant la valeur stockée dans une colonne pour une ligne donnée.
- Les variables : il s’agit d’entités qui peuvent être employées en tant
qu’expressions ou dans des expressions. Les variables sont préfixées par le
caractère @. Les variables systèmes sont préfixées par les caractères @@. La
valeur de l’expression variable est la valeur de la variable elle-même.
- Les fonctions : il est possible d’utiliser comme expression n’importe quelle
fonction. Elles permettent d’exécuter des blocs d’instructions T-SQL, et de
retourner une valeur.
- Les expressions booléennes : elles sont destinées à tester des conditions. Elles
sont utilisées dans des structures algorithmiques de type WHILE, IF ou encore
dans la clause WHERE d’une requête SQL, à affiner de permettre d’afficher
une recherche, ou bien à poser une condition d’exécution.
- Les sous-requêtes : une sous requête SELECT peut-être placée en tant
qu’expression. La valeur de l’expression est la valeur renvoyée par la requête.
31
1. Affichage d’informations
Syntaxe :
Print Elément_A_Afficher
Exemples:
Soient @a et @b des variables de type Chaîne de caractères, @c et @d des variables de
type entier
Print 'Bonjour' -- Affiche le texte Bonjour
Print @a -- Affiche la valeur de @a
Print @c -- Affiche la valeur de @c
Print @c + @d -- Affiche la somme des variables @c et @d
Print convert(varchar, @c) + @b
2. Structures alternatives
If...Else:
Syntaxe :
If Condition
Begin
Instructions
End
Else
Begin
Instructions
End
Remarques:
Si une instruction Select apparaît dans la condition, il faut la mettre entre
parenthèses
Si dans la clause If ou Else il existe une seule instruction, on peut omettre
le Begin et le End
Exemple :
On souhaite vérifier si le stock de l'article portant le numéro 10 a atteint son seuil
[Link] c'est le cas afficher le message 'Rupture de stock' :
Declare @QS int
Declare @SM int
Select @QS = (Select QteEnStock from article Where NumArt =10)
Select @SM = (Select SeuilMinimum from article Where NumArt =10)
If @QS<=@SM
Print 'Rupture de stock'
Else
Print 'Stock disponible'
33
3. Instruction case
Case : Permet d'affecter, selon une condition, une valeur à un champ dans une
requête Select
Syntaxe:
Case
When Condition1 Then Résultat 1
When Condition2 Then Résultat 2
...
Else Résultat N
End
Exemple :
Afficher la liste des articles (Numéro, Désignation et prix) avec en plus une
colonne Observation qui affiche 'Non Disponible' si la quantité en stock est égale
à 0, 'Disponible' si laquantité en stock est supérieure au stock Minimum et 'à
Commander' sinon.
Exercices :
1. Ecrire un programme qui calcule le montant de la commande numéro 10 et affiche un
message 'Commande Normale' ou 'Commande Spéciale' selon que le montant est
inférieur ousupérieur à 100000 Fbu
2. Ecrire un programme qui supprime l'article numéro 8 de la commande numéro 5 et
met àjour le stock. Si après la suppression de cet article, la commande numéro 5 n'a plus
34
d'articlesassociés, la supprimer.
3. Ecrire un programme qui affiche la liste des commandes et indique pour chaque
commande dans une colonne Type s'il s'agit d'une commande normale (montant
<=100000Fbu) ou d'une commande spéciale (montant > 100000 Fbu)
4.. A supposer que toutes les commandes ont des montants différents, écrire un
programme qui stocke dans une nouvelle table temporaire les 5 meilleures commandes
(ayant le montantle plus élevé) classées par montant décroissant (la table à créer aura la
structure suivante : NumCom, DatCom, MontantCom)
5. Ecrire un programme qui :
Recherche le numéro de commande le plus élevé dans la table commande et
l'incrémente de 1
Enregistre une commande avec ce numéro
Pour chaque article dont la quantité en stock est inférieure ou égale au seuil
minimumenregistre une ligne de commande avec le numéro calculé et une
quantité commandée égale au triple du seuil minimum
4. Structures répétitives
Syntaxe :
While Condition
Begin
instructions
End
Remarques:
Le mot clé Break est utilisé dans une boucle While pour forcer l'arrêt de la boucle
Le mot clé Continue est utilisé dans une boucle While pour annuler l'itération en
cours et passer aux itérations suivantes (renvoyer le programme à la ligne du
while)
35
Exemple:
Tant que la moyenne des prix des articles n'a pas encore atteint 3000 Fbu et le prix le
plus élevépour un article n'a pas encore atteint 30 Fbu, augmenter les prix de 10% et
afficher après chaque modification effectuée la liste des articles. Une fois toutes les
modifications effectuées, afficher la moyenne des prix et le prix le plus élevé :
While (((Select avg(puart) from article)<3000) and (select max(puart)
from article) <6000)
Begin
Update article Set puart=puart+(puart*10)/100
Select * from article
End
Select avg(puart) as moyenne , max(puart) as [Prix eleve] from article
Syntaxe:
If Update (Nom_Colonne)
Begin
…
End
Exemple :
If update (numCom)
Print 'Numéro de commande modifié'
6. Branchement
L'instruction Goto renvoie l'exécution du programme vers un point spécifique repéré par
une étiquette
36
Syntaxe :
Goto Etiquette
Remarque :
Pour créer une étiquette, il suffit d'indiquer son nom suivi de deux points (:)
Exemple :
L'exemple précédent peut être écrit ainsi en utilisant l'instruction goto :
Declare @a decimal, @b decimal Etiquette_1:
Set @a= (Select avg(puart) from article) Set @b= (Select Max(puart) from
article)
If @a<20 and @b<30
Begin
Update article Set puart=puart+(puart*20)/100
Select * from article
Goto Etiquette_1
End
Select avg(puart) as moyenne , max(puart) as [Prix eleve] from article
7. Transaction
Une transaction permet d'exécuter un groupe d'instructions. Si pour une raison ou une
autrel'une de ces instructions n'a pas pu être exécutée, tout le groupe d'instructions est
annulé (letout ou rien) :
Pour démarrer une transaction on utilise l'instruction Begin Tran
Pour valider la transaction et rendre les traitements qui lui sont associés
effectifs, onutilise l'instruction Commit Tran
Pour interrompre une transaction en cours qui n'a pas encore été validée, on
utilise l'instruction Rollback Tran
Si plusieurs transactions peuvent être en cours, on peut leur attribuer des noms
pourles distinguer
37
Syntaxe :
Begin Tran [Nom_Transaction]
…
If Condition
RollBack Tran [Nom_Transaction]
…
Commit Tran [Nom_Transaction]
Exemple :
Supposons qu'il n'existe pas de contrainte clé étrangère entre le champ NumCom de
la table LigneCommande et le champ NumCom de la Commande.
On souhaite supprimer la commande numéro 5 ainsi que la liste de ces articles. Le
programmeserait :
Delete from Commande where NumCom=5
Delete from LigneCommande where NumCom=5
Mais si, juste après l'exécution de la première instruction et alors que la deuxième n'a
pas encore eu lieu, un problème survient (une coupure de courant par exemple) la base
de données deviendra incohérente car on aura des lignes de commande pour une
commande qui n'existe pas.
En présence d'une transaction, le programme n'ayant pas atteint l'instruction Commit
Tran, aurait annulé toutes les instructions depuis Begin Tran. Le programme devra être
alors :
Begin Tran
Delete from Commande where NumCom=5
Delete from LigneCommande where NumCom=5
Commit Tran
Syntaxe :
Raiserror (Num message|Texte message, gravité, état[, Param1,
Param2... ] )
Description :
Numéro du message : Indiquer le numéro de message pour faire appel à un
message déjà disponible dans la table SysMessages.
Texte Message : Représente le texte du message. Pour rendre certaines parties
dumessage paramétrables, Il faut la représenter avec %d. Les valeurs à affecter
à cesparamètres seront spécifiés par l'instruction raiserror (au maximum 20
paramètrespeuvent être utilisés dans un message).
Gravité : Représente le niveau de gravité. Seul l'administrateur système peut
ajouter des messages avec un niveau de gravité compris entre 19 et 25
(consulter l'aide Transact-SQL dans l'analyseur de requêtes SQL pour le détail
des niveaux de gravité).
Etat : Valeur entière comprise entre 1 et 127 qui identifie la source à partir de
laquellel'erreur a été émise (consulter l'aide Transact-SQL pour le détail sur les
différents états).
Param : Paramètres servant à la substitution des variables définies dans le
[Link] paramètres ne peuvent être que de type int, varchar, binary ou
varbinary
V.2. Curseurs
Un curseur est un groupe d'enregistrements résultat de l'interrogation d'une base de
données.L'intérêt d'utiliser des curseurs est de pouvoir faire des traitements ligne par
ligne chose qui n'est pas possible avec une requête SQL simple où un seul traitement
sera appliqué à toutes les lignes répondant à cette requête et seul le résultat final sera
visible.
39
Syntaxe
Pour déclarer un curseur
Declare nom_curseur Curs Static For Select …
MUTAMA
2022-05-19 [Link]
Keyset
--------------------------------------------
Dynamic
Cursor
Exemple :
Pour afficher la liste des articles sous la forme :
L'article Numéro ........ portant la désignation ………coûte …. …..
Exercices
1- Ecrire un programme qui pour chaque commande :
Affiche le numéro et la date de commande sous la forme :
Commande N° : ……Effectuée le : …
La liste des articles associés
Le montant de cette commande
2- Ecrire un programme qui pour chaque commande vérifie si cette commande
a au moinsun article. Si c'est le cas affiche son numéro et la liste de ses articles
sinon affiche un message d'erreur : Aucun article pour la commande …. Elle
sera supprimée et supprime cette commande
Syntaxe:
Create Procedure Nom_Procédure as
Instructions
Exécution :
Exec Nom_Procedure
Exemples :
1. Créer une procédure stockée nommée SP_Articles qui affiche la liste des articles avec
pour chaque article le numéro et la désignation :
2. Créer une procédure stockée qui calcule le nombre d'articles par commande :
Syntaxe :
Create Procedure Nom_Propriétaire.Nom_Procedure Nom_Param1_Entrée
Type_Donnée = Valeur_Par_Defaut, Nom_Param2_Entrée Type_Donnée =
Valeur_Par_Defaut… as
Instructions
44
Exécution :
Exec Nom_Procedure Valeur_Param1, Valeur_Param2... Ou
Exec Nom_Procedure Nom_Param1 = Valeur_Param1, Nom_Param2 =
Valeur_Param2...
Remarque:
Avec la deuxième syntaxe, l'utilisateur n'est pas obligé de passer les paramètres dans
l'ordre eten plus si des paramètres ont des valeurs par défaut, il n'est pas obligé de les
passer.
Exemples :
1. Créer une procédure stockée nommée SP_ListeArticles qui affiche la liste des
articlesd'une commande dont le numéro est donné en paramètre :
Create Procedure SP_ListeArticles @NumCom int as Select [Link],
DesArt, PUArt, QteCommandee From Article A, LigneCommande LC
Where [Link]=[Link] and [Link]=@NumCom
3. Créer une procédure stockée nommée SP_TypeComPeriode qui affiche la liste des
commandes effectuées entre deux dates passées en paramètres. En plus si le
nombre de ces commandes est supérieur à 100, afficher 'Période rouge'. Si le
nombre de ces commandes est entre 50 et 100 afficher 'Période jaune' sinon
afficher 'Période blanche'(exploiter la procédure précédente) :
45
Remarque :
Les procédures utilisant des paramètres de sortie peuvent avoir ou ne pas avoir (selon
lebesoin) des paramètres en entrée
Syntaxe :
Create Procedure Nom_Propriétaire.Nom_Procedure
Nom_Param1_Entrée Type_Donnée = Valeur_Par_Defaut,
Nom_Param1_Entrée Type_Donnée = Valeur_Par_Defaut,…
Nom_Param1_Sortie Type_Donnée Output, Nom_Param2_Sortie
Type_Donnée Output...
as
Instructions
--Exécution :
Declare Var_Param1_Sortie Type_Param1_Sortie
Declare Var_Param2_Sortie Type_Param2_Sortie
...
Exec Nom_Procedure Val_Param1_Entrée, Val_Param2_Entrée...,
Var_Param1_Sortie Output, Var_Param2_Sortie Output...
46
Exemples :
1. Créer une procédure stockée nommée SP_NbrCommandes qui retourne le nombre
decommandes :
Create Procedure SP_NbrCommandes @Nbr int output as Set @Nbr = (Select
count(NumCom) from Commande)
Syntaxe :
Create Procedure Nom_Propriétaire.Nom_Procedure
...
as
Instructions
...
Return Valeur_Sortie
Exécution :
Declare Var_Retour Type_Var_Retour
...
Exec Var_Retour=Nom_Procedure …
Exemple :
Créer une procédure stockée nommée SP_TypePeriode qui renvoie un code de retour.
Si le nombre de commandes est supérieur à 100, la procédure renvoie 1. Si le nombre
de commandes est entre 50 et 100, la procédure renvoie 2. Si le nombre de commandes
est inférieur à 50, la procédure renvoie 3. Si une erreur système a lieu, la procédure
renvoie 4 :
Create Procedure SP_TypePeriode as Declare @NbrCom int
Set @NbrCom = (Select count(NumCom) from Commande)
If @NbrCom >=100
Return 1
If @NbrCom >50
Return 2
If @NbrCom <=50
Return 3
If @@ERROR <>0
Return 4
exec @an=SP_TypePeriode
print @an
48
Exemple :
Drop Procedure NbrArticlesCommande
V.4. Fonctions
1. Fonction qui retourne une valeur scalaire
Syntaxe :
Create Function Nom_Procedure (Nom_Param1 Type_Donnée, …)
Returns type_de_retour
as
Instructions
...
Return Valeur
Exemple :
Créer une fonction nommée F_NbrCommandes qui retourne le nombre de commandes
Create Function F_NbrCommandes() Returns int
as begin
declare @Nbr int
Set @Nbr = (Select count(NumCom) from Commande)
Return @Nbr
end
49
Exemple :
Créer une fonction nommée F_ListeArticles qui return la liste des articles d'une
commandedont le numéro est donné en paramètre :
Les déclencheurs peuvent être associés à trois types d'actions de déclenchement sur
une table :
Déclencheurs d'insertion : Se déclenchent suite à une opération d'ajout
d'enregistrements dans la table ;
Déclencheurs de modification : Se déclenchent suite à une opération de
modification des enregistrements de la table ;
Déclencheurs de suppression : Se déclenchent suite à une opération de
suppression d'enregistrements à partir de la table.
Les triggers consomment peu de ressources système à condition qu'ils n'utilisent pas
decurseurs.
Plusieurs déclencheurs AFTER sont autorisés sur une même table et pour
une même action de déclenchement. La procédure stockée système
sp_SetTriggerOrder permet de spécifier le premier et le dernier
déclencheur à exécuter pour une action :
Exec sp_SetTriggerOrder
@triggername = 'MyTrigger',
@order = 'first|Last|None',
@stmttype = 'Insert|Update|Delete'
Exemple :
Un utilisateur exécute l'action suivante :
Insert into commande values (100,'2007-09-13')
Supposons qu'un trigger instead of est associé à l'action d'insertion sur la table
commande. Dans le corps de ce trigger, on affiche le contenu de la table inserted et le
contenu de la table commande.
Dans la table inserted, on remarquera la présence de la commande numéro 100 mais
dans la table commande cet enregistrement est absent et ne sera pas ajouté à la
table commande même après la fin de l'exécution de l'action d'ajout. Ceci est dû au
fait que l'exécution des triggers instead of remplace l'action de déclenchement.
Cas où seul des triggers AFTER sont associés à l'action de mise à jour (insert,
deleteou update) : Les contraintes sont testées en premier. Si une contrainte n'est
pas vérifiée l'insertion est annulée sans que le trigger soit exécuté. Si les
contraintes sont vérifiées, le trigger est exécuté. Les enregistrements ajoutés
apparaissent et dans la table d'origine et dans les tables temporaires concernées
par l'action. Si dans le code associé à ce trigger, aucune action n'annule la
transaction, l'opération est validée.
Cas où un trigger INSTEAD OF ainsi que des triggers AFTER sont associés à
l'action de mise à jour (insert, delete ou update) : Le trigger INSTEAD OF est
exécuté en premier, les enregistrements concernés par l'action de mise à jour
53
Syntaxe :
Create Trigger Nom_Trigger
On Nom_Table
Instead Of | For Opération1, Opération2...
As
1. Instructions
Remarque :
Opération peut prendre Insert, Delete ou Update selon le type de trigger à créer
Un même trigger peut être associé à une seule opération ou à plusieurs
opérations à la fois
A chaque table, peuvent être associées trois triggers au maximum : ajout,
modificationet suppression (un trigger concernant deux opérations est compté
comme deux triggers)
Le corps du trigger créé peut inclure n'importe quelles instructions excepté
Create Database, Alter Database, Drop Database, Restore Database, Restore
54
Log et reconfigure ;
Exercices :
1. Le trigger suivant interdit la modification des commandes
Create Trigger Tr_Empêcher_Modif
On Commande
For Update As Rollback
5. Le trigger suivant à l'ajout d'une ligne de commande vérifie si les quantités sont
disponibles et met le stock à jour
Remarque :
Si le trigger déclenché effectue une opération sur une autre table, les triggers associés
à cettetable sont alors déclenchés (principe de cascade)
55
Syntaxe :
Drop Trigger Nom_Trigger
Syntaxe :
Alter Trigger Nom_Trigger
On Nom_Table
For Opération1, Opération2...
as
Nouvelles Instructions
V.6. Vue
Une vue est une des fonctionnalités les plus remarquables des SGBD relationnels.
Elle suggère la possibilité d’ajouter au schéma des tables ’virtuelles’ qui ne sont rien
d’autres que le résultat de requêtes stockées. De telles tables sont nommées des vues
dans la terminologie relationnelle. On peut interroger des vues comme des tables
stockées. Une vue n’induit aucun stockage puisqu’elle n’existe pas physiquement, et
permet d’obtenir une représentation différente des tables sur lesquelles elle est basée.
Exemple : on peut créer une vue qui ne contient que les cinémas parisiens :
CREATE VIEW ParisCinemas
AS SELECT * FROM Cinema WHERE ville = ’Paris’
On peut aussi en profiter pour restreindre la vision des cinémas parisiens à leur nom
et à leur nombre de salles.
CREATE VIEW SimpleParisCinemas AS SELECT nom, COUNT(*) AS nbSalles
FROM Cinema c, Salle s WHERE ville = ’Paris’ AND [Link] = [Link]
GROUP BY [Link]
Enfin un des intérêts des vues est de donner une représentation dénormalisée de la
base, en regroupant des informations par des jointures. Par exemple on peut créer une
vue Casting donnant explicitement les titres des films, leur année et les noms et
prénoms des acteurs.
CREATE VIEW Casting (film, annee, acteur, prenom) AS SELECT titre,
annee, nom, prenom FROM Film f, Role r, Artiste a WHERE [Link] =
[Link] AND [Link] = [Link]
On peut ensuite donner des droits en lecture sur cette vue pour que cette information
limitée soit disponible à tous.
GRANT SELECT ON Casting TO PUBLIC
Cet ordre s’adresse à une vue issue de trois tables. Il n’y a clairement pas assez
d’information pour alimenter ces tables de manière cohérente, et l’insertion n’est pas
possible (de même que toute mise à jour). De telles vues sont dites non modifiables.
Les règles définissant les vues modifiables sont très strictes.
1. La vue doit être basée sur une seule table.
2. Toute colonne non référencée dans la vue doit pouvoir être mise à NULL ou
disposer d’une valeur par défaut.
3. On ne peut pas mettre-à-jour un attribut qui résulte d’un calcul ou d’une
opération.
Il est donc tout à fait possible d’insérer, modifier ou détruire la table Film au travers
de la vue ParisCinema.
L’insertion donnée en exemple ci-dessus devient impossible. Enfin on détruit une vue
avec la syntaxe courante SQL :
DROP VIEW ParisCinemas
59
VI.3. Entités
Les entités dans les spécifications de l'API Java Persistence permettent d'encapsuler
les données d'une occurrence d'une ou plusieurs tables. Ce sont de simples POJO
(Plain Old Java Object). Un POJO est une classe Java qui n'implémente aucune
interface particulière ni n'hérite d'aucune classe mère spécifique. Un objet Java de type
POJO mappé vers une table de la base de données grâce à des méta data via l'API Java
Persistence est nommé bean entité (Entity bean). Un bean entité doit obligatoirement
avoir un constructeur sans argument et la classe du bean doit obligatoirement être
60
Annotation Rôle
@[Link] : Préciser le nom de la table concernée par le
mapping
Attributs : Rôle
VI.5. EntityManager
Les interactions entre la base de données et les beans entités sont assurées par un objet
de type [Link] : il permet de lire et rechercher des données
mais aussi de les mettre à jour (ajout, modification, suppression). L'EntityManager est
donc au coeur de toutes les actions de persistance.
Les beans entités étant de simple POJO, leur instanciation se fait comme pour tout
autre objet Java. Les données de cette instance ne sont rendues persistantes que par
une action explicite demandée à l'EntityManager sur le bean entité.
L'EntityManager assure aussi les interactions avec un éventuel gestionnaire de
transactions.
Un EntityManager gère un ensemble défini de beans entités nommé persistence unit.
La définition d'un persistence unit est assurée dans un fichier de description nommé
[Link].
Sous Java EE, il est préférable d'utiliser l'injection de dépendance pour obtenir une
fabrique ou un contexte de persistance.
L'annotation @[Link] sur un champ de type
EntityManagerFactory permet d'injecter une fabrique. Cette annotation possède un
attribut unitName qui précise le nom de l'unité de persistance.
Exemple :
@PersistenceUnit(unitName="MaBaseDeTestPU")
Il est alors possible d'utiliser la fabrique pour obtenir un objet de type EntityManager
qui encapsule un contexte de persistence de type extended. Pour associer ce contexte
à la transaction courante, il faut utiliser la méthode joinTransaction().
La méthode close() est automatiquement appelée par le conteneur : il ne faut pas
utiliser cette méthode dans un conteneur sinon une exception de type
IllegalStateException est levée.
L'annotation @[Link] sur un champ de type
EntityManager permet d'injecter un contexte de persistance. Cette annotation
possède un attribut unitName qui précise le nom de l'unité de persistance.
Exemple :
@PersistenceContext(unitName="MaBaseDeTestPU")
private EntityManager entityManager;
2. Classe EntityManager
La méthode contains() de l'EntityManager permet de savoir si une instance fournie en
paramètre est gérée par le contexte. Dans ce cas, elle renvoie true, sinon elle renvoie
false.
La méthode clear() de l'EntityManager permet de détacher toutes les entités gérées par
le contexte. Dans ce cas, toutes les modifications apportées aux entités sont perdues :
64
il est préférable d'appeler la méthode flush() avant la méthode clear() afin de rendre
persistante toutes les modifications.
L'appel des méthodes de mise à jour persist(), merge() et remove() ne réalise pas
d'actions immédiates dans la base de données sous-jacente. L'exécution de ces actions
est à la discrétion de l'EntityManager selon le FlushModeType (AUTO ou COMMIT).
Dans le mode AUTO, les mises à jour sont reportées dans la base de données avant
chaque requête. Dans le mode COMMIT, les mises à jour sont reportées dans la base
de données lors du commit de la transaction.
Le mode COMMIT est plus performant car il limite les échanges avec la base de
données.
Il est possible de forcer l'enregistrement des mises à jour dans la base de données en
utilisant la méthode flush() de l'EntityManager.
L'objet Query gère aussi des paramètres nommés dans la requête. Le nom de chaque
paramètre est préfixé par « : » dans la requête. La méthode setParameter() permet de
fournir une valeur à chaque paramètre.
EXERCICE D’APPLICATION
66
REFERENCES BIBLIOGRAPHIQUES
[1] Jarke M., Koch J., « Query Optimization in Database Systems » ACM Computing
Surveys, vol. 16, n° 2, p. 111-152, Juin 1984.
[2] Kim Won, Reiner S., Batory D., Query Processing in Database Systems, Springer-
Verlag Ed., 1985.
[3] Graefe G., McKenna W., « The Volcano Optimizer Generator », Proceedings of
the 9th International Conference on Data Engineering, IEEE Ed., p. 209-218, 1993.
[4] Gray J. Ed., The Benchmark Handbook , Morgan & Kaufman Pub., San Mateo,
1991.
[5] Selinger P., « Access Path Selection in a Relational Database Management System
», ACM SIGMOD Intl. Conf. On Management of Data, Boston, Mai 1979.
[6] Transaction Processing Council, Benchmark TPC/D, San Fransisco, CA, 1995.
[7]Wikipedia,"Mapping objet-relationnel", juin 2016: [Link]
Mapping_objet-relationnel
[8]Carrez C., Des Structures aux Bases de Données, Masson
[9] Gardarin G., Maîtriser les Bases de Données: modèles et langages, Eyrolles
[10] Marcenac, P., SGBD relationnels, Optimisation des performances, Eyrolles.
[11] Date C.J., An Introduction to Database Systems, 5e edition, The Systems
Programming Series, volumes I (854 pages) et II (383 pages), Addison Wesley, 1990.
[12] Delobel C., Lécluse Ch., Richard Ph., Bases de Données : Des Systèmes
Relationnels aux Systèmes à Objets, 460 pages, InterÉditions, Paris, 1991.
[13] Gardarin G., Gardarin O., Le Client-Serveur, 470 pages, Éditions Eyrolles, 1997.
[14] Gray J. Ed., The Benchmark Handbook, Morgan & Kaufman Pub., San Mateo,
1991.
[15] Silberschatz A., Korth H., Sudarshan S., Database System Concepts, 819 pages,
Mc Graw-Hill Editions, 3e edition, 1997.