web-dev-qa-db-ja.com

PostgreSQLを使用してテーブル名から列属性クエリを取得する方法は?

プロジェクトがあり、テーブル名を使用してすべての列の属性(列名、位置、データ型、Not Null ?、コメント)を取得するクエリが必要です。

Column Name、Position Data Type、Not Nullの取得を達成しましたか?このクエリでは:

SELECT column_name, data_type, ordinal_position, is_nullable 
FROM information_schema."columns"
WHERE "table_name"='TABLE-NAME'

しかし、コメントが必要です!

15
Carlos Aviles

システムカタログ に対するクエリを次に示します。これは、必要なものすべてを取得する必要があります(ボーナスのプライマリキーフィールドが無料でスローされます)。

SELECT DISTINCT
    a.attnum as num,
    a.attname as name,
    format_type(a.atttypid, a.atttypmod) as typ,
    a.attnotnull as notnull, 
    com.description as comment,
    coalesce(i.indisprimary,false) as primary_key,
    def.adsrc as default
FROM pg_attribute a 
JOIN pg_class pgc ON pgc.oid = a.attrelid
LEFT JOIN pg_index i ON 
    (pgc.oid = i.indrelid AND i.indkey[0] = a.attnum)
LEFT JOIN pg_description com on 
    (pgc.oid = com.objoid AND a.attnum = com.objsubid)
LEFT JOIN pg_attrdef def ON 
    (a.attrelid = def.adrelid AND a.attnum = def.adnum)
WHERE a.attnum > 0 AND pgc.oid = a.attrelid
AND pg_table_is_visible(pgc.oid)
AND NOT a.attisdropped
AND pgc.relname = 'TABLE_NAME'  -- Your table name here
ORDER BY a.attnum;

次のような結果が返されます:

 num |    name     |             typ             | notnull |       comment       | primary_key 
-----+-------------+-----------------------------+---------+---------------------+-------------
   1 | id          | integer                     | t       | a primary key thing | t
   2 | ref         | text                        | f       |                     | f
   3 | created     | timestamp without time zone | t       |                     | f
   4 | modified    | timestamp without time zone | t       |                     | f
   5 | name        | text                        | t       |                     | f
  • num:列番号
  • name:列名
  • typ:データ型
  • notnull:列はNOT NULLとして定義されていますか
  • コメント:列に定義されているCOMMENT
  • primary_key:PRIMARY KEYとして定義されている列です
  • default:デフォルト値に使用されるコマンド
26
Chris Farmiloe

@ Chrisによる回答 に基づいて構築:

_SELECT a.attnum
      ,a.attname                            AS name
      ,format_type(a.atttypid, a.atttypmod) AS typ
      ,a.attnotnull                         AS notnull
      ,coalesce(p.indisprimary, FALSE)      AS primary_key
      ,f.adsrc                              AS default_val
      ,d.description                        AS col_comment
FROM   pg_attribute    a 
LEFT   JOIN pg_index   p ON p.indrelid = a.attrelid AND a.attnum = ANY(p.indkey)
LEFT   JOIN pg_description d ON d.objoid  = a.attrelid AND d.objsubid = a.attnum
LEFT   JOIN pg_attrdef f ON f.adrelid = a.attrelid  AND f.adnum = a.attnum
WHERE  a.attnum > 0
AND    NOT a.attisdropped
AND    a.attrelid = 'schema.tbl'::regclass  -- table may be schema-qualified
ORDER  BY a.attnum;
_

だが:

テーブル名はデータベース内で一意ではないため、システムカタログにも含まれません。名前をスキーマで修飾する必要がある場合があります。
条件として_a.attrelid = 'tbl'::regclass_を使用します。この方法で、名前として_myschema.mytbl_を渡し、明確にすることができます。この場合、_pg_class_に参加する必要はまったくありません。
また、regclassの可視性が自動的にチェックされ、pg_table_is_visible()は不要です。

主キーは複数の列にまたがることができますa.attnum = ANY(p.indkey)の_pg_index_に参加することでこれを処理します。
indkeyのタイプは_int2vecor_です。これは_int2[]_の特殊なケースで、カタログでのみ使用されます。

_psql -E_ は、この種の問題に役立ちます。

適合性

このような特殊なクエリは、メジャーバージョンの更新後に破損する可能性があります。 Postgresは、カタログテーブルの安定性を保証しません。基本的な要素が変更されることはほとんどありませんが、クエリが複雑で専門化されるほど、チャンスは大きくなります。代わりに 情報スキーマ を使用できます。これは標準化されていますが、比較的低速です。

5