Héritage de tables dans postgresql

Publié le par greg

Gérer l'héritage d'objets dans une base de données est un problème que beaucoup de développeurs connaissent. Imaginons que nous sommes en train d'écrire une application de gestion de bibliothèque (le cas d'école). Vous avez une table  qui va regrouper les ouvrages c'est à dire l'ensemble des publications que possède votre bibliothèque. Mais cette table généraliste va forcemment ne pas avoir des attributs spécifiques à certains types d'ouvrages commes des livres de poche, des bédés ou des magazines.

Illustrons ce cas concret avec 2 bases de données : une base de données «classique» appelons la «myXsql» et une base postgresql.

Avec la base classique, nous allons avoir un schéma avec une jointure  :

heritage01.png
 Cette solution est compliquée car nous gérons une clé primaire par table, une clé étrangère dans chaque table fille pour faire le lien avec l'ouvrage correspondant.

Au niveau du modèle objet, cela se traduit tant bien que mal. Nous avons en effet plusieurs façons de gérer cela. La  façon SQL de penser donne que l'objet ouvrage est un attribut de mon objet magazine ou livre de poche et que l'on regroupe tout dans une jointure.

La  façon objet est de faire étendre la classe ouvrage aux classes magazines et livre_poche pour que chaque couche gère sa table grace à l'appel à la méthode parent. Du coup, on double le nombre de requêtes (une pour chaque table).

Postgresql propose la fonctionnalité de l'héritage de table qui va gérer tout cela pour nous. Notre schéma de base de données devient très simple.

Pour bien illuster cet exemple, voici la ligne de création de la table magazine :
CREATE TABLE ouvrage (id SERIAL, created_at TIMESTAMP NOT NULL);

CREATE TABLE magazine (titre VARCHAR(255) NOT NULL, published_at TIMESTAMP NOT NULL, number INTEGER) INHERITS (ouvrage);
CREATE TABLE livre_poche (isbn VARCHAR(255) NOT NULL, title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL) INHERITS (ouvrage);
Regardons le résultat :
test=$ d ouvrage
                                     Table "public.ouvrage"
   Column     |            Type              |                      Modifiers
----------------+-------------------------+------------------------------------------------------
 id                  | integer                     | not null default nextval('ouvrage_id_seq'::regclass)
 created_at  | timestamp               | not null
et nos tables étendues :
test=$ d magazine
                                      Table "public.magazine"
    Column    |            Type             |                      Modifiers
----------------+-----------------------------+------------------------------------------------------
 id                  | integer                     | not null default nextval('ouvrage_id_seq'::regclass)
 created_at  | timestamp               | not null
 titre               | character varying(255)      | not null
 published_at | timestamp            | not null
 number        | integer                     |
Inherits: ouvrage
test=$ d livre_poche
                                   Table "public.livre_poche"
   Column   |            Type             |                      Modifiers
--------------+-------------------------+------------------------------------------------------
 id                | integer                    | not null default nextval('ouvrage_id_seq'::regclass)
 created_at | timestamp             | not null
 isbn            | character varying(255)      | not null
 title             | character varying(255)      | not null
 author        | character varying(255)      | not null
Inherits: ouvrage

Je sens votre curiosimètre en plein effervesence et pour cause, nous n'avons pas eu à déclarer de clé primaire sur les tables magazine et livre_poche car nous héritons de celle d'ouvrage ! Un exemple valant mieux que tartines d'explications, lançons nous :

test=$ ALTER TABLE ouvrage ALTER COLUMN created_at SET DEFAULT now();
ALTER TABLE
test$ d magazine
                                      Table "public.magazine"
    Column    |            Type             |                      Modifiers
----------------+-----------------------------+------------------------------------------------------
 id                  | integer                     | not null default nextval('ouvrage_id_seq'::regclass)
 created_at  | timestamp               | not null default now()
 titre               | character varying(255)      | not null
 published_at | timestamp            | not null
 number        | integer                     |
Inherits: ouvrage

Ce premier exemple se passe de commentaire. Ajoutons maintenant un magazine :
test=$ INSERT INTO magazine (titre, published_at, number) VALUES ('art et decoration', TIMESTAMP '2008/01/01', 144);
INSERT 0 1
test=$ SELECT * FROM magazine ;
 id |         created_at                           |       titre                 |    published_at             | number
----+----------------------------------------+----------------------+------------------------------+--------
  1 | 2008-03-09 12:12:07.787696 | art et decoration | 2008-01-01 00:00:00 |    144
(1 row)

test=$ SELECT * FROM ouvrage;
 id |         created_at
----+------------------------------
  1 | 2008-03-09 12:12:07.787696
(1 row)
test=$ SELECT * FROM livre_poche ;
 id | created_at | isbn | title | author
----+--------------+-------+-----+--------
(0 rows)







Publicité

Publié dans postgresql

Pour être informé des derniers articles, inscrivez vous :
Commenter cet article