Jak mogę uzyskać listę wszystkich funkcji przechowywanych w bazie danych określonego schematu w PostgreSQL?


135

Chcę mieć możliwość połączenia się z bazą danych PostgreSQL i znalezienia wszystkich funkcji dla określonego schematu.

Pomyślałem, że mógłbym wykonać zapytanie do pg_catalog lub information_schema i uzyskać listę wszystkich funkcji, ale nie mogę dowiedzieć się, gdzie są przechowywane nazwy i parametry. Szukam zapytania, które poda nazwę funkcji i typy parametrów, które przyjmuje (i kolejność, w jakiej je przyjmuje).

Czy jest na to sposób?

Odpowiedzi:


191
\df <schema>.*

w psqlzawiera niezbędne informacje.

Aby zobaczyć zapytanie, które jest używane wewnętrznie, połącz się z bazą danych psqli podaj dodatkową opcję „ -E” (lub „ --echo-hidden”), a następnie wykonaj powyższe polecenie.


1
Czy możesz wkleić to zapytanie?
— Rudd Zwolinski

3
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 TO 'trigger' ELSE 'normal' END as "Type" Z 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; Powyżej jest wygenerowane zapytanie (z \ set ECHO_HIDDEN „on”).
— Simon D,

90

Po kilku poszukiwaniach udało mi się znaleźć information_schema.routinesstół i information_schema.parametersstoły. Korzystając z nich, można w tym celu skonstruować zapytanie. LEFT JOIN, zamiast JOIN, jest konieczne do pobierania funkcji bez parametrów.

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
Znajdziesz też oidvectortypesnaprawdę przydatne. Zobacz nową odpowiedź: stackoverflow.com/a/24034604/398670
— Craig Ringer

Powyższy kod nie pokaże wszystkich funkcji, potrzebujesz LEFT JOIN zamiast JOIN, aby wyświetlać również funkcje bez parametrów wejściowych.
— David

35

Jeśli ktoś jest zainteresowany, oto jakie zapytanie jest wykonywane psqlna postgres 9.1:

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;

Możesz uzyskać to, co psqldziała dla polecenia z ukośnikiem odwrotnym, uruchamiając psqlz -Eflagą.


Właśnie znalazłem twoją odpowiedź i spróbowałem zapytać na Postgres 11.5. Mówi:ERROR: column p.proisagg does not exist
— Christiaan Westerbeek

Dzięki za to; dwie najwyżej ocenione odpowiedzi nie pokazały mojej funkcji!
— machineghost

29

Jest przydatna funkcja oidvectortypes, która znacznie to ułatwia.

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';

Podziękowania dla Leo Hsu i Reginy Obe z Postgres Online za wskazanie oidvectortypes. Pisałem wcześniej podobne funkcje, ale używałem złożonych wyrażeń zagnieżdżonych, których ta funkcja eliminuje potrzebę.

Zobacz powiązaną odpowiedź .


(edytuj w 2016)

Podsumowując typowe opcje raportu:

-- 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';

UWAGA : użyj, p.proname||'_'||p.oid AS specific_name aby uzyskać unikalne nazwy, lub DOŁĄCZ do information_schematabel - patrz routinesi parametersprzy odpowiedzi @ RuddZwolinski.


Z funkcji OID (patrz  pg_catalog.pg_proc), a funkcja jest specific_name (zobacz  information_schema.routines) to główne opcje odniesienie do funkcji. Poniżej kilka przydatnych funkcji w raportowaniu i innych kontekstach.

--- --- --- --- ---
--- 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;

To pronamejest nazwa, ale jak zdobyć OID np. używać w pg_catalog.pg_get_function_result(oid))?
— Peter Krauss

1
@PeterKrauss oidKolumna pg_proc. To ukryta kolumna.
— Craig Ringer

1
Zobacz także stackoverflow.com/a/25388031/161040, aby dowiedzieć się, jak wykluczyć funkcje zależne od rozszerzeń (np. Funkcje z PostGIS).
— Simon D

20

Uruchom poniżej zapytanie SQL, aby utworzyć widok, który pokaże wszystkie funkcje:

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

10

Czy dobrym pomysłem jest nazwanie funkcji z aliasami komunikacyjnymi na pierwszych słowach, aby odfiltrować nazwę z LIKE Przykładem ze schematem publicznym w Postgresql 9.4, należy zamienić na jego schemat

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

4

Przykład:

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
Czym to się różni od odpowiedzi Milena?
— a_horse_with_no_name

3
To nie jest zapytanie, to polecenie psqlinterfejsu klienta Postgres. Działa to tylko w programie psqli nie jest technicznie zapytaniem SQL.
— GregT

3

Pobierz listę schematu_funkcji i nazwa_funkcji ...


> 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

Ta funkcja zwraca wszystkie procedury zdefiniowane przez użytkownika w bieżącej bazie danych.

SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.