1

postgres 8.3データベースを調べて、その外部キーの詳細を取得しようとしています。次のスキーマがあると想像してください。

CREATE TABLE "a" (
 "id" SERIAL PRIMARY KEY
);

CREATE TABLE "b" (
 "one" integer,
 "two" integer,
 "a_id" integer REFERENCES "a",
 PRIMARY KEY ("one", "two")
);

CREATE TABLE "c" (
 "id" SERIAL PRIMARY KEY,
 "a_id" integer REFERENCES "a",
 "b_one" integer,
 "b_two" integer,
 FOREIGN KEY ("b_one", "b_two") REFERENCES "b"
);

次に、次のようなクエリを実行したいと思います。

table | columns        | foreign table | foreign columns
--------------------------------------------------------
 b    | {a_id}         | a             | {id}
 c    | {a_id}         | a             | {id}
 c    | {b_one, b_two} | b             | {one, two}

私の最初の努力は私に質問を与えました

SELECT conrelid::regclass as "table",
       conkey as columns, 
       confrelid::regclass as "foreign table", 
       confkey as "foreign columns"
  FROM pg_constraint
 WHERE contype = 'f' ;

 table | columns | foreign table | foreign columns 
-------+---------+---------------+-----------------
 b     | {3}     | a             | {1}
 c     | {2}     | a             | {1}
 c     | {3,4}   | b             | {1,2}

ほぼそこにあります。しかし、列番号を列名に変換するための私の努力は、まだ私に望ましい結果を提供していません。グーグルは私に以下を与えました、それはまた、完全に正しくありません。

SELECT conrelid::regclass as "table",
       a.attname as columns,
       confrelid::regclass as "foreign table",
       af.attname as "foreign columns"
  FROM pg_attribute AS af,
       pg_attribute AS a,
       ( SELECT conrelid,
                confrelid,
                conkey[i] AS conkey,
                confkey[i] as confkey
           FROM ( SELECT conrelid,
                         confrelid, 
                         conkey, 
                         confkey, 
                         generate_series(1, array_upper(conkey, 1)) AS i
                    FROM pg_constraint
     WHERE contype = 'f'
         ) AS ss
       ) AS ss2
 WHERE af.attnum = confkey
   AND af.attrelid = confrelid
   AND a.attnum = conkey
   AND a.attrelid = conrelid ;

 table | columns | foreign table | foreign columns 
-------+---------+---------------+-----------------
 b     | a_id    | a             | id
 c     | a_id    | a             | id
 c     | b_one   | b             | one
 c     | b_two   | b             | two

誰かが私がその最後の一歩を踏み出すのを手伝ってもらえますか?

4

2 に答える 2

4

PeterEisentrautの答えを具体化する。postgresql 8.3の場合、array_agg関数は次のように定義できます。

CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

そして、私の希望する答えを得るための完全なクエリは次のようになります

SELECT "table",
       array_accum(columns) AS columns,
       "foreign table",
       array_accum("foreign columns") AS "foreign columns"
  FROM ( SELECT conrelid::regclass AS "table",
                a.attname as columns,
                confrelid::regclass as "foreign table",
                af.attname as "foreign columns"
           FROM pg_attribute AS af,
                pg_attribute AS a,
                ( SELECT conrelid,
                         confrelid,
                         conkey[i] AS conkey,
                         confkey[i] as confkey
                    FROM ( SELECT conrelid,
                                  confrelid, 
                                  conkey, 
                                  confkey, 
                                  generate_series(1, array_upper(conkey, 1)) AS i
                             FROM pg_constraint
              WHERE contype = 'f'
                  ) AS ss
                ) AS ss2
          WHERE af.attnum = confkey
            AND af.attrelid = confrelid
            AND a.attnum = conkey
            AND a.attrelid = conrelid
       ) AS ss3
  GROUP BY "table",
           "foreign table";

彼の答えにコメントする非標準的な方法を許してください、私はまだStackoverflowの使い方を学んでいます、そして最初にアカウントを作成しなかったのは物事を助けませんでした。

于 2009-10-17T20:34:30.613 に答える
2
SELECT table, array_agg(columns), foreign_table, array_agg(foreign_columns) FROM (your query here) GROUP BY table, foreign_table;

array_aggにはPostgreSQL8.4が必要です。以前のバージョンでは、独自のバージョンを定義できます(ドキュメントでarray_accumを探してください)。もちろん、このクエリを大きなクエリにマージすることもできますが、これで一般的な考え方が得られるはずです。

于 2009-10-14T23:13:32.447 に答える