Documentation PostgreSQL 8.0.25 | ||||
---|---|---|---|---|
Précédent | Arrière rapide | Chapitre 5. Définition des données | Avance rapide | Suivant |
Créons deux tables. La table capitales contient les capitales d'état qui sont aussi des villes. Naturellement, la table capitales doit hériter de villes.
CREATE TABLE villes ( nom text, population float, altitude int -- (in ft) ); CREATE TABLE capitales ( etat char(2) ) INHERITS (villes);
Dans ce cas, une rangée de capitales hérite de tous les attributs (nom, population, et altitude) de son parent villes. Les capitales d'état ont un attribut supplémentaire state qui donne leur état. Dans PostgreSQL, une table peut hériter de zéro tables ou plus et une requête peut référencer toutes les rangées d'une table ou toutes les rangées d'une table plus celles de ses descendants.
Note : La hiérarchie d'héritage est en fait un graphe acyclique dirigé.
Par exemple, la requête suivante cherche les noms de toutes les villes, y compris les capitales d'état, qui se situent à une altitude de plus de 500 pieds:
SELECT nom, altitude FROM villes WHERE altitude > 500;
qui retourne:
nom | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845
D'un autre côté, la requête suivante cherche toutes les villes qui ne sont pas des capitales d'état et qui sont situés à une altitude de plus de 500 pieds:
SELECT nom, altitude FROM ONLY villes WHERE altitude > 500; nom | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953
Ici, le << ONLY >> avant villes indique que la requête ne devrait être lancée que sur villes et non les tables en dessous de villes dans la hiérarchie d'héritage. Beaucoup des commandes donc nous avons déjà discuté -- SELECT, UPDATE et DELETE -- gèrent cette syntaxe << ONLY >>.
Obsolète : Dans les précédentes versions de PostgreSQL, le comportement par défaut était de ne pas inclure les tables enfants dans les requêtes. Il a été prouvé que cela amenait facilement des erreurs et est aussi en violation du standard SQL:1999. Avec l'ancienne syntaxe, pour obtenir les sous-tables, vous ajoutez * au nom de la table. Par exemple
SELECT * from villes*;Vous pouvez toujours spécifié explicitement le parcours des tables enfants en ajoutant *, ainsi qu'en spécifiant explicitement les tables enfants en écrivant << ONLY >>. Mais, depuis la version 7.1, le comportement par défaut pour un nom de table non décoré est de parcourir aussi ses tables enfants alors qu'avant ce n'était pas le comportement par défaut. Pour obtenir l'ancien comportement par défaut, initialisez l'option de configuration SQL_Inheritance à off, ainsi
SET SQL_Inheritance TO OFF;ou ajoutez une ligne dans votre fichier postgresql.conf.
Dans certain cas, vous souhaiterez savoir dans quel table provient une rangée donnée. Il y a une colonne système appelée TABLEOID dans chaque table qui peut vous donner la table d'origine:
SELECT c.tableoid, c.nom, c.altitude FROM villes c WHERE c.altitude > 500;
qui renvoie :
tableoid | name | altitude ----------+-----------+---------- 139793 | Las Vegas | 2174 139793 | Mariposa | 1953 139798 | Madison | 845
(Si vous essayez de reproduire cet exemple, vous obtiendrez probablement des OID numériques différents.) En faisant une jointure avec pg_class, vous pourrez voir les noms de tables actuelles:
SELECT p.relname, v.nom, v.altitude FROM villes v, pg_class p WHERE v.altitude > 500 and v.tableoid = p.oid;
ce qui retourne:
relname | nom | altitude -----------+-----------+---------- villes | Las Vegas | 2174 villes | Mariposa | 1953 capitales | Madison | 845
Une table peut très bien hériter de plusieurs tables. Dans ce cas-là, les colonnes de la table fille correspondent à l'union des colonnes provenant des tables parentes et des colonnes définies dans la table fille.
Une limitation sérieuse de la fonctionnalité d'héritage est que les index (incluant les contraintes uniques) et les contraintes de clés étrangères s'appliquent seulement à des tables seules, pas à leurs héritiers. Ceci est vrai pour le côté de référence et le côté référencé d'une contrainte de clé étrangère. Du coup, dans les termes de l'exemple ci-dessus :
Si nous déclarons villes.nom comme UNIQUE ou comme une PRIMARY KEY, ceci n'empêchera pas la table capitales d'avoir des lignes avec des noms dupliqués dans villes. Et ces lignes dupliquées pourraient par défaut s'afficher dans les requêtes sur villes. En fait, par défaut, capitales n'aurait pas du tout de contrainte unique et, du coup, pourrait contenir plusieurs lignes avec le même nom. Vous pouvez ajouter une contrainte unique à capitales mais ceci n'empêcherait pas la duplication comparée à villes.
De façon similaire, si nous devions spécifier que villes.nom REFERENCES une autre table, cette contrainte ne serait pas automatiquement propager à capitales. Dans ce cas, vous pourriez contourner ceci en ajoutant manuellement la même contrainte REFERENCES à capitales.
Spécifier que la colonne d'une autre table REFERENCES villes(nom) autoriserait l'autre table à contenir les noms des villes mais pas les noms des capitales. Il n'existe pas de bons contournements pour ce cas.
Ces déficiences seront probablement corrigées dans une future version mais en attendant, un soucis considérable est nécessaire dans la décision de l'utilité de l'héritage pour votre problème.
Précédent | Sommaire | Suivant |
Colonnes Systèmes | Niveau supérieur | Modification des tables |