継承
PostgreSQLではテーブル間で継承関係を作成できるらしいので試してみた.
似ているが若干構造が異なるテーブルがいくつかあったり,実際にモデル化すると親子関係にあるテーブルがある場合がある.このような場合に,あるテーブルの定義を継承しつつ,いくつかの付加属性を加えるといったテーブル定義ができると便利である.そこで,継承を使用したテーブル定義を試してみた.まず,親となるテーブルを作成する.
firstdb=> CREATE TABLE parent ( firstdb(> id integer primary key, firstdb(> name text not null firstdb(> ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'parent_pkey' for table 'parent' CREATEこのテーブルparentの定義を継承したテーブルchildを作成する.
firstdb=> CREATE TABLE child ( firstdb(> optional integer firstdb(> ) inherits (parent); CREATEこのように,テーブル間の継承関係を指定するには,子テーブル定義時にinheritsで使用する.
CREATE TABLE 子テーブル( ... ) inherits (親テーブル);これらのテーブルにデータを投入してみる.
firstdb=> INSERT INTO parent VALUES (1, 'hoge'); INSERT 1008327 1 firstdb=> INSERT INTO parent VALUES (2, 'fuga'); INSERT 1008328 1 firstdb=> INSERT INTO child VALUES (1, 'foo', 10); INSERT 1008332 1 firstdb=> INSERT INTO child VALUES (2, 'var'); INSERT 1008333 1このように子テーブルは親の属性id,nameを継承していることがわかる.親から継承するのは属性だけでなく,制約も継承する.たとえば以下は親の属性nameのNOT NULL制約に違反しているのでエラーになる.
firstdb=> INSERT INTO child VALUES (3); ERROR: ExecAppend: Fail to add null value in not null attribute nameまた,当然ながら親テーブルには属性optionはないので以下はエラーになる.
firstdb=> INSERT INTO parent VALUES (1, 'hoge' 10); ERROR: parser: parse error at or near "10"
継承を使用してテーブルを作成すると,テーブル定義が若干楽になるだけではなく,選択の際にも効果がある.すなわち親テーブルに対する検索の範囲は子テーブルにも及ぶ.以下では親テーブルに対してSELECTしたのに,子テーブルのレコードまで出力される例である.
firstdb=> SELECT * FROM parent; 1 | hoge 2 | fuga 1 | foo 2 | var親テーブルのみを検索範囲としたい場合は
FROM ONLY テーブル名というように,FROMの後にONLYをつける.
firstdb=> SELECT * FROM ONLY parent; 1 | hoge 2 | fuga当然ながら,子テーブルを検索範囲とした場合は親テーブルは検索範囲外である.
firstdb=> SELECT * FROM child; 1 | foo | 10 2 | var |
想像どおり,選択による検索範囲が上記のようなので,更新の場合にもそのようになる.すなわち親テーブルに対するUPDATE文なのに,子テーブルまで更新される.
firstdb=> UPDATE parent SET id=id+10; UPDATE 4 firstdb=> SELECT * FROM parent; 11 | hoge 12 | fuga 11 | foo 12 | var親テーブルのみを対象にしたい場合はやはりONLYをつける.
firstdb=> UPDATE ONLY parent SET id=id-10; UPDATE 2 firstdb=> SELECT * FROM parent; 1 | hoge 2 | fuga 11 | foo 12 | varDELETEについても同様である.
firstdb=> DELETE FROM parent WHERE id%2=0; DELETE 2 firstdb=> SELECT * from parent; 1 | hoge 11 | foo firstdb=> DELETE FROM ONLY parent WHERE id%2=1; DELETE 1 firstdb=> SELECT * from parent; 11 | foo
他のテーブルに継承されているテーブルをいきなり削除することはできない.
firstdb=> DROP TABLE parent; ERROR: Relation "child" inherits from "parent"このような場合は継承している側から順に削除する.
firstdb=> DROP TABLE child; DROP firstdb=> DROP TABLE parent; DROP

