Wie kann ich eine Liste aller Funktionen erhalten, die in der Datenbank eines bestimmten Schemas in PostgreSQL gespeichert sind?


135

Ich möchte in der Lage sein, eine Verbindung zu einer PostgreSQL-Datenbank herzustellen und alle Funktionen für ein bestimmtes Schema zu finden.

Mein Gedanke war, dass ich eine Abfrage an pg_catalog oder information_schema machen und eine Liste aller Funktionen erhalten könnte, aber ich kann nicht herausfinden, wo die Namen und Parameter gespeichert sind. Ich suche nach einer Abfrage, die mir den Funktionsnamen und die verwendeten Parametertypen gibt (und in welcher Reihenfolge sie verwendet werden).

Gibt es eine Möglichkeit, dies zu tun?

Antworten:


191
\df <schema>.*

in psqlgibt die notwendigen Informationen.

Um die Abfrage anzuzeigen, die intern verwendet wird, stellen Sie eine Verbindung zu einer Datenbank mit psqleiner zusätzlichen Option " -E" (oder " --echo-hidden") her und führen Sie den obigen Befehl aus.


1
Könnten Sie einfügen, was diese Abfrage ist?
Rudd Zwolinski

3
SELECT n.nspname als "Schema", p.proname als "Name", pg_catalog.pg_get_function_result (p.oid) als "Ergebnisdatentyp", pg_catalog.pg_get_function_arguments (p.oid) als "Argumentdatentypen", CASE WHEN p .proisagg THEN 'agg' WHEN p.proiswindow THEN 'window' WHEN p.prorettype = 'pg_catalog.trigger' :: pg_catalog.regtype THEN 'Trigger' ELSE 'normal' END as "Type" FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog .pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; Oben ist die Abfrage generiert (aus \ set ECHO_HIDDEN 'on').
Simon D

90

Nach einigem Suchen konnte ich den information_schema.routinesTisch und die information_schema.parametersTische finden. Mit diesen kann man zu diesem Zweck eine Abfrage erstellen. LEFT JOIN anstelle von JOIN ist erforderlich, um Funktionen ohne Parameter abzurufen.

SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
FROM information_schema.routines
    LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.specific_schema='my_specified_schema_name'
ORDER BY routines.routine_name, parameters.ordinal_position;

2
Sie werden es auch oidvectortypessehr nützlich finden . Siehe neue Antwort: stackoverflow.com/a/24034604/398670
Craig Ringer

Der obige Code zeigt nicht alle Funktionen an. Sie benötigen einen LEFT JOIN anstelle von JOIN, um auch Funktionen ohne Eingabeparameter anzuzeigen.
David

35

Wenn jemand interessiert ist, ist hier, welche Abfrage psqlauf postgres 9.1 ausgeführt wird :

SELECT n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;

Sie können ermitteln, was psqlfür einen Backslash-Befehl ausgeführt wird, indem Sie psqlmit dem -EFlag ausgeführt werden.


Ich bin gerade auf Ihre Antwort gestoßen und habe die Abfrage in Postgres 11.5 ausprobiert. Es heißt:ERROR: column p.proisagg does not exist
Christiaan Westerbeek

Danke dafür; Die beiden am besten bewerteten Antworten zeigten nicht meine Funktion!
Maschinenhost

29

Es gibt eine praktische Funktion, oidvectortypesdie dies viel einfacher macht.

SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) 
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

Dank an Leo Hsu und Regina Obe von Postgres Online für den Hinweis oidvectortypes. Ich habe bereits ähnliche Funktionen geschrieben, aber komplexe verschachtelte Ausdrücke verwendet, für die diese Funktion nicht mehr erforderlich ist.

Siehe verwandte Antwort .


(bearbeiten im Jahr 2016)

Zusammenfassen typischer Berichtsoptionen:

-- Compact:
SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes))

-- With result data type: 
SELECT format(
       '%I.%I(%s)=%s', 
       ns.nspname, p.proname, oidvectortypes(p.proargtypes),
       pg_get_function_result(p.oid)
)

-- With complete argument description: 
SELECT format('%I.%I(%s)', ns.nspname, p.proname, pg_get_function_arguments(p.oid))

-- ... and mixing it.

-- All with the same FROM clause:
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

HINWEIS : Verwenden Sie p.proname||'_'||p.oid AS specific_name diese Option , um eindeutige Namen zu erhalten oder sich information_schemaTabellen anzuschließen - siehe routinesund parametersunter @ RuddZwolinskis Antwort.


Die OIDpg_catalog.pg_proc der Funktion (siehe  ) und der spezifische Name der Funktion (siehe  information_schema.routines) sind die Hauptreferenzoptionen für Funktionen. Im Folgenden einige nützliche Funktionen für die Berichterstellung und andere Kontexte.

--- --- --- --- ---
--- Useful overloads: 

CREATE FUNCTION oidvectortypes(p_oid int) RETURNS text AS $$
    SELECT oidvectortypes(proargtypes) FROM pg_proc WHERE oid=$1;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION oidvectortypes(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in oidvectortypes(oid).
    SELECT oidvectortypes(proargtypes) 
    FROM pg_proc WHERE oid=regexp_replace($1, '^.+?([^_]+)$', '\1')::int;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION pg_get_function_arguments(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in pg_get_function_arguments.
    SELECT pg_get_function_arguments(regexp_replace($1, '^.+?([^_]+)$', '\1')::int)
$$ LANGUAGE SQL IMMUTABLE;

--- --- --- --- ---
--- User customization: 

CREATE FUNCTION pg_get_function_arguments2(p_specific_name text) RETURNS text AS $$
    -- Example of "special layout" version.
    SELECT trim(array_agg( op||'-'||dt )::text,'{}') 
    FROM (
        SELECT data_type::text as dt, ordinal_position as op
        FROM information_schema.parameters 
        WHERE specific_name = p_specific_name 
        ORDER BY ordinal_position
    ) t
$$ LANGUAGE SQL IMMUTABLE;

Das pronameist der Name, aber wie bekommt man die OID für z. verwenden in pg_catalog.pg_get_function_result(oid))?
Peter Krauss

1
@PeterKrauss Die oidSpalte von pg_proc. Es ist eine versteckte Spalte.
Craig Ringer

1
Siehe auch stackoverflow.com/a/25388031/161040 zum Ausschließen von erweiterungsabhängigen Funktionen (z. B. Funktionen aus PostGIS).
Simon D

20

Führen Sie die folgende SQL-Abfrage aus, um eine Ansicht zu erstellen, in der alle Funktionen angezeigt werden:

CREATE OR REPLACE VIEW show_functions AS
    SELECT routine_name FROM information_schema.routines 
        WHERE routine_type='FUNCTION' AND specific_schema='public';

10

Ist eine gute Idee, die Funktionen mit kommunalem Alias ​​auf den ersten Wörtern für filtre den Namen mit LIKE Beispiel mit öffentlichem Schema in Postgresql 9.4 zu benennen , stellen Sie sicher, durch sein Schema zu ersetzen

SELECT routine_name 
FROM information_schema.routines 
WHERE routine_type='FUNCTION' 
  AND specific_schema='public'
  AND routine_name LIKE 'aliasmyfunctions%';

4

Beispiel:

perfdb-# \df information_schema.*;

List of functions
        Schema      |        Name        | Result data type | Argument data types |  Type  
 information_schema | _pg_char_max_length   | integer | typid oid, typmod integer | normal
 information_schema | _pg_char_octet_length | integer | typid oid, typmod integer | normal
 information_schema | _pg_datetime_precision| integer | typid oid, typmod integer | normal
 .....
 information_schema | _pg_numeric_scale     | integer | typid oid, typmod integer | normal
 information_schema | _pg_truetypid         | oid     | pg_attribute, pg_type     | normal
 information_schema | _pg_truetypmod        | integer | pg_attribute, pg_type     | normal
(11 rows)

5
Und wie unterscheidet sich das von Milens Antwort?
a_horse_with_no_name

3
Dies ist keine Abfrage, sondern ein Befehl der psqlPostgres-Client-Schnittstelle. Dies funktioniert nur in psqlund ist technisch gesehen keine SQL-Abfrage.
GregT

3

Liste der Funktionsschemata und Funktionsnamen abrufen ...


> select n.nspname as function_schema,
> 
> p.proname as function_name
> 
> from pg_proc p
> 
> left join pg_namespace n on p.pronamespace = n.oid
> 
> where n.nspname not in ('pg_catalog', 'information_schema')
> 
> order by function_schema, function_name;

2

Diese Funktion gibt alle benutzerdefinierten Routinen in der aktuellen Datenbank zurück.

SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
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.