2つのテーブルを作ってみましょう。 capitalsテーブルで保持される州都は、市(cities)でもあります。 capitalsテーブルはcitiesテーブルから継承されるべきだというのが自然な流れでしょう。
CREATE TABLE cities ( name text, population float, altitude int -- (in ft) ); CREATE TABLE capitals ( state char(2) ) INHERITS (cities);
この場合、capitalsの行は全ての属性(name(名前)、population(人口)、altitude(高度))を親テーブルのcitiesから継承します。州都は外部の属性(state(州))を持っていて、これは州を意味します。 PostgreSQLでは、テーブルは0個以上のテーブルから継承することができ、問い合わせは1つのテーブルの全ての行を参照することも、テーブルとその子孫全ての行を参照することも可能です。
注意: 継承の階層は非循環有向グラフです。
例えば、次の問い合わせは、州都を含む、高度が500フィート以上にある全ての市を見つけます。
SELECT name, altitude FROM cities WHERE altitude > 500;
出力は以下の通りです。
name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845
一方、次の問い合わせは、高度が500フィート以上にあり州都ではない全ての市を見つけます。
SELECT name, altitude FROM ONLY cities WHERE altitude > 500; name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953
ここで、citiesの前の"ONLY"は、この問い合わせはcitiesのみを対象とし、citiesを継承したテーブルは対象外としなければならないことを表します。 これまでに説明した多くのコマンド、SELECT、UPDATE や DELETE は、この"ONLY"という構文をサポートしています。
改善のために仕様変更された部分: PostgreSQLの以前のバージョンでは、デフォルトでは子テーブルにアクセスすることができませんでした。 これは間違いのもとであり、また標準SQL1999にも違反しています。 古い構文では、サブテーブルを得るためには*をテーブル名に付加していました。 例えば下記のようになります。
SELECT * from cities*;現在でも*を付加することで子テーブルのスキャンを明確に指定したり、"ONLY"を書くことで子テーブルをスキャンしないことを明確にすることができます。 しかしバージョン7.1からは、何も指定されていないテーブル名のデフォルト動作では子テーブルもスキャンします。 逆に、以前のデフォルトはそうしないことでした。 以前のデフォルト動作で作業をしたい場合はSQL_Inheritance設定オプションを無効にしてください。 以下に例を示します。
SET SQL_Inheritance TO OFF;または、postgresql.confファイルに1行追加してください。
場合によっては、ある特定の行がどのテーブルからきたものか知りたいということがあるかもしれません。 それぞれのテーブルにはtableoidという、元になったテーブルを示すシステム列があります。
SELECT c.tableoid, c.name, c.altitude FROM cities c WHERE c.altitude > 500;
出力は以下の通りです。
tableoid | name | altitude ----------+-----------+---------- 139793 | Las Vegas | 2174 139793 | Mariposa | 1953 139798 | Madison | 845
(この例を再生しても、おそらく異なる数値OIDが与えられるでしょう。) pg_classと結合することで、テーブルの実際の名前が判ります。
SELECT p.relname, c.name, c.altitude FROM cities c, pg_class p WHERE c.altitude > 500 and c.tableoid = p.oid;
出力は以下の通りです。
relname | name | altitude ----------+-----------+---------- cities | Las Vegas | 2174 cities | Mariposa | 1953 capitals | Madison | 845
テーブルは1つ以上の親テーブルから継承されることができます。その場合には、テーブルは親テーブルで定義されている列の和(さらに子テーブルで特別に宣言されているどのような列も)を持ちます。
継承機能の厳しい制限として、(一意性制約を含む)インデックス、および、外部キーは、そのテーブルのみに適用され、それを継承した子テーブルには適用されないことがあります。これは外部キーの参照側、被参照側でも同様に適用されません。 従って、上の例では
もし、cities.nameをUNIQUEまたはPRIMARY KEYと宣言しても、 citiesテーブルの行を複製した行を、capitalsテーブル内に持つことを禁止することにはなりません。 更に、これらの複製された行はデフォルトでcitiesテーブルへの問い合わせで現れるでしょう。 事実として、capitalsテーブルはデフォルトで一意性制約を持っていませんし、同一の名前の複数の行を持つことが有り得ます。 capitalsテーブルに一意性制約を追加できますが、これはcitiesテーブルと比較して複製を禁止することにはなりません。
同じように、もしcities.name REFERENCES他のテーブルとしても、 この制約は自動的にcapitalsに引き継がれるわけではありません。この場合はcapitalsテーブルに 同一のREFERENCES制約を手動で追加しなければいけません。
他のテーブルの列REFERENCES cities(name)を指定することは、他のテーブルが市の名前を持つことを 許可しますが、州都の名前を持つことを許可しません。この場合は次善策はありません。
これらの機能の不足は、今後のリリースで恐らく改善されるでしょう。しかし 継承が有用であるかどうかは、十分注意して決定してください。