sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでプログラムで継承されたテーブルを見つける方法は?

    このような古いバージョンの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);
    


    1. JavaからOracleプロシージャにオブジェクトを渡す

    2. SQLiteデータベースのビューを一覧表示する4つの方法

    3. PDO fetch()は失敗時に例外をスローしますか?

    4. Html2Pdfのページ分割