如何在postgresql中显示函数、过程和触发器的源代码?

238
如何在PostgreSQL中打印函数和触发器源代码?如果有人知道显示函数和触发器源代码的查询,请告诉我。

13
对于那些想要找出如何列出所有触发器的关注者,需要注意的是,可以使用select * from pg_trigger;进行查询,或者如果你想查看每个触发器所应用的表,可以使用select tgrelid::regclass, tgname from pg_trigger;。顺便提一下。 - rogerdpack
6
\sf(下面的解释)是查看函数源代码的最佳方式。 - Peter Krauss
9个回答

222

\df+psql中可以获得源代码。


30
好的 :) 我建议使用\df来查找您的函数名称,然后使用\x来展开输出,最后使用\df+ 函数名称来获取更详细的信息。 - Sam Watkins
61
如果你只需要代码,\sf 就足够了!但是 \df 输出的内容比代码多得多。 - Telic
1
如何查看已安装扩展的函数?例如,我正在使用 ltree,但是使用 \df ltxtquery 没有响应。 - Peter Krauss
2
\x ON 是转置显示的必要条件。 - andilabs
1
为什么 \sf+ Coalesce 给我写了错误:函数“Coalesce”不存在。 - El_L

166

对于函数:

你可以查询 pg_proc 视图,如下所示:

select proname,prosrc from pg_proc where proname= your_function_name; 

另一种方法是执行常用的命令\df\ef,以列出函数。

skytf=> \df           
                                             List of functions
 Schema |         Name         | Result data type |              Argument data types               |  Type  
--------+----------------------+------------------+------------------------------------------------+--------
 public | pg_buffercache_pages | SETOF record     |                                                | normal


skytf=> \ef  pg_buffercache_pages

它将显示函数的源代码。

对于触发器:

我不知道是否有直接获取源代码的方法。只知道以下方法,也许能帮到你!

  • 步骤1:获取触发器的表oid:
    skytf=> select tgrelid from pg_trigger  where tgname='insert_tbl_tmp_trigger';
      tgrelid
    ---------
       26599
    (1 row)
  • 步骤2:获取上述OID的表名!
    skytf=> select oid,relname  from pg_class where oid=26599;
      oid  |           relname           
    -------+-----------------------------
     26599 | tbl_tmp
    (1 row)
  • 步骤3:列出表信息
    skytf=> \d tbl_tmp

它将显示您的表触发器的详细信息。通常触发器使用函数。因此,您可以按照我上面指出的方式获得触发器函数的源代码!


64

以下是来自PostgreSQL-9.5的几个示例

显示列表:

  1. 函数: \df+
  2. 触发器: \dy+

显示定义:

postgres=# \sf
function name is required

postgres=# \sf pg_reload_conf()
CREATE OR REPLACE FUNCTION pg_catalog.pg_reload_conf()
 RETURNS boolean
 LANGUAGE internal
 STRICT
AS $function$pg_reload_conf$function$

postgres=# \sf pg_encoding_to_char
CREATE OR REPLACE FUNCTION pg_catalog.pg_encoding_to_char(integer)
 RETURNS name
 LANGUAGE internal
 STABLE STRICT
AS $function$PG_encoding_to_char$function$

10
使用\x首先打开扩展显示也有助于提高可读性。 - Pocketsand
这很有帮助--谢谢!--尽管奇怪的是包括括号(例如,\sf shared.is_authorized())会失败并显示“函数...不存在”,而省略括号则可以正常工作(例如,\sf shared.is_authorized)。 (psql 12.9) - Glenn

32

有很多可能性。最简单的方法是使用pgAdmin并从SQL窗口中获取此信息。但是,如果您想以编程方式获取此信息,请检查pg_procpg_trigger 系统目录或来自信息模式的 routinestriggers 视图(这是SQL标准方式,但可能不覆盖所有特性,特别是针对PostgreSQL的)。例如:

SELECT
    routine_definition 
FROM
    information_schema.routines 
WHERE
    specific_schema LIKE 'public'
    AND routine_name LIKE 'functionName';

3
我有一些PGPSQL函数,它们的routine_defintion为空,并且在routine_body字段中标记为“EXTERNAL”。你知道我可以在哪里找到它们吗? - alfonx
2
+1 这是更标准/可移植的解决方案。对于视图,SQL 语句为:SELECT view_definition FROM information_schema.views WHERE table_schema = ? AND table_name = ? - Franta
但是如果一个函数名称不唯一,因为有人使用相同的名称和不同的函数参数创建了函数,该怎么办? - mg1075
1
@alfonx 请查看 pgproc.prosrc 列。 - Tomáš Záluský
我对这个解决方案感到满意,但使用“LIKE”运算符的原因是什么? - Ray Ronnaret

22

除了仅显示函数外,还可以获得原地编辑功能。

\ef <function_name>非常方便。它将以可编辑格式打开函数的源代码。您不仅可以查看它,还可以编辑和执行它。

只需使用\ef而不使用function_name,则会打开可编辑的CREATE FUNCTION模板。

更多参考资料 -> https://www.postgresql.org/docs/9.6/static/app-psql.html


编辑完函数后需要输入 \g 命令以更新函数。 - Abdusoli

20

\sf函数在psql中会返回单个函数的可编辑源代码。

来自https://www.postgresql.org/docs/9.6/static/app-psql.html:

\sf[+] 函数描述 此命令获取并显示指定函数的定义,格式为CREATE OR REPLACE FUNCTION命令。

如果在命令名称后添加+,则输出行将编号,函数正文的第一行为第1行。


2
显示一个函数的源代码。使用 \ef 函数名称 可以在可编辑的模板中打开它。 - amar
1
这绝对应该成为被采纳的答案!它只是一个三个字符的命令,就是这样。 - Bill

14

7
列出所有的函数:
select n.nspname as function_schema,
       p.proname as function_name,
       l.lanname as function_language,
       case when l.lanname = 'internal' then p.prosrc
            else pg_get_functiondef(p.oid)
            end as definition,
       pg_get_function_arguments(p.oid) as function_arguments,
       t.typname as return_type
from pg_proc p
left join pg_namespace n on p.pronamespace = n.oid
left join pg_language l on p.prolang = l.oid
left join pg_type t on t.oid = p.prorettype 
where n.nspname not in ('pg_catalog', 'information_schema')
order by function_schema,
             function_name;

如果您想在所有函数中搜索特定单词或文本,方法如下,请确保将您的文本替换为以下函数中的文本:

with tbl as (
select n.nspname as function_schema,
       p.proname as function_name,
       l.lanname as function_language,
       case when l.lanname = 'internal' then p.prosrc
            else pg_get_functiondef(p.oid)
            end as definition,
       pg_get_function_arguments(p.oid) as function_arguments,
       t.typname as return_type
from pg_proc p
left join pg_namespace n on p.pronamespace = n.oid
left join pg_language l on p.prolang = l.oid
left join pg_type t on t.oid = p.prorettype 
where n.nspname not in ('pg_catalog', 'information_schema')
)
    select *
    from tbl
    where definition ilike '%word or text you want to search%'
    order by function_schema,
             function_name;

7

自版本:psql(9.6.17,服务器11.6)

我尝试了以上所有答案,但对我来说

postgres=> \sf jsonb_extract_path_text
CREATE OR REPLACE FUNCTION pg_catalog.jsonb_extract_path_text(from_json jsonb, VARIADIC path_elems text[])
 RETURNS text
 LANGUAGE internal
 IMMUTABLE PARALLEL SAFE STRICT
AS $function$jsonb_extract_path_text$function$



postgres=> \df+
ERROR:  column p.proisagg does not exist
LINE 6:   WHEN p.proisagg THEN 'agg'
               ^
HINT:  Perhaps you meant to reference the column "p.prolang".

对我来说,df命令似乎无法正常工作。


这似乎是使用过时的psql版本发生的,例如当psql --version打印出类似于10.x的版本,而服务器是11+时。https://dba.stackexchange.com/a/238906 - Falco Preiseni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接