2009-08-28 21 views
65

Chcę być w stanie połączyć się z bazą danych PostgreSQL i znaleźć wszystkie funkcje dla określonego schematu.Jak mogę uzyskać listę wszystkich funkcji przechowywanych w bazie danych określonego schematu w PostgreSQL?

Myślałem, że mogę wykonać zapytanie do pg_catalog lub information_schema i uzyskać listę wszystkich funkcji, ale nie wiem, gdzie są przechowywane nazwy i parametry. Szukam zapytania, które da mi nazwę funkcji i typy parametrów, które bierze (i jaką kolejność ich bierze).

Czy istnieje sposób, aby to zrobić?

Odpowiedz

48

Po poszukiwaniach, udało mi się znaleźć stolik information_schema.routines i information_schema.parameters tabele. Korzystając z nich, można skonstruować zapytanie w tym celu. LEFT JOIN, zamiast JOIN, jest niezbędne 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

Bardzo użyteczne są również "oidvectortypes". Zobacz nową odpowiedź: http://stackoverflow.com/a/24034604/398670 –

+0

Powyższy kod nie będzie wyświetlał wszystkich funkcji. Aby wyświetlać funkcje bez parametrów wejściowych, potrzebujesz LEWEGO POŁĄCZENIA zamiast JOIN. – David

93
\df <schema>.* 

w psql daje niezbędne informacje.

Aby zobaczyć zapytania, który jest używany wewnętrznie połączyć się z bazą danych z psql i dostarczyć dodatkową „-E” (lub „--echo-hidden”) opcję, a następnie wykonać powyższą komendę.

+1

Czy możesz wkleić to, czym jest to zapytanie? –

+2

to powinna być akceptowana odpowiedź na prostotę. –

+0

SELECT n.nspname jako "Schema", p.protron jako "Name", pg_catalog.pg_get_function_result (p.oid) jako "Typ danych wynikowych", pg_catalog.pg_get_function_arguments (p.oid) jako "Typy danych argumentów" , CASE KIEDY p.proisagg Then 'agg' KIEDY p.proiswindow Then 'okno' KIEDY p.prorettype = 'pg_catalog.trigger' :: pg_catalog.regtype Then 'spust' ELSE 'normalne' END jako " Wpisz " FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ZAMÓW PRZEZ 1, 2, 4; Powyżej jest wygenerowane zapytanie (z \ set ECHO_HIDDEN "on"). –

3

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

+2

To nie jest zapytanie, jest to polecenie interfejsu klienta 'psql' Postgres. To zadziała tylko w 'psql' i technicznie nie jest zapytaniem SQL. – GregT

18

Jeśli ktoś jest zainteresowany tutaj jest to, co kwerenda jest wykonywana przez psql na PostgreSQL 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żna dostać co psql trwa polecenia backslash uruchamiając psql z flagą -E.

16

Jest przydatna funkcja, oidvectortypes, dzięki czemu jest o wiele łatwiej.

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

zgłosił Leo Hsu and Regina Obe at Postgres Online za wskazanie oidvectortypes. Napisałem już podobne funkcje, ale użyłem złożonych wyrażeń zagnieżdżonych, których ta funkcja pozbywa się potrzeby.

See related answer.


(edycja 2016)

Podsumowując typowe opcje raport:

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

OGŁOSZENIE: użyj p.proname||'_'||p.oid AS specific_name aby uzyskać unikalne nazwy, lub przyłączyć się information_schema tabelach — zobaczyć routines i parameters przy odpowiedzi @ RuddZwolinskiego.


Funkcja użytkownika OID (patrz   pg_catalog.pg_proc), a funkcja jest specific_name (patrz   information_schema.routines) są główne opcje odniesienie do funkcji. Poniżej kilka użytecznych 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; 
+0

Bardzo ładne. Dzięki! –

+0

Nazwa 'proname' to nazwa, ale jak uzyskać OID dla, np. użyć w 'pg_catalog.pg_get_function_result (oid))'? –

+1

@PeterKrauss Kolumna 'oid' z' pg_proc'. To ukryta kolumna. –

6

jest dobrym pomysłem nazwie funkcji z commun alias na pierwszych słów dla Filtre nazwy z LIKE przykład w schemacie publicznym w PostgreSQL 9.4, należy wymienić jego programu

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

Uruchom poniżej kwerendę SQL, aby utworzyć widok, który będzie wyświetlał wszystkie funkcje:

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

To przechodzi do repozytorium utils. Dzięki – Emiliano

Powiązane problemy