root/traduc/branches/bv803/manuel/advanced.sgml

Revision 13, 18.7 kB (checked in by gleu, 3 years ago)

Suite de l'import pour le passage CVS à SVN.

Line 
1 <!--
2 $Header: /var/lib/cvs/pgsql-fr/sgml/advanced.sgml,v 1.12 2005/07/15 06:14:19 guillaume Exp $
3 -->
4
5  <chapter id="tutorial-advanced">
6   <title>Fonctionnalités avancées</title>
7
8   <sect1 id="tutorial-advanced-intro">
9    <title>Introduction</title>
10
11    <para>
12     Dans le chapitre précédent, nous avons couvert les bases de l'utilisation
13     de <acronym>SQL</acronym> pour stocker et accéder à vos données avec
14     <productname>PostgreSQL</productname>. Nous allons maintenant aborder
15     quelques fonctionnalités avancées de <acronym>SQL</acronym>
16     simplifiant la gestion et empêchant la perte ou la corruption de vos
17     données. Enfin, nous regarderons quelques extensions de
18     <productname>PostgreSQL</productname>.
19    </para>
20
21    <para>
22     Ce chapitre se référera occasionnellement aux exemples disponibles dans le
23     <xref linkend="tutorial-sql"> pour les modifier ou les améliorer, donc il
24     serait avantageux d'avoir lu ce chapitre. Quelques exemples de ce
25     chapitre sont aussi disponibles dans <filename>advanced.sql</filename>
26     placé dans le répertoire du tutoriel. Ce fichier contient aussi quelques
27     données à charger pour l'exemple, ce qui ne sera pas répété ici.
28     (Référez-vous à la <xref linkend="tutorial-sql-intro"> pour savoir comment
29     utiliser ce fichier.)
30    </para>
31   </sect1>
32
33
34   <sect1 id="tutorial-views">
35    <title>Vues</title>
36
37    <indexterm zone="tutorial-views">
38     <primary>vue</primary>
39     <secondary>view</secondary>
40    </indexterm>
41
42    <para>
43     Référez-vous aux requêtes de la <xref linkend="tutorial-join">.
44     Supposons que la liste des enregistrements du temps et des villes soit d'un
45     intérêt particulier pour votre application mais que vous ne voulez pas
46     saisir la requête à chaque fois que vous en avez besoin. Vous pouvez créer
47     une <firstterm>vue</firstterm> avec la requête, ce qui donne un nom à la
48     requête à laquelle vous pouvez vous référer comme dans le cas d'une table
49     ordinaire.
50
51 <programlisting>
52 CREATE VIEW mavue AS
53     SELECT ville, temp_basse, temp_haute, prcp, date, emplacement
54         FROM temps, villes
55         WHERE ville = nom;
56
57 SELECT * FROM mavue;
58 </programlisting>
59    </para>
60
61    <para>
62     Avoir une utilisation libérale des vues est un aspect clé d'une bonne
63     conception des bases de données avec SQL. Les vues vous permettent
64     d'encapsuler les détails de la structure de vos tables, qui pourraient
65     changer lors de l'évolution de votre application, tout en restant
66     consistant au niveau de l'interface.
67    </para>
68
69    <para>
70     Les vues peuvent être utilisées pratiquement partout où une vraie table est
71     utilisable. Construire des vues basées sur d'autres vues n'est pas
72     inhabituel.
73    </para>
74   </sect1>
75
76
77   <sect1 id="tutorial-fk">
78    <title>Clés secondaires</title>
79
80    <indexterm zone="tutorial-fk">
81     <primary>clé secondaire</primary>
82     <secondary>foreign key</secondary>
83    </indexterm>
84
85    <indexterm zone="tutorial-fk">
86     <primary>intégrité référentielle</primary>
87     <secondary>referential integrity</secondary>
88    </indexterm>
89
90    <para>
91     Souvenez-vous des tables <classname>temps</classname> et
92     <classname>villes</classname> du <xref linkend="tutorial-sql">.
93     Considérez le problème suivant&nbsp;: vous voulez vous assurer que personne
94     n'insère de lignes dans la table <classname>temps</classname> qui ne
95     correspondraient pas à une entrée dans la table
96     <classname>villes</classname>. Ceci maintient l'<firstterm>intégrité
97     référentielle</firstterm> de vos données. Dans les systèmes de bases de
98     données simples, ceci serait implémenté (si possible) en vérifiant en
99     premier lieu que la table <classname>villes</classname> dispose bien d'un
100     enregistrement correspondant, puis en insérant ou en empêchant l'insertion
101     du nouvel enregistrement dans <classname>temps</classname>. Cette approche
102     présente un certain nombre de problèmes et n'est pas très pratique, donc
103     <productname>PostgreSQL</productname> peut s'en charger pour vous.
104    </para>
105
106    <para>
107     La nouvelle déclaration des tables ressemblerait à ceci&nbsp;:
108
109 <programlisting>
110 CREATE TABLE villes (
111         ville       varchar(80) primary key,
112         emplacement point
113 );
114
115 CREATE TABLE temps (
116         ville      varchar(80) references villes,
117         temp_haute int,
118         temp_basse int,
119         prcp       real,
120         date       date
121 );
122 </programlisting>
123
124     Maintenant, essayons d'insérer un enregistrement non valide&nbsp;:
125
126 <programlisting>
127 INSERT INTO temps VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28');
128 </programlisting>
129
130 <screen>
131 ERROR:  insert or update on table "temps" violates foreign key constraint "temps_ville_fkey"
132 DETAIL:  Key (ville)=(Berkeley) is not present in table "villes".
133 </screen>
134    </para>
135
136    <para>
137     Le comportement des clés secondaires peut être précisé très finement pour
138     votre application. Nous n'irons pas plus loin que cet exemple simple dans
139     ce tutoriel mais référez-vous simplement au <xref linkend="ddl"> pour plus
140     d'informations. Utiliser correctement les clés secondaires améliore la
141     qualité de vos applications de bases de données, donc vous êtes fortement
142     encouragé à les connaître.
143    </para>
144   </sect1>
145
146
147   <sect1 id="tutorial-transactions">
148    <title>Transactions</title>
149
150    <indexterm zone="tutorial-transactions">
151     <primary>transaction</primary>
152    </indexterm>
153
154    <para>
155     Les <firstterm>transactions</> sont un concept fondamental de tous les
156     systèmes de bases de données. Le point essentiel d'une transaction est
157     qu'il assemble plusieurs étapes en une seule opération tout-ou-rien.
158     Les états intermédiaires entre les étapes ne sont pas visibles pour les
159     autres transactions concurrentes, et si un échec survient empêchant la
160     transaction de bien se terminer, alors aucune des étapes n'affecte la base
161     de données.
162    </para>
163
164    <para>
165     Par exemple, considérez la base de données d'une banque qui contiendrait la
166     balance pour différents comptes clients, ainsi que les balances du total du
167     dépôt par branches. Supposez que nous voulons enregistrer un virement de
168     100 euros du compte d'Alice vers celui de Bob. En simplifiant énormément,
169     les commandes SQL pour ceci ressembleraient à ça
170
171 <programlisting>
172 UPDATE comptes SET balance = balance - 100.00
173     WHERE nom = 'Alice';
174 UPDATE branches SET balance = balance - 100.00
175     WHERE nom = (SELECT nom_branche FROM comptes WHERE nom = 'Alice');
176 UPDATE comptes SET balance = balance + 100.00
177     WHERE nom = 'Bob';
178 UPDATE branches SET balance = balance + 100.00
179     WHERE nom = (SELECT nom_branche FROM comptes WHERE nom = 'Bob');
180 </programlisting>
181    </para>
182
183    <para>
184     Les détails de ces commandes ne sont pas importants ici&nbsp;; le point
185     important est que cela nécessite plusieurs mises à jour séparées pour
186     accomplir cette opération assez simple. Les employés de la banque
187     voudront être assurés que soit toutes les commandes sont effectuées
188     soit aucune ne l'est. Il ne serait pas acceptable que, suite à une erreur
189     du système, Bob reçoive 100 euros qui n'ont pas été débités du compte
190     d'Alice. De la même façon, Alice ne restera pas longtemps une cliente si
191     elle est débitée du montant sans que celui-ci ne soit crédité sur le compte
192     de Bob. Nous avons besoin d'une garantie comme quoi si quelque chose se
193     passe mal, aucune des étapes déjà exécutées ne prendra effet. Grouper les
194     mises à jour en une <firstterm>transaction</> nous donne cette garantie.
195     Une transaction est dite <firstterm>atomique</>&nbsp;: du point de vue des autres
196     transactions, cela se passe complètement ou pas du tout.
197    </para>
198
199    <para>
200     Nous voulons aussi la garantie qu'une fois une transaction terminée et
201     validée par le système de base de données, les modifications seront
202     enregistrées de façon permanente et ne seront pas perdues même si un arrêt
203     brutal arrive peu après. Par exemple, si nous enregistrons un retrait
204     d'argent par Bob, nous ne voulons surtout pas que le débit de son compte
205     disparaisse lors d'un crash à sa sortie de la banque. Une base de données
206     transactionnelle garantit que toutes les mises à jour faites lors d'une
207     transaction sont enregistrées dans un stockage permanent (c'est-à-dire sur
208     disque) avant que la transaction ne soit validée.
209    </para>
210
211    <para>
212     Une autre propriété importante des bases de données transactionnelles est
213     en relation étroite avec la notion de mises à jour atomiques&nbsp;: quand
214     de multiples transactions sont lancées en parallèle, chacune d'entre elles
215     ne doit pas être capable de voir les modifications incomplètes faites
216     par les autres. Par exemple, si une transaction est occupée à calculer le
217     total de toutes les branches, il ne serait pas bon d'inclure le débit de la
218     branche d'Alice sans le crédit de la branche de Bob, ou vice-versa.
219     Donc, les transactions doivent être tout-ou-rien non seulement pour leur
220     effet permanent sur la base de données, mais aussi pour leur visibilité
221     au moment de leur exécution. Les mises à jour faites ainsi par une
222     transaction ouverte sont invisibles aux autres transactions jusqu'à la fin
223     de celle-ci, moment qui rendra visible toutes les mises à jours
224     simultanément.
225    </para>
226
227    <para>
228     Avec <productname>PostgreSQL</>, une transaction est réalisée en entourant
229     les commandes SQL de la transaction avec les commandes <command>BEGIN</>
230     et <command>COMMIT</>. Donc, notre transaction pour la banque ressemblera à
231     ceci
232
233 <programlisting>
234 BEGIN;
235 UPDATE comptes SET balance = balance - 100.00
236     WHERE nom = 'Alice';
237 -- etc etc
238 COMMIT;
239 </programlisting>
240    </para>
241
242    <para>
243     Si, au cours de la transaction, nous décidons que nous ne voulons pas
244     valider (peut-être nous sommes-nous aperçu que la balance d'Alice devenait
245     négative), nous pouvons envoyer la commande <command>ROLLBACK</> au lieu de
246     <command>COMMIT</>, et toutes nos mises à jour jusqu'à maintenant seront
247     annulées.
248    </para>
249
250    <para>
251     En fait, <productname>PostgreSQL</> traite chaque instruction SQL comme
252     étant exécutée dans une transaction. Si vous ne lancez pas une commande
253     <command>BEGIN</>, alors chaque instruction individuelle se trouve
254     enveloppée avec un <command>BEGIN</> et (en cas de succès) un
255     <command>COMMIT</> implicites.  Un groupe d'instructions entouré par un
256     <command>BEGIN</> et un <command>COMMIT</> est quelque fois appelé un
257     <firstterm>bloc transactionnel</>.
258    </para>
259
260    <note>
261     <para>
262      Quelques bibliothèques clients lancent les commandes <command>BEGIN</> et
263      <command>COMMIT</> automatiquement, de façon à ce que vous bénéficiiez des
264      effets des blocs transactionnels sans les demander. Vérifiez la
265      documentation de l'interface que vous utilisez.
266     </para>
267    </note>
268    
269    <para>
270     Il est possible de contrôler les instructions dans une transaction d'une
271     façon plus granulaire avec l'utilisation des <firstterm>points de
272     sauvegarde</>. Les points de sauvegarde vous permettent d'annuler des
273     parties de la transaction tout en validant le reste. Après avoir défini un
274     point de sauvegarde avec <command>SAVEPOINT</>, vous pouvez, si nécessaire,
275     annuler jusqu'au point de sauvegarde avec <command>ROLLBACK TO</>. Toutes
276     les modifications de la transaction dans la base de données entre le moment
277     où le point de sauvegarde est défini et celui où l'annulation est demandée
278     sont annulées mais les modifications antérieures au point de sauvegarde sont
279     conservées.
280    </para>
281
282    <para>
283     Après avoir annulé jusqu'à un point de sauvegarde, il reste défini, donc
284     vous pouvez de nouveau annuler plusieurs fois et rester au même point. Par
285     contre, si vous êtes sûr de ne plus avoir besoin d'annuler jusqu'à un point
286     de sauvegarde particulier, il peut être libéré pour que le système puisse
287     récupérer quelques ressources. Gardez à l'esprit que libérer un point de
288     sauvegarde ou annuler les opérations jusqu'à ce point de sauvegarde libérera
289     tous les points de sauvegarde définis après lui.
290    </para>
291
292    <para>
293     Tout ceci survient à l'intérieur du bloc de transaction, donc ce n'est pas
294     visible par les autres sessions de la base de données. Quand et si vous
295     validez le bloc de transaction, les actions validées deviennent visibles en
296     un seul coup aux autres sessions, alors que les actions annulées ne
297     deviendront jamais visibles.
298    </para>
299
300    <para>
301     Rappelez-vous la base de données de la banque. Supposons que nous débitons
302     le compte d'Alice de $100.00, somme que nous créditons au compte de Bob,
303     pour trouver plus tard que nous aurions dû créditer le compte de Wally. Nous
304     pouvons le faire en utilisant des points de sauvegarde comme ceci&nbsp;:
305
306 <programlisting>
307 BEGIN;
308 UPDATE comptes SET balance = balance - 100.00
309     WHERE nom = 'Alice';
310 SAVEPOINT mon_pointdesauvegarde;
311 UPDATE comptes SET balance = balance + 100.00
312     WHERE nom = 'Bob';
313 -- oups ... oublions ça et créditons le compte de Wally
314 ROLLBACK TO mon_pointdesauvegarde;
315 UPDATE comptes SET balance = balance + 100.00
316     WHERE nom = 'Wally';
317 COMMIT;
318 </programlisting>
319    </para>
320
321    <para>
322     Cet exemple est bien sûr très simplifié mais il y a beaucoup de contrôle
323     possible dans un bloc de transaction grâce à l'utilisation des points de
324     sauvegarde. De plus, <command>ROLLBACK TO</> est le seul moyen pour regagner
325     le contrôle d'un bloc de transaction qui a été placé dans un état
326     d'annulation par le système à cause d'une erreur, plutôt que de tout annuler
327     et de tout recommencer.
328    </para>
329   </sect1>
330
331
332   <sect1 id="tutorial-inheritance">
333    <title>Héritage</title>
334
335    <indexterm zone="tutorial-inheritance">
336     <primary>héritage</primary>
337     <secondary>inheritance</secondary>
338    </indexterm>
339
340    <para>
341     L'héritage est un concept provenant des bases de données orientées objet.
342     Il ouvre de nouvelles possibilités intéressantes dans la conception de
343     bases de données.
344    </para>
345
346    <para>
347     Créons deux tables&nbsp;: une table <classname>villes</classname> et une
348     table <classname>capitales</classname>. Naturellement, les capitales sont
349     aussi des villes, donc vous voulez un moyen pour afficher implicitement les
350     capitales lorsque vous listez les villes. Si vous êtes réellement
351     intelligent, vous pourriez inventer ceci&nbsp;:
352
353 <programlisting>
354 CREATE TABLE capitales (
355   nom        text,
356   population real,
357   altitude   int,    -- (en pied)
358   etat       char(2)
359 );
360
361 CREATE TABLE non_capitales (
362   nom        text,
363   population real,
364   altitude   int     -- (en pied)
365 );
366
367 CREATE VIEW villes AS
368   SELECT nom, population, altitude FROM capitales
369     UNION
370   SELECT nom, population, altitude FROM non_capitales;
371 </programlisting>
372
373     Ceci fonctionne bien pour les requêtes, mais c'est horrible lorsque vous
374     avez besoin de mettre à jour plusieurs lignes par exemple.
375    </para>
376
377    <para>
378     Voici une meilleure solution&nbsp;:
379
380 <programlisting>
381 CREATE TABLE villes (
382   nom        text,
383   population real,
384   altitude   int     -- (en pied)
385 );
386
387 CREATE TABLE capitales (
388   etat      char(2)
389 ) INHERITS (villes);
390 </programlisting>
391    </para>
392
393    <para>
394     Dans ce cas, une ligne de <classname>capitales</classname>
395     <firstterm>hérite</firstterm> de toutes les colonnes (<structfield>nom</>,
396     <structfield>population</> et <structfield>altitude</>) de son
397     <firstterm>parent</firstterm>, <classname>villes</classname>. Le type de la
398     colonne <structfield>nom</structfield> est <type>text</type>, un type natif
399     de <productname>PostgreSQL</productname> pour les chaînes de caractères à
400     longueur variable. Les capitales d'état ont une colonne supplémentaire,
401     etat, qui affiche leur état. Dans <productname>PostgreSQL</productname>,
402     une table peut hériter d'aucune ou de plusieurs autres tables.
403    </para>
404
405    <para>
406     Par exemple, la requête suivante trouve les noms de toutes les villes, en
407     incluant les capitales des états, situées à une altitude de plus de 500
408     pieds&nbsp;:
409
410 <programlisting>
411 SELECT nom, altitude
412   FROM villes
413   WHERE altitude &gt; 500;
414 </programlisting>
415
416     ce qui renvoie&nbsp;:
417
418 <screen>
419    nom     | altitude
420 -----------+----------
421  Las Vegas |     2174
422  Mariposa  |     1953
423  Madison   |      845
424 (3 rows)
425 </screen>
426    </para>
427
428    <para>
429     Autrement, la requête suivante trouve toutes les villes qui ne sont pas des
430     capitales et qui sont situées à une altitude d'au moins 500 pieds&nbsp;:
431
432 <programlisting>
433 SELECT nom, altitude
434     FROM ONLY villes
435     WHERE altitude &gt; 500;
436 </programlisting>
437
438 <screen>
439    nom     | altitude
440 -----------+----------
441  Las Vegas |     2174
442  Mariposa  |     1953
443 (2 rows)
444 </screen>
445    </para>
446
447    <para>
448     Ici, <literal>ONLY</literal> avant <literal>villes</literal>
449     indique que la requête ne doit être lancée que sur la table
450     <classname>villes</classname>, et non pas sur les tables sous
451     <classname>villes</classname> suivant la hiérarchie des héritages. La plupart
452     des commandes dont nous avons déjà discutées &mdash;
453     <command>SELECT</command>, <command>UPDATE</command> et
454     <command>DELETE</command> &mdash; supportent cette
455     notation (<literal>ONLY</literal>).
456    </para>
457
458    <note>
459     <para>
460      Bien que l'héritage soit fréquemment utile, il n'a pas été intégré avec
461      les contraintes uniques ou les clés étrangères, ce qui limite leur utilité.
462      Voir <xref linkend="ddl-inherit"> pour plus de détails.
463     </para>
464    </note>
465   </sect1>
466
467
468   <sect1 id="tutorial-conclusion">
469    <title>Conclusion</title>
470  
471    <para>
472     <productname>PostgreSQL</productname> a bien plus de fonctionnalités que
473     celles aperçues lors de ce tutoriel d'introduction, qui a été orienté vers
474     les nouveaux utilisateurs de <acronym>SQL</acronym>. Ces fonctionnalités
475     sont discutées avec plus de détails dans le reste de ce livre.
476    </para>
477
478    <para>
479     Si vous sentez que vous avez besoin d'une introduction plus approfondie,
480     merci de visiter le <ulink url="http://www.postgresql.org">site web
481     PostgreSQL</ulink> pour des liens vers d'autres ressources.
482    </para>
483   </sect1>
484  </chapter>
485
486 <!-- Keep this comment at the end of the file
487 Local variables:
488 mode:sgml
489 sgml-omittag:nil
490 sgml-shorttag:t
491 sgml-minimize-attributes:nil
492 sgml-always-quote-attributes:t
493 sgml-indent-step:1
494 sgml-indent-data:t
495 sgml-parent-document:nil
496 sgml-default-dtd-file:"./reference.ced"
497 sgml-exposed-tags:nil
498 sgml-local-catalogs:("/usr/lib/sgml/catalog")
499 sgml-local-ecat-files:nil
500 End:
501 -->
Note: See TracBrowser for help on using the browser.