テーブルの継承が使用されているPostgreSQL 8.3データベースがあります。私は、クエリを使用してベーステーブルから継承されたスキーマ名と共に、すべてのテーブルのリストを取得したいと思います。 PGSQLを使用してこれを得る方法はありますか?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)
ここでは、Pgのを更新した場合に動作します再帰CTEのバージョンは、ですが、あなたの現在のバージョンでは動作しません。はるかにクリーンなIMOです。 RECURSIVE
サポート付きのPostgreSQLのバージョンを実行している人のために
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);
次の文は、表public.base_table_name
のすべての子テーブルを取得します。私は100%確実ではないですが、それは8.3で動作するはず
select bt.relname as table_name, bns.nspname as table_schema
from pg_class ct
join pg_namespace cns on ct.relnamespace = cns.oid and cns.nspname = 'public'
join pg_inherits i on i.inhparent = ct.oid and ct.relname = 'base_table_name'
join pg_class bt on i.inhrelid = bt.oid
join pg_namespace bns on bt.relnamespace = bns.oid
。
ここで指定したベーステーブルの派生テーブルを検出機能があります。
CREATE OR REPLACE FUNCTION tables_derived_from(base_namespace name, base_table name)
RETURNS TABLE (table_schema name, table_name name, oid oid)
AS $BODY$
WITH RECURSIVE inherited_id AS
(
SELECT i.inhrelid AS oid
FROM pg_inherits i
JOIN pg_class base_t ON i.inhparent = base_t.oid
JOIN pg_namespace base_ns ON base_t.relnamespace = base_ns.oid
WHERE base_ns.nspname = base_namespace AND base_t.relname = base_table
UNION
SELECT i.inhrelid AS oid
FROM pg_inherits i
JOIN inherited_id b ON i.inhparent = b.oid
)
SELECT child_ns.nspname as table_schema, child_t.relname as table_name, child_t.oid
FROM inherited_id i
JOIN pg_class child_t ON i.oid = child_t.oid
JOIN pg_namespace child_ns ON child_t.relnamespace = child_ns.oid
ORDER BY 1, 2, 3;
$BODY$ LANGUAGE sql STABLE;
これは、1つのテーブルが複数テーブルを継承していない、と本当にそれを公開記載されているソリューションのどれもできることに注意することが重要です。彼らは片親の木を歩いているだけです。考えてみましょう:bはab_とba_継承bの両方として、間違っていたすべてので表示されないことを
CREATE TABLE a();
CREATE TABLE b();
CREATE TABLE ab_() INHERITS (a,b);
CREATE TABLE ba_() INHERITS (b,a);
CREATE TABLE ab__() INHERITS (ab_);
CREATE TABLE ba__() INHERITS (ba_);
CREATE TABLE ab_ba_() INHERITS (ab_, ba_);
CREATE TABLE ba_ab_() INHERITS (ba_, ab_);
WITH RECURSIVE inh AS (
SELECT i.inhparent::regclass, i.inhrelid::regclass, i.inhseqno FROM pg_catalog.pg_inherits i WHERE inhparent = 'a'::regclass
UNION
SELECT i.inhparent::regclass, i.inhrelid::regclass, i.inhseqno FROM inh INNER JOIN pg_catalog.pg_inherits i ON (inh.inhrelid = i.inhparent)
) SELECT * FROM inh;
inhparent | inhrelid | inhseqno
-----------+----------+----------
a | ab_ | 1
a | ba_ | 2
ab_ | ab__ | 1
ba_ | ba__ | 1
ab_ | ab_ba_ | 1
ba_ | ab_ba_ | 2
ba_ | ba_ab_ | 1
ab_ | ba_ab_ | 2
(8 rows)
お知らせ。
これを処理する "最良の"方法は、text []で、各テーブルの(配列[inhparent :: regclass]):: textを含む列であると思われます。明らかに理想的ではない、それは、少なくとも完全な継承パスを公開し、あなたが十分な体操でそれにアクセスすることを可能にするだろうがそれはあなた
inhrelid path
ab_ {"{a,b}"}
ba_ {"{b,a}"}
ab_ba_ {"{a,b}","{b,a}"}
のようなものを与えるだろう。残念ながら、それを構築するのは簡単ではありません。
もう少し簡単な代替案は、各レベルで完全な継承パスを含めるのではなく、各テーブルのみが親に指示することです。それはあなたにこれを与えるでしょう:
inhrelid parents
ab_ {a,b}
ba_ {b,a}
ab_ba_ {ab_,ba_}
- 1. PSQLの別のテーブルを継承する子テーブルを見つける方法
- 2. PostgreSQLの継承:親テーブルの引き金は継承されていますか?
- 3. インデックスを持たないテーブル(PostgreSQL)を見つける方法
- 4. .External2()によって呼び出されたコードを見つける方法は?
- 5. 継承された型ヒントをPythonで持つ方法は?
- 6. Entity Frameworkで継承を持つオブジェクトを見つけよう
- 7. プログラムによってphp.iniファイルの場所を見つける方法は?
- 8. 継承されたCSSを避ける
- 9. 反射によってオーバーロードされたメソッドを見つける方法
- 10. Cバイナリによって要求されたURLを見つける方法
- 11. @継承されたアノテーションは継承されていません
- 12. ActiveRecord - 単一テーブル継承を持つ派生クラスのメソッドを見つける
- 13. 「SWTクラスによって継承されたフィールドを持つ」オブジェクトのシリアライズ
- 14. 子によって継承されたPython RabbitMQ接続
- 15. ロードされた共有ライブラリのバージョンをプログラムで見つける方法は?
- 16. postgresqlで特定の列を持つテーブルを見つける方法
- 17. 継承されたエンティティタイプのテーブル分割?
- 18. Doctrine2、 "継承された"テーブルのマッピング
- 19. C#で継承されたクラスプロパティをオーバーライドする方法は?
- 20. C#で継承された配列を埋める方法は?
- 21. モデルバインディングで継承されたインターフェイスプロパティが見つかりません
- 22. 与えられたテーブルの子テーブルを見つける方法
- 23. JPA:継承テーブルに継承が挿入されない
- 24. コアデータ:プログラムで継承されたリレーションシップがゼロになる
- 25. PostgreSQLの2つの継承テーブルから選択
- 26. ActiveRecordのPostgreSQL継承?
- 27. winformsデザイナーで継承されたコントロールにアクセスする方法
- 28. アンインストールされたプログラムのレジストリのエントリを見つける方法は?
- 29. PostgreSQLがテーブルとインサートのトリガーを継承しました
- 30. 継承されたトランスフォームを中和する方法は?
複数の継承を示す+1。私はそれを考えなかった。 –
これは素晴らしい質問です。私はそれを実行しようとしたが、それは完璧に働いた!これを私たちの命名規則に合わせて修正しました。こんにちは、ありがとうございました。 – Arun
@Arun Glad it helped。 –