root/traduc/trunk/postgresql/advanced.xml

Revision 973, 18.5 kB (checked in by gleu, 8 months ago)

L'encodage indique dans les fichiers XML devient iso-8859-15 (latin9 donc) au lieu du vieux et obsolète iso-8859-1, pour autoriser des caractères
comme œ et le symbole euro.
La génération de la documentation utilise maintenant recode pour transformer le latin9 en utf8 car tidy (utilisé dans l'étape qui suit) ne reconnaît
pas le latin9... d'où les problèmes de visualisation des caractères spécifiques au latin9. Du coup, la configuration de tidy est modifiée pour qu'il
sache qu'il utilise des fichiers en utf8 et qu'il doit créer des fichiers dans ce même encodage.

Seules les versions XML sont modifiées car ce sont (à mon souvenir) les seules à utiliser ce type de caractères.

  • Property svn:keywords set to Date Author Revision
Line 
1 <?xml version="1.0" encoding="ISO-8859-15"?>
2 <!-- Dernière modification
3      le       $Date$
4      par      $Author$
5      révision $Revision$ -->
6 <!-- SAS : 20070311 -->
7
8  <chapter id="tutorial-advanced">
9   <title>Fonctionnalités avancées</title>
10
11   <sect1 id="tutorial-advanced-intro">
12    <title>Introduction</title>
13
14    <para>
15     Le chapitre précédant couvre les bases de l'utilisation
16     de <acronym>SQL</acronym> pour le stockage et l'accès aux données avec
17     <productname>PostgreSQL</productname>. Il est temps d'aborder
18     quelques fonctionnalités avancées du <acronym>SQL</acronym>
19     qui simplifient la gestion et empêchent la perte ou la corruption des
20     données. Quelques extensions de <productname>PostgreSQL</productname> sont
21     également abordées.
22    </para>
23
24    <para>
25     Ce chapitre fait occasionnellement référence aux exemples disponibles dans le
26     <xref linkend="tutorial-sql"/> pour les modifier ou les améliorer. Il est donc
27     préférable d'avoir lu ce chapitre. Quelques exemples de ce
28     chapitre sont également disponibles dans <filename>advanced.sql</filename>
29     situé dans le répertoire du tutoriel. Ce fichier contient, de plus, quelques
30     données à charger pour utiliser l'exemple. Cela n'est pas repris ici
31     (on peut se référer à la <xref linkend="tutorial-sql-intro"/> pour savoir comment
32     utiliser ce fichier).
33    </para>
34   </sect1>
35
36
37   <sect1 id="tutorial-views">
38    <title>Vues</title>
39
40    <indexterm zone="tutorial-views">
41     <primary>vue</primary>
42     <secondary>view</secondary>
43    </indexterm>
44
45    <para>
46     Se référer aux requêtes de la <xref linkend="tutorial-join"/>.
47     Si la liste des enregistrements du temps et des villes est d'un
48     intérêt particulier pour l'application considérée mais qu'il devient
49     contraignant de saisir la requête à chaque utilisation, il est possible
50     de créer une <firstterm>vue</firstterm> avec la requête. De ce fait, la
51     requête est nommée et il peut y être fait référence de la même façon
52     qu'il est fait référence à une table&nbsp;:
53
54 <programlisting>CREATE VIEW ma_vue AS
55     SELECT ville, t_basse, t_haute, prcp, date, emplacement
56         FROM temps, villes
57         WHERE ville = nom;
58
59 SELECT * FROM ma_vue;</programlisting>
60    </para>
61
62    <para>
63     L'utilisation des vues est un aspect clé d'une bonne
64     conception des bases de données SQL. Les vues permettent
65     d'encapsuler les détails de la structure des tables. Celle-ci peut
66     alors changer avec l'évolution de l'application, tandis que l'interface reste
67     constante.
68    </para>
69
70    <para>
71     Les vues peuvent être utilisées dans quasiment toutes les situations
72     où une vraie table est utilisable. Il n'est, de plus, pas
73     inhabituel de construire des vues reposant sur d'autres vues.
74    </para>
75   </sect1>
76
77
78   <sect1 id="tutorial-fk">
79    <title>Clés étrangères</title>
80
81    <indexterm zone="tutorial-fk">
82     <primary>clé étrangère</primary>
83     <secondary>foreign key</secondary>
84    </indexterm>
85
86    <indexterm zone="tutorial-fk">
87     <primary>intégrité référentielle</primary>
88     <secondary>referential integrity</secondary>
89    </indexterm>
90
91    <para>
92     Soient les tables
93     <classname>temps</classname> et <classname>villes</classname> définies
94     dans le <xref linkend="tutorial-sql"/>.
95     Il s'agit maintenant de s'assurer que personne
96     n'insère de ligne dans la table <classname>temps</classname> qui ne
97     corresponde à une entrée dans la table <classname>villes</classname>.
98     On appelle cela maintenir l'<firstterm>intégrité
99     référentielle</firstterm> des données. Dans les systèmes de bases de
100     données simplistes, lorsqu'au moins c'est possible, cela est parfois
101     obtenu par la vérification préalable de l'existence d'un enregistrement
102     correspondant dans la table <classname>villes</classname>, puis par
103     l'insertion, ou l'interdiction, du nouvel enregistrement dans
104     <classname>temps</classname>. Puisque cette approche, peu pratique,
105     présente un certain nombre d'inconvénients,
106     <productname>PostgreSQL</productname> peut se charger du maintien de
107     l'<firstterm>intégrité référentielle</firstterm>.
108    </para>
109
110    <para>
111     La nouvelle déclaration des tables ressemble alors à ceci&nbsp;:
112
113 <programlisting>CREATE TABLE villes (
114         ville       varchar(80) primary key,
115         emplacement point
116 );
117
118 CREATE TABLE temps (
119         ville      varchar(80) references villes,
120         t_haute int,
121         t_basse int,
122         prcp       real,
123         date       date
124 );</programlisting>
125
126     Lors d'une tentative d'insertion d'enregistrement non valide&nbsp;:
127
128 <programlisting>INSERT INTO temps VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28');</programlisting>
129
130 <screen>ERROR:  insert or update on table "temps" violates foreign key constraint "temps_ville_fkey"
131 DETAIL : Key (ville)=(a) is not present in table "villes".</screen>
132
133 <!-- SAS 20061109
134 Pourquoi ne pas traduire les messages d'erreur ?
135 <screen>ERROR:  insert or update on table "temps" violates foreign key constraint "temps_ville_fkey"
136 DETAIL:  Key (ville)=(Berkeley) is not present in table "villes".</screen>
137 -->
138    </para>
139
140 <!-- SAS 20080225
141 Clé secondaire ? -->
142    <para>
143     Le comportement des clés étrangères peut être adapté très finement à
144     une application particulière. Ce tutoriel ne va pas plus loin que cet exemple simple.
145     De plus amples informations sont accessibles dans le <xref linkend="ddl"/>.
146     Une utilisation efficiente des clés étrangères améliore la
147     qualité des applications accédant aux bases de données. Il est donc
148     fortement conseillé d'apprendre à les utiliser.
149    </para>
150   </sect1>
151
152
153   <sect1 id="tutorial-transactions">
154    <title>Transactions</title>
155
156    <indexterm zone="tutorial-transactions">
157     <primary>transaction</primary>
158    </indexterm>
159
160    <para>
161     Les <firstterm>transactions</firstterm> sont un concept fondamental de tous les
162     systèmes de bases de données. Une transaction assemble plusieurs étapes
163     en une seule opération tout-ou-rien.
164     Les états intermédiaires entre les étapes ne sont pas visibles par les
165     transactions concurrentes. De plus, si un échec survient qui empêche le
166     succès de la transaction, alors aucune des étapes n'affecte la base
167     de données.
168    </para>
169
170    <para>
171     Si l'on considère, par exemple, la base de données d'une banque qui
172     contient le solde de différents comptes clients et le solde total des
173     dépôts par branches et que l'on veuille enregistrer un virement de
174     100 euros du compte d'Alice vers celui de Bob,
175     les commandes SQL peuvent ressembler à cela (après simplification)&nbsp;:
176
177 <programlisting>UPDATE comptes SET balance = balance - 100.00
178     WHERE nom = 'Alice';
179 UPDATE branches SET balance = balance - 100.00
180     WHERE nom = (SELECT nom_branche FROM comptes WHERE nom = 'Alice');
181 UPDATE comptes SET balance = balance + 100.00
182     WHERE nom = 'Bob';
183 UPDATE branches SET balance = balance + 100.00
184     WHERE nom = (SELECT nom_branche FROM comptes WHERE nom = 'Bob');</programlisting>
185    </para>
186
187    <para>
188     Ce ne sont pas les détails des commandes qui importent ici&nbsp;; le point
189     important est la nécessité de plusieurs mises à jour séparées pour
190     accomplir cette opération assez simple. Les employés de la banque
191     veulent être assurés que, soit toutes les commandes sont effectuées,
192     soit aucune ne l'est. Il n'est pas envisageable que, suite à une erreur
193     du système, Bob reçoive 100 euros qui n'ont pas été débités du compte
194     d'Alice. De la même façon, Alice ne restera pas longtemps une cliente fidèle
195     si elle est débitée du montant sans que celui-ci ne soit crédité sur le compte
196     de Bob.
197    </para>
198    <para>
199     Il est important de garantir que si quelque chose se
200     passe mal, aucune des étapes déjà exécutées n'est prise en compte. Le
201     regroupement des mises à jour au sein d'une <firstterm>transaction</firstterm>
202     apporte cette garantie.
203     Une transaction est dite <firstterm>atomique</firstterm>&nbsp;:
204     du point de vue des autres transactions, elle passe complètement ou pas du tout.
205    </para>
206
207    <para>
208     Il est également nécessaire de garantir qu'une fois la transaction
209     terminée et validée par la base de données, les transactions sont
210     enregistrées définitivement et ne peuvent être perdues, même si une
211     panne survient peu après.
212    </para>
213    <para>
214     Ainsi, si un retrait d'argent est effectué par Bob, il ne faut
215     absolument pas que le débit de son compte disparaisse avec l'apparition
216     d'une panne juste après son départ de la banque.
217    </para>
218    <para>
219     Une base de données transactionnelle garantit que toutes les mises à jour
220     faites lors d'une transaction sont stockées de manière persistante
221     (c'est-à-dire sur disque) avant que la transaction ne soit déclarée validée.
222    </para>
223
224    <para>
225     Une autre propriété importante des bases de données transactionnelles est
226     en relation étroite avec la notion de mises à jour atomiques&nbsp;: quand
227     plusieurs transactions sont lancées en parallèle, aucune d'entre elles
228     ne doit être capable de voir les modifications incomplètes effectuées
229     par les autres.
230    </para>
231    <para>
232     Ainsi, si une transaction calcule le total de toutes les branches,
233     inclure le débit de la branche d'Alice sans le crédit de la branche de
234     Bob, ou vice-versa, est une véritable erreur.
235    </para>
236    <para>
237     Les transactions doivent donc être tout-ou-rien, non seulement pour leur
238     effet persistant sur la base de données, mais aussi pour leur visibilité
239     au moment de leur exécution. Les mises à jour faites jusque-là par une
240     transaction ouverte sont invisibles aux autres transactions jusqu'à la fin
241     de celle-là. À ce moment toutes les mises à jours deviennent
242     simultanément visibles.
243    </para>
244
245    <para>
246     Sous <productname>PostgreSQL</productname>, une transaction est déclarée
247     en entourant les commandes SQL de la transaction par les commandes
248     <command>BEGIN</command> et <command>COMMIT</command>.
249    </para>
250    <para>
251     La transaction bancaire ressemble alors à ceci&nbsp;:
252
253 <programlisting>BEGIN;
254 UPDATE comptes SET balance = balance - 100.00
255     WHERE nom = 'Alice';
256 -- etc etc
257 COMMIT;</programlisting>
258    </para>
259
260    <para>
261     Si, au cours de la transaction, il est décidé de ne pas valider
262     (peut-être la banque s'aperçoit-elle que la balance d'Alice passe en
263     négatif), la commande <command>ROLLBACK</command> peut être utilisée à
264     la place de <command>COMMIT</command>. Toutes les mises à jour réalisées
265     jusque-là sont alors annulées.
266    </para>
267
268    <para>
269     En fait, <productname>PostgreSQL</productname> traite chaque instruction SQL comme
270     si elle était exécutée dans une transaction. En l'absence de commande
271     <command>BEGIN</command> explicite, chaque instruction individuelle se trouve
272     implicitement entourée d'un <command>BEGIN</command> et (en cas de succès) d'un
273     <command>COMMIT</command>.
274    </para>
275    <para>
276     Un groupe d'instructions entourées par
277     <command>BEGIN</command> et <command>COMMIT</command> est parfois appelé
278     <firstterm>bloc transactionnel</firstterm>.
279    </para>
280
281    <note>
282     <para>
283      Quelques bibliothèques clientes lancent les commandes
284      <command>BEGIN</command> et <command>COMMIT</command> automatiquement.
285      L'utilisateur bénéficie alors des effets des blocs transactionnels
286      sans les demander. Ces informations se trouvent en général dans la
287      documentation de l'interface utilisée.
288     </para>
289    </note>
290    
291    <para>
292     Il est possible d'augmenter la granularité du contrôle des instructions
293     au sein d'une transaction en utilisant des
294     <firstterm>points de retournement</firstterm>
295     (<foreignphrase>savepoint</foreignphrase>). Ceux-ci permettent d'annuler des
296     parties de la transaction tout en validant le reste.
297    </para>
298    <para>
299     Après avoir défini un point de retournement à l'aide de
300     <command>SAVEPOINT</command>, les instructions exécutées depuis ce point
301     peuvent, au besoin, être annulées avec <command>ROLLBACK TO</command>.
302     Toutes les modifications de la base de données effectuées par la
303     transaction entre le moment où le point de retournement a été défini et
304     celui où l'annulation est demandée sont annulées mais les modifications
305     antérieures à ce point sont conservées.
306    </para>
307
308    <para>
309     Le retour à un point de retournement ne l'annule pas. Il reste défini et
310     peut donc être utilisé plusieurs fois. À l'inverse, lorsqu'il n'est plus
311     nécessaire de revenir à un point de sauvegarde pariculier, il peut être
312     relâché, ce qui permet de libérer des ressources systèmes. Il faut
313     savoir toutefois que relâcher un point de retournement, ou y revenir
314     relâche tous les points de sauvegarde qui ont été définis après.
315    </para>
316
317    <para>
318     Tout ceci survient à l'intérieur du bloc de transaction, et n'est donc pas
319     visible par les autres sessions en cours sur la base de données. Si le
320     bloc est validé, et à ce moment-là seulement, toutes les actions validées
321     deviennent immédiatement visibles par les autres sessions, tandis que
322     les actions annulées ne le seront jamais.
323    </para>
324
325    <para>
326     Reconsidérant la base de données de la banque, on peut supposer vouloir
327     débiter le compte d'Alice de $100.00, somme à créditer sur le compte de Bob,
328     mais considérer plus tard que c'est le compte de Wally qu'il convient de
329     créditer. À l'aide des points de retournement, cela peut-être réalisé
330     ainsi&nbsp;:
331
332 <programlisting>BEGIN;
333 UPDATE comptes SET balance = balance - 100.00
334     WHERE nom = 'Alice';
335 SAVEPOINT mon_pointdesauvegarde;
336 UPDATE comptes SET balance = balance + 100.00
337     WHERE nom = 'Bob';
338 -- oups ... oublions ça et créditons le compte de Wally
339 ROLLBACK TO mon_pointdesauvegarde;
340 UPDATE comptes SET balance = balance + 100.00
341     WHERE nom = 'Wally';
342 COMMIT;</programlisting>
343    </para>
344
345    <para>
346     Cet exemple est bien sûr très simplifié mais de nombreux contrôles sont
347     réalisables au sein d'un bloc de transaction grâce à l'utilisation des points de
348     retournement. Qui plus est, <command>ROLLBACK TO</command> est le seul moyen
349     de regagner le contrôle d'un bloc de transaction placé dans un état
350     d'annulation par le système du fait d'une erreur. C'est plus rapide que
351     de tout annuler pour tout recommencer.
352    </para>
353   </sect1>
354
355
356   <sect1 id="tutorial-inheritance">
357    <title>Héritage</title>
358
359    <indexterm zone="tutorial-inheritance">
360     <primary>héritage</primary>
361     <secondary>inheritance</secondary>
362    </indexterm>
363
364    <para>
365     L'héritage est un concept issu des bases de données orientées objet.
366     Il ouvre de nouvelles possibilités intéressantes en conception de
367     bases de données.
368    </para>
369
370    <para>
371     Soient deux tables&nbsp;: une table <classname>villes</classname> et une
372     table <classname>capitales</classname>. Les capitales étant également
373     des villes, il est intéressant d'avoir la possibilité d'afficher
374     implicitement les capitales lorsque les villes sont listées. Un
375     utilisateur particulièrement brillant peut écrire ceci&nbsp;
376
377 <programlisting>CREATE TABLE capitales (
378   nom        text,
379   population real,
380   altitude   int,    -- (en pied)
381   etat       char(2)
382 );
383
384 CREATE TABLE non_capitales (
385   nom        text,
386   population real,
387   altitude   int     -- (en pied)
388 );
389
390 CREATE VIEW villes AS
391   SELECT nom, population, altitude FROM capitales
392     UNION
393   SELECT nom, population, altitude FROM non_capitales;</programlisting>
394
395     Cela fonctionne bien pour les requêtes, mais la mise à jour d'une même
396     donnée sur plusieurs lignes devient vite un horrible casse-tête.
397    </para>
398
399    <para>
400     Une meilleure solution peut-être&nbsp;:
401
402 <programlisting>CREATE TABLE villes (
403   nom        text,
404   population real,
405   altitude   int     -- (en pied)
406 );
407
408 CREATE TABLE capitales (
409   etat      char(2)
410 ) INHERITS (villes);</programlisting>
411    </para>
412
413    <para>
414     Dans ce cas, une ligne de <classname>capitales</classname>
415     <firstterm>hérite</firstterm> de toutes les colonnes (<structfield>nom</structfield>,
416     <structfield>population</structfield> et <structfield>altitude</structfield>) de son
417     <firstterm>parent</firstterm>, <classname>villes</classname>. Le type de la
418     colonne <structfield>nom</structfield> est <type>text</type>, un type natif
419     de <productname>PostgreSQL</productname> pour les chaînes de caractères à
420     longueur variable. Les capitales d'état ont une colonne supplémentaire,
421     <structfield>etat</structfield>, qui affiche l'état dont elles sont la
422     capitale. Sous <productname>PostgreSQL</productname>,
423     une table peut hériter de zéro à plusieurs autres tables.
424    </para>
425
426    <para>
427     La requête qui suit fournit un exemple de récupération des noms de
428     toutes les villes, en incluant les capitales des états, situées à une
429     altitude de plus de 500 pieds&nbsp;:
430
431 <programlisting>SELECT nom, altitude
432   FROM villes
433   WHERE altitude &gt; 500;</programlisting>
434
435     ce qui renvoie&nbsp;:
436
437 <screen>   nom     | altitude
438 -----------+----------
439  Las Vegas |     2174
440  Mariposa  |     1953
441  Madison   |      845
442 (3 rows)</screen>
443    </para>
444
445    <para>
446     À l'inverse, la requête qui suit récupère toutes les villes qui ne sont pas des
447     capitales et qui sont situées à une altitude d'au moins 500 pieds&nbsp;:
448
449 <programlisting>SELECT nom, altitude
450     FROM ONLY villes
451     WHERE altitude &gt; 500;</programlisting>
452
453 <screen>   nom     | altitude
454 -----------+----------
455  Las Vegas |     2174
456  Mariposa  |     1953
457 (2 rows)</screen>
458    </para>
459
460    <para>
461     Ici, <literal>ONLY</literal> avant <literal>villes</literal>
462     indique que la requête ne doit être exécutée que sur la table
463     <classname>villes</classname>, et non pas sur les tables en dessous de
464     <classname>villes</classname> dans la hiérarchie des héritages. La plupart
465     des commandes déjà évoquées &mdash;
466     <command>SELECT</command>, <command>UPDATE</command> et
467     <command>DELETE</command> &mdash; supportent cette
468     notation (<literal>ONLY</literal>).
469    </para>
470
471    <note>
472     <para>
473      Bien que l'héritage soit fréquemment utile, il n'a pas été intégré avec
474      les contraintes d'unicité et les clés étrangères, ce qui limite son utilité.
475      Voir la <xref linkend="ddl-inherit"/> pour plus de détails.
476     </para>
477    </note>
478   </sect1>
479
480
481   <sect1 id="tutorial-conclusion">
482    <title>Conclusion</title>
483  
484    <para>
485     <productname>PostgreSQL</productname> dispose d'autres fonctionnalités
486     non décrites dans ce tutoriel d'introduction orienté vers
487     les nouveaux utilisateurs de <acronym>SQL</acronym>. Ces fonctionnalités
488     sont discutées plus en détails dans le reste de ce livre.
489    </para>
490
491    <para>
492     Si une introduction plus approfondie est nécessaire, le lecteur peut
493     visiter le <ulink url="http://www.postgresql.org">site web</ulink>
494     de PostgreSQL qui fournit des liens vers d'autres ressources.
495    </para>
496   </sect1>
497  </chapter>
498
Note: See TracBrowser for help on using the browser.