Zeigen Sie benutzerdefinierte Typen und deren Details an

12

Ich habe einige neue UDTs in PostgreSQL erstellt. Jetzt habe ich jedoch zwei Probleme:

  1. Wie kann man sehen, welche UDTs definiert wurden?
  2. Wie werden die in diesen UDTs definierten Spalten angezeigt?

Leider konnte ich in der PostgreSQL-Dokumentation nichts dazu finden.

navige
quelle

Antworten:

17

Fangen Sie damit an?

SELECT n.nspname AS schema,
        pg_catalog.format_type ( t.oid, NULL ) AS name,
        t.typname AS internal_name,
        CASE
            WHEN t.typrelid != 0
            THEN CAST ( 'tuple' AS pg_catalog.text )
            WHEN t.typlen < 0
            THEN CAST ( 'var' AS pg_catalog.text )
            ELSE CAST ( t.typlen AS pg_catalog.text )
        END AS size,
        pg_catalog.array_to_string (
            ARRAY( SELECT e.enumlabel
                    FROM pg_catalog.pg_enum e
                    WHERE e.enumtypid = t.oid
                    ORDER BY e.oid ), E'\n'
            ) AS elements,
        pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description
    FROM pg_catalog.pg_type t
    LEFT JOIN pg_catalog.pg_namespace n
        ON n.oid = t.typnamespace
    WHERE ( t.typrelid = 0
            OR ( SELECT c.relkind = 'c'
                    FROM pg_catalog.pg_class c
                    WHERE c.oid = t.typrelid
                )
        )
        AND NOT EXISTS
            ( SELECT 1
                FROM pg_catalog.pg_type el
                WHERE el.oid = t.typelem
                    AND el.typarray = t.oid
            )
        AND n.nspname <> 'pg_catalog'
        AND n.nspname <> 'information_schema'
        AND pg_catalog.pg_type_is_visible ( t.oid )
    ORDER BY 1, 2;

In psql können Sie \set ECHO_HIDDEN onpsql die Abfragen anzeigen lassen, mit denen die Ausgabe der \d...Befehle generiert wird . Ich habe festgestellt, dass diese Abfragen als Ausgangspunkt für das Ausgraben von Metadaten aus Datenbanken sehr nützlich sind.

Update: 2019-12-16

Für zusammengesetzte Typen können die Spaltenmetadaten wie folgt bestimmt werden:

WITH types AS (
    SELECT n.nspname,
            pg_catalog.format_type ( t.oid, NULL ) AS obj_name,
            CASE
                WHEN t.typrelid != 0 THEN CAST ( 'tuple' AS pg_catalog.text )
                WHEN t.typlen < 0 THEN CAST ( 'var' AS pg_catalog.text )
                ELSE CAST ( t.typlen AS pg_catalog.text )
                END AS obj_type,
            coalesce ( pg_catalog.obj_description ( t.oid, 'pg_type' ), '' ) AS description
        FROM pg_catalog.pg_type t
        JOIN pg_catalog.pg_namespace n
            ON n.oid = t.typnamespace
        WHERE ( t.typrelid = 0
                OR ( SELECT c.relkind = 'c'
                        FROM pg_catalog.pg_class c
                        WHERE c.oid = t.typrelid ) )
            AND NOT EXISTS (
                    SELECT 1
                        FROM pg_catalog.pg_type el
                        WHERE el.oid = t.typelem
                        AND el.typarray = t.oid )
            AND n.nspname <> 'pg_catalog'
            AND n.nspname <> 'information_schema'
            AND n.nspname !~ '^pg_toast'
),
cols AS (
    SELECT n.nspname::text AS schema_name,
            pg_catalog.format_type ( t.oid, NULL ) AS obj_name,
            a.attname::text AS column_name,
            pg_catalog.format_type ( a.atttypid, a.atttypmod ) AS data_type,
            a.attnotnull AS is_required,
            a.attnum AS ordinal_position,
            pg_catalog.col_description ( a.attrelid, a.attnum ) AS description
        FROM pg_catalog.pg_attribute a
        JOIN pg_catalog.pg_type t
            ON a.attrelid = t.typrelid
        JOIN pg_catalog.pg_namespace n
            ON ( n.oid = t.typnamespace )
        JOIN types
            ON ( types.nspname = n.nspname
                AND types.obj_name = pg_catalog.format_type ( t.oid, NULL ) )
        WHERE a.attnum > 0
            AND NOT a.attisdropped
)
SELECT cols.schema_name,
        cols.obj_name,
        cols.column_name,
        cols.data_type,
        cols.ordinal_position,
        cols.is_required,
        coalesce ( cols.description, '' ) AS description
    FROM cols
    ORDER BY cols.schema_name,
            cols.obj_name,
            cols.ordinal_position ;
gsiems
quelle
3
Dieser Tipp mit ECHO_HIDDEN ist von unschätzbarem Wert.
Dekso
1
@dezso: Du bekommst das gleiche mit psql -E.
Erwin Brandstetter
Vielen Dank für den Code und die Erklärungen. Nur eins: Was meinst du mit ´ \ d ... ´ Befehlen?
Navige
1
Geben Sie \?in psql oder lesen Sie hier das Handbuch eine Liste der Meta-Befehle und Erklärungen zu erhalten. \d(& Freunde) beschreiben Objekte der Datenbank. Intern werden die meisten Meta-Befehle als SQL für den Systemkatalog ausgeführt, der auch mit den genannten Optionen angezeigt werden kann.
Erwin Brandstetter
1
Schön, aber es wird nur eine Zeile pro Typ angezeigt, genau wie \ dT + in psql. Was ist mit den Informationen zum Erstellen des Typs, genau wie pgAdmin es zeigt (siehe nächste Antwort), aber ohne pgAdmin zu verwenden?
Holger Jakobs
13

Sie können die Standard-GUI pgAdmin verwenden :

gibt pgAdmin ein

Stellen Sie sicher, dass die Typen im Objektbrowser aktiviert sind ( Optionen - Browser - Anzeige ).

Links sehen Sie benutzerdefinierte Typen im ausgewählten Schema (Frage 1 ).

Auf SQL paneder rechten Seite befindet sich das rückentwickelte SQL-Skript für den ausgewählten Typ (Frage 2 ).
Weitere Details im Bereich darüber, wie Dependentsetc.


Alternativ können Sie die standardmäßige interaktive Konsole psql verwenden :

  1. \dT um eine Liste der benutzerdefinierten Typen zu erhalten.
  2. \d type_name um die Spaltendefinitionsliste für den angegebenen Typ abzurufen.

Das Handbuch:

\d[S+] [ pattern ]

Zeigen Sie für jede Beziehung (Tabelle, Ansicht, materialisierte Ansicht, Index, Sequenz oder Fremdtabelle) oder zusammengesetzten Typ , die dem Muster entspricht , alle Spalten, ihre Typen, [...]

Meine kühne Betonung. Der Befehl funktioniert auch für zusammengesetzte Typen, da mindestens Postgres 9.1.

Und:

\dT[S+] [ pattern ]

Listet Datentypen auf. Wenn Muster angegeben ist, werden nur Typen aufgelistet, deren Namen mit dem Muster übereinstimmen. Wenn +an den Befehlsnamen angehängt wird, wird jeder Typ mit seinem internen Namen und seiner Größe, seinen zulässigen Werten, wenn es sich um einen enumTyp handelt, und den zugehörigen Berechtigungen aufgelistet . Standardmäßig werden nur vom Benutzer erstellte Objekte angezeigt. Geben Sie ein Muster oder den SModifikator an, um Systemobjekte einzuschließen.

Erwin Brandstetter
quelle
1
Wie erhalte ich diese Informationen ohne pgAdmin?
Holger Jakobs
1
@ HolgerJakobs: Ich habe oben eine Alternative mit psql hinzugefügt.
Erwin Brandstetter
1
\ dT gibt eine Liste von Typen an, \ dT Typname gibt keine Spalten an, \ d Typname zeigt an, dass "keine Beziehung mit dem Namen" ... "gefunden wurde. Wenn der Typ aufgrund einer Tabelle mit demselben Namen vorhanden ist, ist dies der Fall funktioniert, aber ein von "CREATE TYPE" erstellter Typ zeigt seine Spalten nicht an.
Holger Jakobs
@HolgerJakobs: Ich weiß, dass dies wie angekündigt funktioniert, und ich habe es vor dem Posten getestet. Das heißt, im heutigen Postgres ( psql , um genau zu sein). Sie müssen eine veraltete Version von psql verwenden. Siehe oben hinzugefügte Bits.
Erwin Brandstetter
3
Ich habe die gleiche Nachricht erhalten, aber \ dT + Typname hat funktioniert. (Version 9.5)
Spike
1

Versuchen Sie, diesen Code auszuführen:

SELECT
    pg_type.typname, 
     pg_enum.enumlabel
FROM
    pg_type 
JOIN
    pg_enum ON pg_enum.enumtypid = pg_type.oid;
Santos L. Victor
quelle
1
Weitere Erklärungen werden im Allgemeinen als angemessen angesehen, warum Code verwendet werden sollte.
James Jenkins
Ich habe keine Ergebnisse aus dieser Abfrage erhalten. Ich bin mir nicht sicher, wie die Daten aussehen sollten.
jDub9
1

Dies ist eine sehr einfache Alternative , aber genug für einfache Anwendungsfälle. Wenn der Spaltentyp UDT ist, verwenden wir die udt_nameSpalte aus der information_schema.columnsTabelle.

select column_name, case 
        when (data_type = 'USER-DEFINED') then udt_name 
        else data_type 
    end as data_type
from information_schema.columns 
where table_schema = 'altimetria' and table_name = 'cnivel';

Ergebnis ( geometryist ein UDT):

 column_name  |    data_type     
--------------+------------------
 ogc_fid      | integer
 wkb_geometry | geometry
 id_cnivel    | bigint
 cod_cart     | bigint
 cod_fam      | bigint
 cod_sub      | integer
 z            | double precision
 shape_len    | double precision
jgrocha
quelle