Obtendo o tipo de dados de cada coluna da tabela PostGIS?

9

Eu preciso obter os tipos de dados da coluna de todas as colunas em uma tabela, incluindo os tipos de geometria. O que eu queria saber é se existe uma função ou SQL que fornece algo como isto:

column_name | data_type
------------+--------------
gid         | integer
descr       | character varying(32)
class       | character varying(10)
area        | double precision
geom        | geometry(Polygon,3763)

De algumas respostas sobre Stackexchange e gis.stackexchange Eu sei que eu posso conseguir algumas informações com a seguinte consulta:

SELECT 
    g.column_name,
    g.data_type,
    g.character_maximum_length,
    g.udt_name,
    f.type,
    f.srid
FROM 
     information_schema.columns as g JOIN
     geometry_columns AS f 
         ON (g.table_schema = f.f_table_schema and g.table_name = f.f_table_name )
WHERE
    table_schema = 'my_schema_name' and
    table_name = 'my_table_name'

Resultado:

column_name | data_type         | character_maximum_length | udt_name | type    | srid
------------+-------------------+--------------------------+----------+---------+------
gid         | integer           |                          |          |         |
descr       | character varying | 32                       |          |         |
class       | character varying | 10                       |          |         |
area        | double precision  |                          |
geom        | USER-DEFINED      |                          | geometry | Polygon | 3763

Mas, existe uma maneira mais prática e adequada de recuperar as informações no formato necessário? Ou devo entrar no "mundo" de CASE WHENestruturas e concatenação de cadeias para reunir todos os atributos da coluna em uma única coluna nesse formato?

Meu medo é que um tipo de dados não esperado me surpreenda ao precisar de outro atributo da tabela information_schema.columns. Ou seja, na tabela de exemplo anterior, eu não usei nenhum numeric (15,2)tipo de dado, que precisaria usar outros atributos (numeric_precision e numeric_scale) para serem analisados ​​por um CASE WHEN.

Alexandre Neto
fonte

Respostas:

14

A teoria sim, embora você possa achar muito complexa.

  • Toda tabela (selecione * de pg_class) possui colunas.
  • Cada coluna (selecione * de pg_attribute) possui opcionalmente um número "typmod".
  • Para tipos com typmod (selecione * de pg_type), haverá uma função "typmodout".
  • A execução da função typmod out em um número typmod retornará uma string que pode ser concatenada com o nome do tipo para formar o tipo de assinatura legível pelo usuário com a qual você está acostumado (selecione 'numeric' || numerictypmodout (786441)) (selecione geography_typmod_out (1107460))

Mas, ei, o psql gera as strings que você deseja, se olharmos para o SQL que ele gera, talvez a resposta esteja lá.

Com certeza, há uma função mágica que pega um typeid e typmod e retorna a string mágica.

select a.attname, format_type(a.atttypid, a.atttypmod) from pg_attribute a where attname = 'geog';

Com uma associação ao pg_class, você poderá obter essas informações por tabela.

Paul Ramsey
fonte
Não recebo nenhum resultado, where attname = 'geog'mas = 'geom'funciona. Isso me dá bons resultados para os valores MultiPolygon, Point e MultiPoint, mas não vejo nada para os tipos de linha ou multilinha. São considerados polígonos?
Mhkeller # 28/18
7

Pode ser obtido usando uma simples consulta SQL.

SELECT * from information_schema.columns where table_name='mytablename'

Nilesh Khode
fonte
11
Isso funciona muito bem! E aqui está uma dica: a saída pode ser longa, então você pode querer ativar a exibição expandida no console: \pset pagerdesligar a página e \xativar a exibição expandida.
Modulitos
7

Com a ajuda de Paul Ramsey , fiz desta maneira:

SELECT a.attname as column_name, format_type(a.atttypid, a.atttypmod) AS data_type
FROM pg_attribute a
JOIN pg_class b ON (a.attrelid = b.relfilenode)
WHERE b.relname = 'my_table_name' and a.attstattarget = -1;

ATUALIZAR

Enquanto isso, criei uma função para solicitar um determinado tipo de dados da coluna

CREATE OR REPLACE FUNCTION "vsr_get_data_type"(_t regclass, _c text)
  RETURNS text AS
$body$
DECLARE
    _schema text;
    _table text;
    data_type text;
BEGIN
-- Prepare names to use in index and trigger names
IF _t::text LIKE '%.%' THEN
    _schema := regexp_replace (split_part(_t::text, '.', 1),'"','','g');
    _table := regexp_replace (split_part(_t::text, '.', 2),'"','','g');
    ELSE
        _schema := 'public';
        _table := regexp_replace(_t::text,'"','','g');
    END IF;

    data_type := 
    (
        SELECT format_type(a.atttypid, a.atttypmod)
        FROM pg_attribute a 
        JOIN pg_class b ON (a.attrelid = b.oid)
        JOIN pg_namespace c ON (c.oid = b.relnamespace)
        WHERE
            b.relname = _table AND
            c.nspname = _schema AND
            a.attname = _c
     );

    RETURN data_type;
END
$body$ LANGUAGE plpgsql;

O uso é:

SELECT vsr_get_data_type('schema_name.table_name','column_name')
Alexandre Neto
fonte
-1

se você quiser verificar o tipo de geometria, pode marcar 'udt_name' em 'INFORMATION_SCHEMA.COLUMNS' e usá-lo !:

select column_name,udt_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name =g

Haj Hossein
fonte