为啥我不能从 pgAdmin pgScript 调用 PL/pgSQL 函数?

Posted

技术标签:

【中文标题】为啥我不能从 pgAdmin pgScript 调用 PL/pgSQL 函数?【英文标题】:Why can't I call a PL/pgSQL function from a pgAdmin pgScript?为什么我不能从 pgAdmin pgScript 调用 PL/pgSQL 函数? 【发布时间】:2012-02-28 07:47:26 【问题描述】:

我们的 PostgreSQL 数据库包含一个用 PL/pgSQL 编写的函数。我可以从这样的 SQL 查询窗口中很好地运行它:

BEGIN TRANSACTION;
SELECT sg_copy_form(414, 2621, 1, 1035);
ROLLBACK TRANSACTION;

但是,如果我在上面运行与 pgScript 完全相同的 SQL(例如,单击 pgAdmin 中的 Execute pgScript 按钮而不是 Execute query),那么我会得到以下信息错误:

[QUERY    ] BEGIN TRANSACTION
[WARNING  ] SELECT sg_copy_form(414, 2621, 1, 1035)
        ERROR:  function sg_copy_form(integer, integer, integer, integer) does not exist
        LINE 1: SELECT sg_copy_form(414, 2621, 1, 1035)
                       ^
        HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
[QUERY    ] ROLLBACK TRANSACTION

这是为什么?是否可以从 pgScript 调用 PL/pgSQL 函数?

如果相关:我正在使用 pgAdmin III 1.12.2 在 PostgreSQL 8.3.14 上尝试此操作。


编辑:我尝试按照 Eelke 的建议完全限定函数的名称,如下所示:

BEGIN TRANSACTION;
SELECT db_dev.public.sg_copy_form(414, 2621, 1, 1035);
ROLLBACK TRANSACTION;

当作为普通 SQL 查询运行时,它仍然可以正常工作,但是当我作为 pgScript 运行它时,我得到了一个 不同的 错误消息:

[QUERY    ] BEGIN TRANSACTION
[WARNING  ] SELECT db_dev.public.sg_copy_form(414, 2621, 1, 1035)
        ERROR:  cross-database references are not implemented: db_dev.public.sg_copy_form
[QUERY    ] ROLLBACK TRANSACTION

【问题讨论】:

这意味着 pgScript 在另一个数据库的上下文中执行。 这样的声明:SELECT mydb.myschema.some_func(..); 永远行不通。如错误消息所述:未实现跨数据库引用。您不能为数据库名称添加前缀。您的编辑一定有误。 上面编辑的文字是正确的。事实证明,pgAdmin 中的一个可能的错误(参见下面的答案中的 cmets)意味着它在错误的数据库上执行 pgScript。因此,当将上述代码作为 SQL 执行时,前缀与数据库名称匹配,因此不会导致任何问题;当将代码作为 pgScript 执行时,它在不同的数据库上运行,因此前缀不匹配并触发错误... 【参考方案1】:

您是否仔细检查了这两种情况下您的环境是否相同?请检查

同一个数据库, 同一用户, 相同的搜索路径

问题很可能是 pgadmin3 中的某些设置不同,而您只是没有“看到”该功能。

编辑

您可以像这样比较设置:

将此作为普通 SQL 执行(即仅“执行”):

select current_database(), current_user, current_setting('search_path');

将其作为 pgScript 执行:

declare @foo @db, @usr, @p ;
set @foo = select current_database(), current_user, current_setting('search_path');
print @foo;

结束编辑

顺便说一句:由于错误消息来自服务器,这将发生在用 any 语言(例如 SQL、pljava)编写的函数中,而不仅仅是 PL/pgSQL。

【讨论】:

是的,它绝对是同一个数据库、用户和 search_path,因为唯一的区别是我在 pgAdmin 中按了哪个按钮:执行查询执行 pgScript 您能否尝试明确设置搜索路径或完全限定函数名称?我知道它不应该是必需的,但 pgAdmin 可能正在做一些奇怪的事情(如包含一个错误)。 我尝试使用SET search_path TO public; 设置搜索路径,但没有任何区别。但是,当我完全质量函数名称时,我确实会收到 different 错误消息 - 请参阅上面的编辑! 我不确定 pgscript 是否可以处理存储过程。 @fluca1978:服务器不区分自己的函数和用户定义的函数。错误消息是服务器消息。所以 pgAdmin 已经出局了,除非它非常神奇地做了一些事情。

以上是关于为啥我不能从 pgAdmin pgScript 调用 PL/pgSQL 函数?的主要内容,如果未能解决你的问题,请参考以下文章

pgAdmin III 为啥查询结果会缩短?

为啥这个问题发生在我的 linux mint 上的 pgadmin4 上

为啥 INSERT 查询无限期挂起并锁定 PostgreSQL 数据库和 pgAdmin

无法从 Windows 上的 pgadmin 连接到 greenplum postgresql

PostgreSQL 10.0 压缩版的 pgAdmin 不能用的问题

为啥函数可以修改调用者感知的某些参数,而不能修改其他参数?