Мы много раз обсуждали это. Информационная схема служит определенным целям. Если вы знакомы с системными каталогами, то они лучше всего подходят для большинства целей , IMO. Системные каталоги являются актуальным источником всей информации.
Информация схема обеспечивает стандартизированное мнение , которые помогают с мобильностью, в основном через крупную Postgres версию, потому что портативность на разные платформах RDBMS , как правило , является иллюзией , как только ваши запросы достаточно сложные для необходимости искать системные каталоги. И, в частности, Oracle все еще не поддерживает информационную схему.
Представления в информационной схеме должны перепрыгивать через множество циклов, чтобы получить формат, соответствующий стандарту. Это делает их медленными, иногда очень медленными. Сравните планы и производительность для этих основных объектов:
EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;
Разница замечательная. Это действительно зависит от того, что вы ищете.
Ваш пример
Для вашего примера SELECT * from tbl
сравните два запроса ниже для этой простой таблицы:
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
Связанные ответы:
Список плюсов и минусов , самые большие плюсы (ИМО) выделены жирным шрифтом:
Представления информационной схемы
- часто проще (зависит)
- медленный
- предварительно обработанный, который может или не может удовлетворить ваши потребности
- выборочный (пользователи видят только те объекты, для которых у них есть привилегии)
- соответствует стандарту SQL (который реализуется некоторыми основными СУБД)
- в основном портативные через основные версии 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);