Tivemos discussões sobre isso muitas vezes. O esquema de informações serve a certos propósitos. Se você conhece os catálogos do sistema, eles servem melhor para muitos propósitos , IMO. Os catálogos do sistema são a fonte real de todas as informações.
O esquema de informações fornece visualizações padronizadas que ajudam na portabilidade, principalmente nas principais versões do Postgres, porque a portabilidade em diferentes plataformas RDBMS normalmente é uma ilusão, uma vez que suas consultas são sofisticadas o suficiente para precisar procurar catálogos de sistemas. E, notavelmente, a Oracle ainda não suporta o esquema de informações.
As visualizações no esquema de informações devem passar por muitos aros para obter um formato compatível com o padrão. Isso os torna lentos, às vezes muito lentos. Compare planos e desempenho para esses objetos básicos:
EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;
A diferença é notável. Realmente depende do que você está procurando.
Seu exemplo
Para o seu exemplo SELECT * from tbl
, compare as duas consultas abaixo para esta tabela simples:
CREATE TEMP TABLE foo(
A numeric(12,3)
, b timestamp(0)
);
Usando 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()
retorna o tipo completo com todos os modificadores:
attname | type
--------+-------------------------------
a | numeric(12,3)
b | timestamp(0) without time zone
Observe também que a conversão para regclass
resolve o nome da tabela de maneira inteligente de acordo com a corrente search_path
. Também gera uma exceção se o nome não for válido. Detalhes:
Usando information_schema.columns
:
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'foo'
ORDER BY ordinal_position;
As informações são padronizadas, mas incompletas :
column_name | data_type
------------+----------------------------
a | numeric
b | timestamp without time zone
Para obter informações completas sobre o tipo de dados, é necessário considerar todas essas colunas adicionalmente:
character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision
Respostas relacionadas:
Uma lista de prós e contras , os maiores profissionais (IMO) em negrito:
Exibições de esquema de informações
- geralmente mais simples (depende)
- lento
- pré-processado, que pode ou não atender às suas necessidades
- seletivo (os usuários veem apenas objetos para os quais têm privilégios)
- em conformidade com um padrão SQL (implementado por alguns dos principais RDBMS)
- principalmente portável nas principais versões do Postgres
- não requer muito conhecimento específico sobre o Postgres
- identificadores são descritivos, longos e às vezes estranhos
Catálogos do sistema
- geralmente mais complexo (depende), mais próximo da fonte
- velozes
- completo (colunas do sistema como
oid
incluídas)
- não está em conformidade com um padrão SQL
- menos portátil nas principais versões do Postgres (mas o básico não vai mudar)
- requer conhecimento mais específico sobre o Postgres
- identificadores são concisos, menos descritivos, mas convenientemente curtos
Consulta arbitrária
Para obter a mesma lista de nomes e tipos de colunas de uma consulta, você pode usar um truque simples: CRIAR uma tabela temporária a partir da saída da consulta e, em seguida, usar as mesmas técnicas acima.
Você pode anexar LIMIT 0
, pois não precisa de dados reais:
CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT 0;
Para obter o tipo de dados de colunas individuais, você também pode usar a função pg_typeof()
:
SELECT pg_typeof(1);