¿Obtener el tipo de datos de cada columna de la tabla PostGIS?

9

Necesito obtener los tipos de datos de columna de todas las columnas en una tabla, incluidos los tipos de geometría. Lo que quería saber es si hay una función o SQL que proporcione algo como esto:

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

De algunas respuestas en stackexchange y gis.stackexchange sé que puedo obtener parte de la información con la siguiente 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

Pero, ¿hay una forma más práctica y adecuada de recuperar la información en el formato que necesito? ¿O debo ingresar al "mundo" de CASE WHENestructuras y concatenación de cadenas para reunir todos los atributos de columna en una sola columna en ese formato?

Mi temor es si un tipo de datos no esperado me sorprende al necesitar otro atributo de la tabla information_schema.columns. Es decir, en la tabla de ejemplo anterior, no usé ningún numeric (15,2)tipo de datos, que necesitaría usar otros atributos (numeric_precision y numeric_scale) para ser analizados por CASE WHEN.

Alexandre Neto
fuente

Respuestas:

14

La teoría sí, aunque podría resultarle muy compleja.

  • Cada tabla (seleccione * de pg_class) tiene columnas.
  • Cada columna (seleccione * de pg_attribute) opcionalmente tiene un número "typmod".
  • Para los tipos con typmod (seleccione * de pg_type) habrá una función "typmodout".
  • La ejecución de la función Typmod Out en un número Typmod devolverá una cadena que se puede concatenar con el nombre del tipo para formar el tipo de firma legible por el usuario al que está acostumbrado (seleccione 'numérico' || numerictypmodout (786441)) (seleccione geography_typmod_out (1107460))

Pero, oye, psql genera las cadenas que deseas, si miramos qué SQL genera, tal vez la respuesta esté ahí.

Efectivamente, hay una función mágica que toma un typeid y typmod y devuelve la cadena mágica.

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

Con una unión a pg_class, debería poder obtener esta información por tabla.

Paul Ramsey
fuente
No obtengo ningún resultado where attname = 'geog'pero = 'geom'funciona. Esto me da buenos resultados para los valores MultiPolygon, Point y MultiPoint, pero no veo nada para los tipos Line o MultiLine. ¿Se consideran los polígonos?
mhkeller
7

Se puede obtener usando una simple consulta SQL.

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

Nilesh Khode
fuente
1
¡Esto funciona muy bien! Y aquí hay un consejo: la salida puede ser bastante larga, por lo que es posible que desee habilitar la pantalla expandida en su consola: \pset pagerapagar la página y luego \xhabilitar la pantalla expandida.
modulitos
7

Con la ayuda de Paul Ramsey, lo hice de esta manera:

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;

ACTUALIZAR

Mientras tanto, he creado una función para solicitar un determinado tipo de datos de columna

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;

El uso es:

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

si desea verificar el tipo de geometría, puede marcar 'udt_name' en 'INFORMATION_SCHEMA.COLUMNS' y usarlo:

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

Haj Hossein
fuente