このような古いバージョンのPostgreSQLを使用しているため、おそらくPL / PgSQL関数を使用して1を超える継承の深さを処理する必要があります。最新のPostgreSQL(または8.4)では、再帰共通テーブル式(WITH RECURSIVE
。
pg_catalog.pg_inherits
テーブルが鍵です。与えられた:
create table pp( ); -- The parent we'll search for
CREATE TABLE notpp(); -- Another root for multiple inheritance
create table cc( ) inherits (pp); -- a 1st level child of pp
create table dd( ) inherits (cc,notpp); -- a 2nd level child of pp that also inherits aa
create table notshown( ) inherits (notpp); -- Table that inherits only notpp
create table ccdd () inherits (cc,dd) -- Inheritance is a graph not a tree; join node
正しい結果はcc
を見つけます 、dd
、およびccdd
、ただしnotpp
が見つかりません またはnotshown
。
単一の深さのクエリは次のとおりです。
SELECT pg_namespace.nspname, pg_class.relname
FROM pg_catalog.pg_inherits
INNER JOIN pg_catalog.pg_class ON (pg_inherits.inhrelid = pg_class.oid)
INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
WHERE inhparent = 'pp'::regclass;
...しかし、これはcc
のみを検索します 。
マルチデプス継承の場合(つまり、tableC
tableB
を継承します tableA
を継承します )最後のループの子を次のループの親として使用して、再帰CTEまたはPL/PgSQLのループを介してそれを拡張する必要があります。
更新 :これは、特定の親から直接または間接的に継承するすべてのテーブルを再帰的に検索する必要がある8.3互換バージョンです。多重継承が使用されている場合、ツリーの任意のポイントで、ターゲットテーブルを親の1つとして持つテーブルを見つける必要があります。
CREATE OR REPLACE FUNCTION find_children(oid) RETURNS SETOF oid as $$
SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1
UNION
SELECT find_children(i.inhrelid) FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1;
$$ LANGUAGE 'sql' STABLE;
CREATE OR REPLACE FUNCTION find_children_of(parentoid IN regclass, schemaname OUT name, tablename OUT name) RETURNS SETOF record AS $$
SELECT pg_namespace.nspname, pg_class.relname
FROM find_children($1) inh(inhrelid)
INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid)
INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);
$$ LANGUAGE 'sql' STABLE;
使用法:
regress=# SELECT * FROM find_children_of('pp'::regclass);
schemaname | tablename
------------+-----------
public | cc
public | dd
public | ccdd
(3 rows)
これが再帰CTEバージョンです。これは、Pgを更新すると機能しますが、現在のバージョンでは機能しません。はるかにクリーンなIMOです。
WITH RECURSIVE inh AS (
SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE inhparent = 'pp'::regclass
UNION
SELECT i.inhrelid FROM inh INNER JOIN pg_catalog.pg_inherits i ON (inh.inhrelid = i.inhparent)
)
SELECT pg_namespace.nspname, pg_class.relname
FROM inh
INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid)
INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);