これについて何度も議論を重ねてきました。情報スキーマは特定の目的を果たします。システムカタログの使用方法を知っていれば、ほとんどの目的に適しています、IMO。システムカタログは、すべての情報の実際のソースです。
情報スキーマは、クエリは、システムカタログを検索する必要があるために、洗練された十分にあるいったん別のRDBMSプラットフォーム間での移植は通常、錯覚であるので、そのほとんどが主要なPostgresのバージョン間での移植のヘルプ、標準のビューを提供します。そして、特に、Oracleはまだ情報スキーマをサポートしていません。
情報スキーマ内のビューは、標準に準拠した形式を実現するために多くのフープをジャンプする必要があります。これにより、それらは遅くなり、時には非常に遅くなります。これらの基本オブジェクトの計画とパフォーマンスを比較します。
EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;
その違いは顕著です。それは本当にあなたが探しているものに依存します。
あなたの例
あなたの例ではSELECT * from tbl
、この単純なテーブルについて以下の2つのクエリを比較します。
CREATE TEMP TABLE foo(
A numeric(12,3)
, b timestamp(0)
);
を使用してpg_attribute
:
SELECT attname, format_type(atttypid, atttypmod) AS type
FROM pg_attribute
WHERE attrelid = 'foo'::regclass
AND attnum > 0
AND NOT attisdropped
ORDER BY attnum;
format_type()
すべての修飾子を含む完全な型を返します。
attname | type
--------+-------------------------------
a | numeric(12,3)
b | timestamp(0) without time zone
また、キャストregclass
は、現在のに従ってテーブル名をいくぶんインテリジェントに解決することに注意してくださいsearch_path
。また、名前が無効な場合は例外が発生します。詳細:
を使用してinformation_schema.columns
:
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'foo'
ORDER BY ordinal_position;
情報は標準化されていますが、不完全です:
column_name | data_type
------------+----------------------------
a | numeric
b | timestamp without time zone
データ型の完全な情報を取得するには、これらすべての列をさらに考慮する必要があります。
character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision
関連する回答:
長所と短所、太字の最大の長所(IMO)のリスト:
情報スキーマビュー
- 多くの場合より単純です(依存します)
- スロー
- 前処理済み、ニーズに合っている場合とない場合がある
- 選択的(ユーザーは特権を持っているオブジェクトのみを表示します)
- SQL標準に準拠(主要なRDBMSのいくつかによって実装されています)
- ほとんどの主要なPostgresバージョン間で移植可能
- Postgresについての特別な知識は必要ありません
- 識別子は説明的で長く、時には扱いにくい
システムカタログ
- 多くの場合、ソースにより近い、より複雑な(依存する)
- 速い
- 完全(
oid
含まれるようなシステム列)
- SQL標準に準拠していない
- 主要なPostgresバージョン間での移植性が低い(ただし、基本は変わらない)
- Postgresについてより具体的な知識が必要
- 識別子は簡潔で、説明的ではありませんが、便利な短いです
任意のクエリ
クエリから同じ列名と型のリストを取得するには、クエリ出力から一時テーブルを作成し、上記と同じテクニックを使用するという簡単なトリックを使用できます。
LIMIT 0
実際のデータは必要ないため、を追加できます。
CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT 0;
個々の列のデータ型を取得するには、関数を使用することもできますpg_typeof()
:
SELECT pg_typeof(1);