前も似たことを書いた気がしますが、たぶん無駄があったので。一つのSELECT文で汎用的に(カンマで連結とか、1列ずつ改行とか)全列名を出力。PostgreSQL 9.5.2で動作確認。データ型を付ける例も後半にあります。
↓ 基本形。DELIMITERが列名間の区切り。最後のto_regclassの引数にテーブル名を、必要ならスキーマ名も付けて渡します。1行目のorder byにdescを付けると(使う場面が思い浮かばないけど)列が逆順に。
select string_agg(quote_ident(attname), 'DELIMITER' order by attnum)
from pg_attribute
where attnum > 0
and attrelid = to_regclass('[SCHEMA_NAME.]TABLE_NAME');
↓ 使用例。一つ目がカンマ区切り、二つ目が改行で区切り。
select string_agg(quote_ident(attname), ',' order by attnum)
from pg_attribute
where attnum > 0
and attrelid = to_regclass('pg_tables');
+----------------------------------------------------------------------------------------+
| string_agg |
+----------------------------------------------------------------------------------------+
| schemaname,tablename,tableowner,tablespace,hasindexes,hasrules,hastriggers,rowsecurity |
+----------------------------------------------------------------------------------------+
(1 row)
select string_agg(quote_ident(attname), e'\n' order by attnum)
from pg_attribute
where attnum > 0
and attrelid = to_regclass('pg_tables');
+-------------+
| string_agg |
+-------------+
| schemaname +|
| tablename +|
| tableowner +|
| tablespace +|
| hasindexes +|
| hasrules +|
| hastriggers+|
| rowsecurity |
+-------------+
(1 row)
列名にquote_identを付けているので、列名に英大文字や日本語などがあれば自動的に二重引用符で括られます。
例えば列数が多いテーブル/ビューで、全部に近い列をクエリに書かなきゃいけない時、上のカンマ区切り出力から不要な列だけ消すと楽。本当はそんなクエリ回避できるのが一番ですけど。
一方、テーブル定義に流用するとかの場合はデータ型も要るので ↓ こんな風に。
select string_agg(quote_ident(attname) || ' '
|| format_type(atttypid, null), 'DELIMITER'
order by attnum)
from pg_attribute
where attnum > 0
and attrelid = to_regclass('[SCHEMA_NAME.]TABLE_NAME');
↓ 使用例。列名が多いシステムカタログpg_classです。
select string_agg(quote_ident(attname) || ' '
|| format_type(atttypid, null), e',\n'
order by attnum)
from pg_attribute
where attnum > 0
and attrelid = to_regclass('pg_class');
+------------------------------+
| string_agg |
+------------------------------+
| relname name, +|
| relnamespace oid, +|
| reltype oid, +|
| reloftype oid, +|
| relowner oid, +|
| relam oid, +|
| relfilenode oid, +|
| reltablespace oid, +|
| relpages integer, +|
| reltuples real, +|
| relallvisible integer, +|
| reltoastrelid oid, +|
| relhasindex boolean, +|
| relisshared boolean, +|
| relpersistence "char", +|
| relkind "char", +|
| relnatts smallint, +|
| relchecks smallint, +|
| relhasoids boolean, +|
| relhaspkey boolean, +|
| relhasrules boolean, +|
| relhastriggers boolean, +|
| relhassubclass boolean, +|
| relrowsecurity boolean, +|
| relforcerowsecurity boolean,+|
| relispopulated boolean, +|
| relreplident "char", +|
| relfrozenxid xid, +|
| relminmxid xid, +|
| relacl aclitem[], +|
| reloptions text[] |
+------------------------------+
(1 row)
psqlの\dコマンドでも同等以上の情報が得られますが ↓ 列名とデータ型が別々になっている等、テーブル定義に使うには手間なので今回クエリにしてみました。とは言えクエリも結構長いので、できればpsqlから簡単に(テーブルだけ渡せば済むように)使いたい。明日はそれについて書きます。
\d pg_class
Table "pg_catalog.pg_class"
+---------------------+-----------+-----------+
| Column | Type | Modifiers |
+---------------------+-----------+-----------+
| relname | name | not null |
| relnamespace | oid | not null |
| reltype | oid | not null |
| reloftype | oid | not null |
| relowner | oid | not null |
| relam | oid | not null |
| relfilenode | oid | not null |
| reltablespace | oid | not null |
| relpages | integer | not null |
| reltuples | real | not null |
...