Abfrage, um Namen von Ausgabespalten und Datentypen einer Abfrage, Tabelle oder Ansicht zurückzugeben


21

Gibt es eine PostgreSQL-Abfrage oder einen PostgreSQL-Befehl, der die Feldnamen und Feldtypen einer Abfrage, Tabelle oder Sicht zurückgibt?

ZB sollte eine Lösung, wenn sie auf einfache SELECT-Abfragen angewendet wird, SELECT * from personeine Liste wie die folgende zurückgeben:

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

Ich habe die information_schemain einer Antwort unten beschriebenen Ansichten nachgeschlagen und es scheint, dass sie Tabellen ziemlich gut abdecken, und ich vermute, dass sie auch Ansichten abdecken, aber ich habe das noch nicht überprüft.

Die letzte ist eine beliebige aber gültige SELECT - Abfrage zB Beteiligung, JOINS, UNIONSetc, auf der Datenbank. Gibt es eine integrierte Prozedur oder eine andere gespeicherte Prozedur oder ein Skript, die bzw. das für eine gültige Abfrage dasselbe zurückgeben kann?

Ich entwickle ein Programm, das Daten erstellt und Formulare abfragt. Die Informationen werden für die Datenvalidierung und die Ausführung von Funktionen für die zurückgegebenen Daten benötigt.


Es gibt offensichtlich keinen einzelnen "Befehl", aber es gibt verschiedene Möglichkeiten, Informationen aus den Systemkatalogen abzurufen. Bitte stellen Sie eine bestimmte Frage , fügen Sie ein Beispiel und Ihre Erwartungen hinzu und geben Sie uns eine Vorstellung von der Absicht dahinter.
Erwin Brandstetter

1
Der Grund für die Einfachheit ist, dass für Clients Abfragen, dh SELECTAbfragen, dh nicht datendefinierende oder Datenmanipulationsabfragen, in Tabellen, Ansichten oder anderen Abfragen Datenzeilen und -spalten zurückgeben, sodass PostgreSQL in der Lage sein sollte, a zurückzugeben Liste der Spaltennamen und ihrer Datentypen. Die information_schemain den Antworten unten genannten Ansichten scheinen für Tabellen und Ansichten zu gelten. Beliebige SELECT-Abfragen bilden die letzte Grenze. Ich werde die Antwort bearbeiten, um sie besser zu erklären
vfclists

Antworten:


22

Informationsschema vs. Systemkataloge

Wir haben darüber oft diskutiert. Das Informationsschema dient bestimmten Zwecken. Wenn Sie sich in den Systemkatalogen auskennen, dienen diese den meisten Zwecken besser , IMO. Die Systemkataloge sind die eigentliche Quelle aller Informationen.

Das Informationsschema bietet standardisierte Ansichten, die die Portabilität erleichtern, vor allem über die wichtigsten Postgres-Versionen hinweg, da die Portabilität über verschiedene RDBMS-Plattformen in der Regel eine Illusion ist, wenn Ihre Abfragen so komplex sind, dass sie nach Systemkatalogen suchen müssen. Insbesondere unterstützt Oracle das Informationsschema immer noch nicht.

Ansichten im Informationsschema müssen durch viele Rahmen springen, um ein Format zu erreichen, das dem Standard entspricht. Das macht sie langsam, manchmal sehr langsam. Vergleichen Sie Pläne und Leistung für diese grundlegenden Objekte:

EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;

Der Unterschied ist bemerkenswert. Es kommt wirklich darauf an, wonach Sie suchen.

Dein Beispiel

SELECT * from tblVergleichen Sie für Ihr Beispiel die beiden folgenden Abfragen für diese einfache Tabelle:

CREATE TEMP TABLE foo(
   A numeric(12,3)
 , b timestamp(0)
);

Verwenden von 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() Gibt den vollständigen Typ mit allen Modifikatoren zurück:

attname | type
--------+-------------------------------
a       | numeric(12,3)
b       | timestamp(0) without time zone

Beachten Sie auch, dass die regclassUmwandlung des Tabellennamens entsprechend der aktuellen Situation etwas intelligent ist search_path. Es wird auch eine Ausnahme ausgelöst, wenn der Name nicht gültig ist. Einzelheiten:

Verwenden von information_schema.columns:

SELECT column_name, data_type
FROM   information_schema.columns
WHERE  table_name = 'foo'
ORDER  BY ordinal_position;

Die Informationen sind standardisiert, aber unvollständig :

column_name | data_type
------------+----------------------------
a           | numeric
b           | timestamp without time zone

Um vollständige Informationen für den Datentyp zu erhalten, müssen Sie zusätzlich alle folgenden Spalten berücksichtigen:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Verwandte Antworten:

Eine Liste der Vor-und Nachteile , die größten Vor-und Nachteile (IMO) in Fettschrift:

Informationsschema-Ansichten

  • oft einfacher (ab)
  • schleppend
  • vorverarbeitet, je nachdem, ob es Ihren Anforderungen entspricht oder nicht
  • selektiv (Benutzer sehen nur Objekte, für die sie Berechtigungen haben)
  • Konform mit einem SQL-Standard (der von einigen der wichtigsten RDBMS implementiert wurde)
  • meist portabel für alle gängigen Postgres-Versionen
  • erfordern nicht viel spezifisches Wissen über Postgres
  • Bezeichner sind beschreibend, lang und manchmal umständlich

Systemkataloge

  • oft komplexer (hängt davon ab), näher an der Quelle
  • schnell
  • komplett (Systemspalten wie oidenthalten)
  • entspricht nicht einem SQL-Standard
  • weniger portabel für alle wichtigen Postgres-Versionen (aber die Grundlagen werden sich nicht ändern)
  • erfordern genauere Kenntnisse über Postgres
  • Bezeichner sind knapp, weniger beschreibend, aber zweckmäßig kurz

Beliebige Abfrage

Um dieselbe Liste von Spaltennamen und -typen aus einer Abfrage zu erhalten, können Sie einen einfachen Trick verwenden: ERSTELLEN Sie eine temporäre Tabelle aus der Abfrageausgabe und verwenden Sie dann dieselben Techniken wie oben.

Sie können Folgendes anhängen LIMIT 0, da Sie keine aktuellen Daten benötigen:

CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT  0;

Um den Datentyp einzelner Spalten abzurufen, können Sie auch die Funktion verwenden pg_typeof():

SELECT pg_typeof(1);

Ich danke dir sehr. Ich habe eine Weile lang nach dem Datentyp der Spalte in pg_attribute gesucht und bin gerade auf diesen Beitrag gestoßen. Schätzen Sie Ihren Beitrag.
Melinda

Dies ist im Allgemeinen hilfreich, beantwortet jedoch nicht die ursprüngliche Frage, wie Informationen zu Datentypen der Spalten abgerufen werden, die eine SELECT-Anweisung liefert. Es ging nicht um die Spalten von Views oder Tabellen, die sich natürlich in den Systemkatalogen befinden und auch im Informationsschema angezeigt werden.
Holger Jakobs


2

Wenn Sie Zugriff auf den Katalog pg_catalog haben und PgAdmin3 verwenden, empfehle ich dringend eine Lösung, die ich im Tech-Blog von Valentine ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields) gefunden habe. html ). Es ist ein PgAdmin3-Makro, auf das über eine Verknüpfung zugegriffen werden kann, um die Definition eines ausgewählten Tabellennamens anzuzeigen.

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;

Funktioniert wie ein Zauber und äußerst nützlich.


1

Verwenden Sie die information_schemaAnsichten , sie sind SQL-Standard und enthalten die gewünschten Informationen.

Sie können auch direkt auf usw. zugreifen pg_class, dies pg_attributeist jedoch nicht portabel und häufig umständlich. Sie müssen wie Helferfunktionenoidvectortypes , pg_get_function_argumentsusw. für einige Dinge.

Wenn Sie sehen möchten, wie psqletwas ausgeführt wird \dt, führen psql -ESie Folgendes aus: Die Abfrage wird gedruckt. Normalerweise ist es jedoch besser, das zu verwenden, information_schemawenn es Ihren Anforderungen entspricht.


1

Dies mag zu einfach sein, aber pgAdmin4 zeigt die Feldtypen in den Ausgabeergebnissen an. Die anderen oben genannten Lösungen sind wahrscheinlich eleganter, aber wenn ich nur eine schnelle Antwort benötige, finde ich, dass die Abfrage-GUI von pgAdmin4 ziemlich gut funktioniert. Der Versuch, den Feldtyp eines berechneten Felds zu ermitteln, das von einer Ansicht oder Funktion zurückgegeben wird, kann schwierig sein.

Bildbeschreibung hier eingeben


Es ist sehr schön, dass pgAdmin4 dies tut, aber wie geht das damit um? Können wir das herausfinden, ohne den gesamten Quellcode von PgAdmin4 zu durchsuchen?
Holger Jakobs
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.