Consulta para retornar nomes de colunas de saída e tipos de dados de uma consulta, tabela ou exibição


21

Existe uma consulta ou comando do PostgreSQL que retorna os nomes e os tipos de campo de uma consulta, tabela ou exibição?

Por exemplo, uma solução se aplicada a uma simples consulta SELECT como SELECT * from persondeve retornar uma lista como:

Column Name   | Column Type
===========================
First Name    | character
Last Name     | character
Age           | integer
Date of Birth | date

Procurei as information_schemavisualizações descritas em uma resposta abaixo e ela parece abranger muito bem as tabelas, e suspeito que também abranja as visualizações, mas ainda não a verifiquei.

A última é qualquer consulta SELECT arbitrária, mas válida, por exemplo, envolvendo JOINS, UNIONSetc, no banco de dados. Existe um procedimento interno ou outro procedimento ou script armazenado que possa retornar o mesmo para qualquer QUERY válido?

Estou desenvolvendo um programa que cria dados e formulários de consulta e as informações são necessárias para validação de dados e execução de funções nos dados retornados.


Obviamente, não existe um "comando" único, mas existem várias maneiras de recuperar informações dos catálogos do sistema. Faça uma pergunta específica , adicione um exemplo e o que você espera em troca e nos dê uma idéia sobre a intenção por trás disso.
Erwin Brandstetter

1
A razão da simplicidade é que, no que diz respeito aos clientes SELECT, consultas, ou seja, consultas que não definem ou manipulam dados, seja em tabelas, visualizações ou outras consultas, retornam linhas e colunas de dados; portanto, o PostgreSQL deve poder retornar um lista dos nomes das colunas e seus tipos de dados. As information_schemavisualizações mencionadas abaixo nas respostas parecem respondê-la em tabelas e visualizações. Consultas SELECT arbitrárias são a fronteira final. Eu vou editar a resposta para explicar melhor
vfclists

Respostas:


22

Esquema de informações x catálogos do sistema

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 regclassresolve 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 oidincluí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);

Muito obrigado. Eu estive olhando como obter o tipo de dados da coluna em pg_attribute por algum tempo e acabei de encontrar este post. Aprecie sua postagem.
Melinda

Isso é útil em geral, mas não responde à pergunta original sobre como obter informações sobre os tipos de dados das colunas que uma instrução SELECT fornece. Era não sobre as colunas de pontos de vista ou tabelas, o que, reside naturalmente nos catálogos do sistema e são mostrados no esquema de informações também.
Holger Jakobs 13/09


2

Se você tem acesso ao pg_catalog e usa o PgAdmin3, recomendo vivamente uma solução que encontrei no blog Valentine's Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields). html ). É uma macro PgAdmin3 que pode ser acessada com um atalho para exibir a definição de um nome de tabela selecionado.

select quote_ident(nspname) || '.' || quote_ident(relname) as table_name, 
       quote_ident(attname) as field_name, 
       format_type(atttypid,atttypmod) as field_type, 
       case when attnotnull then ' NOT NULL' else '' end as null_constraint,
       case when atthasdef then 'DEFAULT ' || 
                                ( select pg_get_expr(adbin, attrelid) 
                                    from pg_attrdef 
                                   where adrelid = attrelid and adnum = attnum )::text else ''
       end as dafault_value,
       case when nullif(confrelid, 0) is not null
            then confrelid::regclass::text || '( ' || 
                 array_to_string( ARRAY( select quote_ident( fa.attname ) 
                                           from pg_attribute as fa 
                                          where fa.attnum = ANY ( confkey ) 
                                            and fa.attrelid = confrelid
                                          order by fa.attnum 
                                        ), ','
                                 ) || ' )'
            else '' end as references_to
  from pg_attribute 
       left outer join pg_constraint on conrelid = attrelid 
                                    and attnum = conkey[1] 
                                    and array_upper( conkey, 1 ) = 1,
       pg_class, 
       pg_namespace
 where pg_class.oid = attrelid
   and pg_namespace.oid = relnamespace
   and pg_class.oid = btrim( '$SELECTION$' )::regclass::oid
   and attnum > 0
   and not attisdropped
 order by attrelid, attnum;

Funciona como um encanto e extremamente útil.


1

Use as information_schemavisualizações , elas são padrão SQL e contêm as informações que você deseja.

Você também pode acessar diretamente pg_class, pg_attribute, etc, mas isso é portável e muitas vezes fiddlier; você pode precisar de funções auxiliares comooidvectortypes , pg_get_function_arguments, etc para algumas coisas.

Se você quiser ver como psqlexecuta algo como \dt, execute psql -E- ele imprimirá a consulta. No entanto, geralmente é melhor usar o information_schemase ele atender às suas necessidades.


1

Isso pode ser muito simples, mas o pgAdmin4 mostra os tipos de campo nos resultados da saída. As outras soluções acima são provavelmente mais elegantes, mas quando só preciso de uma resposta rápida, acho que a GUI de consulta do pgAdmin4 funciona muito bem. Tentar descobrir o tipo de campo calculado retornado por uma exibição ou função pode ser complicado.

insira a descrição da imagem aqui


É muito bom que o pgAdmin4 faça isso, mas como faz isso? Podemos descobrir sem escanear todo o código fonte do PgAdmin4?
Holger Jakobs 13/09
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.