Eftersom du använder en så gammal version av PostgreSQL måste du förmodligen använda en PL/PgSQL-funktion för att hantera arvsdjup på> 1. På modern PostgreSQL (eller till och med 8.4) skulle du använda ett rekursivt vanligt tabelluttryck (WITH RECURSIVE
).
pg_catalog.pg_inherits
bordet är nyckeln. Givet:
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
Ett korrekt resultat kommer att hitta cc
, dd
och ccdd
, men inte hitta notpp
eller notshown
.
En enkel djup fråga är:
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;
... men det här hittar bara cc
.
För flerdjupsarv (dvs tableC
ärver tableB
ärver tableA
) du måste förlänga det via en rekursiv CTE eller en loop i PL/PgSQL, med barnen i den sista loopen som föräldrar i nästa.
Uppdatera :Här är en 8.3-kompatibel version som rekursivt bör hitta alla tabeller som ärver direkt eller indirekt från en given förälder. Om multipelarv används bör den hitta vilken tabell som helst som har måltabellen som en av sina föräldrar när som helst längs trädet.
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;
Användning:
regress=# SELECT * FROM find_children_of('pp'::regclass);
schemaname | tablename
------------+-----------
public | cc
public | dd
public | ccdd
(3 rows)
Här är den rekursiva CTE-versionen, som fungerar om du uppdaterar Pg, men som inte fungerar på din nuvarande version. Det är mycket renare 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);