Vous obtenez le type de données de chaque colonne de la table PostGIS?

9

J'ai besoin d'obtenir les types de données de colonne de toutes les colonnes d'une table, y compris les types de géométrie. Ce que je voulais savoir, c'est s'il existe une fonction ou SQL qui donne quelque chose comme ceci:

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

À partir de quelques réponses sur stackexchange et gis.stackexchange, je sais que je peux obtenir certaines informations avec la requête suivante:

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'

Résultat:

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

Mais, existe-t-il un moyen plus pratique et approprié de récupérer les informations dans le format dont j'ai besoin? Ou dois-je entrer dans le "monde" des CASE WHENstructures et de la concaténation de chaînes pour rassembler tous les attributs de colonne dans une seule colonne dans ce format?

Ma crainte est qu'un type de données non attendu me surprenne en ayant besoin d'un autre attribut de la table information_schema.columns. C'est-à-dire que dans l'exemple de tableau précédent, je n'ai utilisé aucun numeric (15,2)type de données, qui aurait besoin d'utiliser un autre attribut (numeric_precision et numeric_scale) pour être analysé par un CASE WHEN.

Alexandre Neto
la source

Réponses:

14

La théorie oui, bien que vous puissiez la trouver très complexe.

  • Chaque table (sélectionnez * dans pg_class) a des colonnes.
  • Chaque colonne (sélectionnez * dans pg_attribute) possède éventuellement un numéro "typmod".
  • Pour les types avec typmod (sélectionnez * dans pg_type), il y aura une fonction "typmodout".
  • L'exécution de la fonction typmod out sur un numéro typmod renvoie une chaîne qui peut être concaténée avec le nom du type pour former le type de signature lisible par l'utilisateur auquel vous êtes habitué (sélectionnez 'numeric' || numerictypmodout (786441)) (sélectionnez geography_typmod_out (1107460))

Mais, hé, psql génère les chaînes que vous voulez, si nous regardons quel SQL il génère, peut-être que la réponse est là.

Effectivement, il existe une fonction magique qui prend un typeid et typmod et renvoie la chaîne magique.

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

Avec une jointure à pg_class, vous devriez pouvoir obtenir ces informations par table.

Paul Ramsey
la source
Je n'obtiens aucun résultat where attname = 'geog'mais = 'geom'fonctionne. Cela me donne de bons résultats pour les valeurs MultiPolygon, Point et MultiPoint mais je ne vois rien pour les types Line ou MultiLine. Sont-ils considérés comme des polygones?
mhkeller
7

Il peut être obtenu en utilisant une simple requête SQL.

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

Nilesh Khode
la source
1
Cela fonctionne très bien! Et voici un conseil: la sortie peut être un peu longue, vous pouvez donc vouloir activer l'affichage étendu sur votre console: \pset pagerdésactiver la page, puis \xactiver l'affichage étendu.
modulitos
7

Avec l' aide de Paul Ramsey, je l'ai fait de cette façon:

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;

MISE À JOUR

Pendant ce temps, j'ai créé une fonction pour demander un certain type de données de colonne

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;

L'utilisation est:

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

si vous voulez vérifier le type de géométrie, vous pouvez cocher 'udt_name' dans 'INFORMATION_SCHEMA.COLUMNS' et l'utiliser!:

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

Haj Hossein
la source