【发布时间】:2010-11-23 18:05:46
【问题描述】:
我希望能够连接到 PostgreSQL 数据库并找到特定模式的所有函数。
我的想法是我可以对 pg_catalog 或 information_schema 进行一些查询并获取所有函数的列表,但我无法弄清楚名称和参数的存储位置。我正在寻找一个查询,它会给我函数名称和它采用的参数类型(以及它采用的顺序)。
有没有办法做到这一点?
【问题讨论】:
标签: postgresql function
我希望能够连接到 PostgreSQL 数据库并找到特定模式的所有函数。
我的想法是我可以对 pg_catalog 或 information_schema 进行一些查询并获取所有函数的列表,但我无法弄清楚名称和参数的存储位置。我正在寻找一个查询,它会给我函数名称和它采用的参数类型(以及它采用的顺序)。
有没有办法做到这一点?
【问题讨论】:
标签: postgresql function
获取 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;
【讨论】:
在第一个单词上使用公共别名命名函数是一个好主意,以便使用 LIKE 过滤名称
Postgresql 9.4 中的公共模式示例,请务必替换为他的方案
SELECT routine_name
FROM information_schema.routines
WHERE routine_type='FUNCTION'
AND specific_schema='public'
AND routine_name LIKE 'aliasmyfunctions%';
【讨论】:
此函数返回当前数据库中所有用户定义的例程。
SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
【讨论】:
经过一番搜索,我找到了 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;
【讨论】:
oidvectortypes 也非常有用。查看新答案:stackoverflow.com/a/24034604/398670
【讨论】:
ERROR: column p.proisagg does not exist。
--echo-hidden 的提及,这当然非常有帮助
在下面运行 SQL 查询以创建一个显示所有函数的视图:
CREATE OR REPLACE VIEW show_functions AS
SELECT routine_name FROM information_schema.routines
WHERE routine_type='FUNCTION' AND specific_schema='public';
【讨论】:
有一个方便的功能,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';
感谢Leo Hsu and Regina Obe at Postgres Online 指出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 获取唯一名称,或加入 information_schema 表 - 请参阅 @RuddZwolinski 的回答中的 routines 和 parameters。
函数的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))中使用?
pg_proc 的 oid 列。这是一个隐藏的列。
如果有人对此感兴趣,请查看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;
您可以通过运行带有-E 标志的psql 来获得psql 为反斜杠命令运行的内容。
【讨论】:
ERROR: column p.proisagg does not exist
例子:
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)
【讨论】:
psql Postgres 客户端接口的命令。这仅适用于psql,并且在技术上不是 SQL 查询。