Як я можу отримати список усіх функцій, що зберігаються в базі даних певної схеми в PostgreSQL?


135

Я хочу мати можливість підключитися до бази даних PostgreSQL і знайти всі функції для певної схеми.

Думав, що я можу зробити запит до pg_catalog або information_schema і отримати список усіх функцій, але я не можу зрозуміти, де зберігаються імена та параметри. Я шукаю запит, який дасть мені ім'я функції та типи параметрів, які вона потребує (і в якому порядку їх приймає).

Чи є спосіб це зробити?

Відповіді:


191
\df <schema>.*

в psqlдає необхідну інформацію.

Щоб побачити запит, який використовується внутрішньо, підключіться до бази даних psqlта надайте додатковий варіант " -E" (або " --echo-hidden") та виконайте вищевказану команду.


1
Не могли б ви вставити, що це за запит?
Rudd Zwolinski

3
Виберіть n.nspname як "Схема", p.proname - як "Ім'я", pg_catalog.pg_get_function_result (p.oid) як "Тип даних результату", pg_catalog.pg_get_function_arguments (p.oid) як "Типи даних аргументу", CASE WHEN p .proisagg ТАГО 'agg' КОЛИ p.proiswindow ТАМО 'вікно' КОЛИ p.prorettype = 'pg_catalog.trigger' :: pg_catalog.regtype ТАГО 'тригер' ELSE 'нормальний' END як "Тип" ВІД pg_catalog.pg_proc p НАЛІГЛЯ ПРИЄДНАЙТЕ pg_catalog .pg_pacepace n ON n.oid = p.pronamespace ДЕ n.nspname ~ '^ (public) $' ЗАМОВИТИ 1, 2, 4; Вище формується запит (від \ set ECHO_HIDDEN 'on').
Саймон Д

90

Після деяких пошуків я зміг знайти information_schema.routinesтаблицю та information_schema.parametersтаблиці. Використовуючи ці, можна побудувати запит для цієї мети. LEFT JOIN замість JOIN необхідний для отримання функцій без параметрів.

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
Ви oidvectortypesтеж знайдете корисне. Дивіться нову відповідь: stackoverflow.com/a/24034604/398670
Крейг Рінгер

У наведеному вище коді не відображатимуться всі функції. Вам потрібно ЛІВНЕ СПОЛУЧЕННЯ замість ПРИЄДНАТИ, щоб також відображалися функції без вхідних параметрів.
Девід

35

Якщо когось цікавить тут, то який запит виконується psqlна 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;

Ви можете отримати те , що psqlпрацює для зворотних косих команд, запустивши psqlз -Eпрапором.


Щойно натрапив на вашу відповідь і спробував запит на Postgres 11.5. Там написано:ERROR: column p.proisagg does not exist
Крістіан Вестербек

Дякую за це; два голосові відповіді не показали моєї функції!
machineghost

29

Є зручна функція oidvectortypes, яка значно спрощує це.

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

Кредит Лео Хсу і Регіна Obe в Postgres онлайн за вказівку oidvectortypes. Я раніше писав подібні функції, але використовував складні вкладені вирази, в яких ця функція позбавляється від потреби.

Дивіться відповідна відповідь .


(редагувати у 2016 році)

Узагальнення типових варіантів звіту:

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

УВАГА : використання p.proname||'_'||p.oid AS specific_name для отримання унікальних імен, або JOIN з information_schemaтаблицями - см routinesі parametersна @ відповідь RuddZwolinski в.


Функція по OID (див  pg_catalog.pg_proc) і функція в SPECIFIC_NAME (див  information_schema.routines) є основними еталонними параметрами для функцій. Нижче наведено деякі корисні функції у звіті та інші контексти.

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

Це pronameім'я, але як отримати OID, наприклад, використання в pg_catalog.pg_get_function_result(oid))?
Пітер Краус

1
@PeterKrauss oidСтовпець pg_proc. Це прихований стовпчик.
Крейг Рінгер

1
Дивіться також stackoverflow.com/a/25388031/161040 про те, як виключити функції, що залежать від розширення (наприклад, функції PostGIS).
Саймон Д

20

Запустіть нижче SQL-запиту, щоб створити подання, в якому будуть показані всі функції:

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

10

Хороша ідея назвала функції з комунікаційним псевдонімом на перших словах для filtre ім'я з LIKE Приклад з публічною схемою в Postgresql 9.4, обов'язково замініть його схемою

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

4

Приклад:

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
Як це відрізняється від відповіді Мілена?
a_horse_with_no_name

3
Це не запит, це команда psqlклієнтського інтерфейсу Postgres. Це працюватиме лише в psqlтехнічному відношенні і не є SQL-запитом.
GregT

3

Отримати список function_schema та function_name ...


> 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

Ця функція повертає всі визначені користувачем процедури у поточній базі даних.

SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.