継承PostgreSQLは、データベース設計者にとって便利なテーブルの継承を実装しています。(SQL:1999以降は型の継承を定義していますが、ここで述べられている継承とは多くの点で異なっています。)まず例から始めましょう。市(cities)のデータモデルを作成しようとしていると仮定してください。それぞれの州にはたくさんの市がありますが、州都(capitals)は1つのみです。どの州についても州都を素早く検索したいとします。これは、2つのテーブルを作成することにより実現できます。1つは州都のテーブルで、もう1つは州都ではない市のテーブルです。継承はこの問題を解決できます。citiesから継承されるcapitalsテーブルを定義するのです。(cities);この場合、capitalsテーブルは、その親テーブルであるcitiesテーブルの列をすべて継承します。州都は1つの追加の列stateを持ち、州を表現します。PostgreSQLでは、1つのテーブルは、0以上のテーブルから継承することが可能です。問い合わせはテーブルのすべての行、またはテーブルのすべての行と継承されたテーブルのすべての行のいずれかを参照できます。後者がデフォルトの動作になります。次の問い合わせは、500フィートより上に位置しているすべての市の名前を、州都を含めて検索します。500;PostgreSQLチュートリアルからのサンプルデータ(2.1を参照してください)に対して、この問い合わせは、以下の結果を出力します。845一方、次の問い合わせは、州都ではなく500フィートより上に位置しているすべての市を検索します。1953ここでONLYキーワードは、問い合わせがcitiesテーブルのみを対象にしcities以下の継承の階層にあるテーブルは対象としないことを意味します。—がONLYキーワードをサポートしています。500;*の指定は、その動作が常にデフォルトであるため、必要ありません。この構文はデフォルトが変更可能であった古いリリースとの互換性のためにまだサポートされています。ある特定の行がどのテーブルからきたものか知りたいという場合もあるでしょう。それぞれのテーブルにはtableoidという、元になったテーブルを示すシステム列があります。500;出力は以下の通りです。845(この例をそのまま実行しても、おそらく異なる数値OIDが得られるでしょう。pg_classと結合することで、テーブルの実際の名前が分かります。p.oid;出力は以下の通りです。845同じ効果を得る別の方法は、別名型regclassを使うことで、これによりテーブルのOIDを記号的に表示します。500;継承はINSERTまたはCOPYによるデータを、継承の階層にある他のテーブルに自動的に伝播しません。この例では、次のINSERT文は失敗します。'NY');データが、どうにかしてcapitalsテーブルに入ることを期待するかもしれませんが、そのようにはなりません。INSERTは、いつも指定されたテーブルそれ自体に対してデータを挿入します。ルール(詳細は第41章を参照してください)を使用して挿入を中継できる場合もあります。ルールを使用しても上記のような場合は解決できません。citiesテーブルにstate列が含まれていないため、ルールが適用される前にコマンドが拒否されてしまうからです。INHERIT句によって明示的に指定され無い限り、その子テーブルに自動的に継承されます。他の種類の制約(一意性制約、主キー、外部キー制約)は継承されません。テーブルは1つ以上の親テーブルから継承可能です。この場合、テーブルは親テーブルで定義された列の和になります。子テーブルで宣言された列は、これらの列に追加されることになります。親テーブルに同じ名前の列がある場合、もしくは、親テーブルと子テーブルに同じ名前の列がある場合は、列が「統合」されて子テーブルではただ1つの列となります。統合されるには列は同じデータ型を持っている必要があります。異なるデータ型の場合にはエラーとなります。継承可能な検査制約と非NULL制約は、同じようなやり方で統合されます。列定義のいずれかが非NULL制約の印が付いているならば、統合された列に非NULLという印が付きます。検査制約は、同じ名前を持っている場合に統合され、それらの条件が異なる場合は統合に失敗します。TABLE文のINHERITS句を使用して、子テーブルを作成する時に確立します。他にも、互換性を持つ方法で定義済みのテーブルに新しく親子関係を付けることも可能です。TABLEのINHERIT形式を使用します。このためには、新しい子テーブルは親テーブルと同じ名前の列を持ち、その列の型は同じデータ型でなければなりません。親テーブルと同じ名前、同じ式の検査制約を持っていなければなりません。INHERIT形式を使用して、同様に継承関係を子テーブルから取り除くことも可能です。継承関係をテーブル分割(5.10を参照)に使用している場合に有用です。TABLEでLIKE句を使用することです。これは、元としたテーブルと同じ列を持つテーブルを新しく作成します。CONSTRAINTSオプションを指定すべきです。子テーブルが存在する場合親テーブルを削除することはできません。子テーブルでは、親テーブルから継承した列、または検査制約を削除することも変更することもできません。テーブルとそのすべての子テーブルを削除したければ、CASCADEオプションを付けて親テーブルを削除することが簡単な方法です(5.13を参照)。TABLEは、列データ定義と検査制約の変更を継承の階層にあるテーブルに伝えます。ここでも、他のテーブルに依存する列の削除はCASCADEオプションを使用したときのみ可能となります。TABLE時に適用される規則に従います。継承された問い合わせは、親テーブルのみアクセス権限を検査します。UPDATE権限をcitiesテーブルに付与することは、citiesテーブルを通じてアクセスする場合に、capitalsテーブルにも行の更新権限を付与することを意味します。これによりデータが親テーブルに(も)あるように見えることが保たれます。capitalsテーブルは、追加権限なしに直接更新することはできません。同様に、親テーブルの行セキュリティポリシー(5.7を参照してください)が、継承された問い合わせの時に子テーブルの行に適用されます。子テーブルのポリシー(あれば)は、問い合わせにて明示的に指定されたテーブルである時にのみ適用されます。この場合、親テーブルに紐付けられたあらゆるポリシーは無視されます。外部テーブル(5.11参照)も通常のテーブルと同様、親テーブルあるいは子テーブルとして継承の階層の一部となりえます。外部テーブルが継承の階層の一部となっている場合、外部テーブルがサポートしない操作は、その継承全体でもサポートされません。警告すべてのSQLコマンドが継承階層に対して動作できるとは限らないことに注意してください。RENAMEは含まれません)は通常、デフォルトで子テーブルを含み、また、それを除外するためのONLY記法をサポートします。データベース保守およびチューニング(例えばREINDEX、VACUUM)を行うコマンドは通常、個々の物理テーブルに対してのみ動作し、継承階層に対する再帰をサポートしません。個々のコマンドのそれぞれの動作はそのマニュアルページ(SQLコマンド)に記載されています。継承機能の重大な制限として、インデックス(一意性制約を含む)、および外部キーは、そのテーブルのみに適用され、それを継承した子テーブルには適用されないことがあります。これは外部キーの参照側、被参照側の両方について当てはまります。KEYと宣言しても、citiesテーブルの行と重複した行をcapitalsテーブル内に持つことを禁止することにはなりません。これらの重複した行はデフォルトでcitiesテーブルへの問い合わせで現れるでしょう。事実として、capitalsテーブルはデフォルトで一意性制約を持っていませんし、同一の名前の複数の行を持つことがあり得ます。capitalsテーブルに一意性制約を追加できますが、これはcitiesテーブルと比較して重複を禁止することにはなりません。REFERENCESで他のテーブルを参照するようにしても、この制約は自動的にcapitalsに引き継がれるわけではありません。この場合はcapitalsテーブルに同一のREFERENCES制約を手動で追加すれば問題を回避できます。cities(name)を指定すると、他のテーブルが市の名前を持つことはできますが、州都の名前を持つことできません。この場合は良い回避策がありません。継承の階層に対して実装されていないいくつかの機能は、宣言的パーティショニングでは実装されています。従来の継承がアプリケーションにとって有用であるかどうかを判断する際に十分注意してください。テーブルのパーティショニング。