PL/pgSQL 函数在 pgAdmin 之外无法正确运行

Posted

技术标签:

【中文标题】PL/pgSQL 函数在 pgAdmin 之外无法正确运行【英文标题】:PL/pgSQL function won't run correctly outside pgAdmin 【发布时间】:2019-01-04 03:55:09 【问题描述】:

我使用 pgAdmin 在 PostgreSQL 10.4 中创建了一个 PL/pgSQL 函数。它返回一个查询并更新同一个表中的条目。在 pgAdmin 中调用,它按预期运行。从外部代码运行时,会返回表,但不会运行更新。想知道这是否与我编写函数的方式有关?

CREATE OR REPLACE FUNCTION report()
RETURNS TABLE(id text, t1 text, t2 text)
LANGUAGE 'plpsql'

AS $BODY$
DECLARE
rec RECORD;

BEGIN
RETURN QUERY
SELECT id,
name AS t1,
data AS t2
FROM table1
WHERE status IS NULL;

IF FOUND THEN
FOR rec IN SELECT id
FROM table1
WHERE status IS NULL
LOOP
UPDATE table1 SET val=val+1
WHERE id=rec.id;
END IF;

RETURN;
END
$BODY$;

编辑:

感谢您的回复。没有其他人可以帮忙看一下,所以这对于排除正在发生的事情非常有帮助。

因为有问题,我太专注于我的 PL/pgSQL 函数,所以我忽略了运行该函数的外部程序。我的用户错误。将 UPDATE 移到 SELECT 上方后,我注意到我的程序看到了 UPDATE。我忘记在我的外部程序中将更新提交回数据库,所以表永远不会更新。添加了一个 commit 和 good to。

【问题讨论】:

没有“pgSQL”。你是说plpgsql吗?请(总是!)提供您的 Postgres 版本。 SELECT version(); 有帮助。还有一个完整的函数定义,即使它不起作用。 这是你现在的实际功能吗? status=NULL 始终为 NULL,并且永远不会返回任何行。你想要status IS NULL。你有并发写权限吗? 你是对的。我无法直接复制/粘贴我的代码,所以我不得不重新输入并打错字。我对并发写访问不是 100%,但我相信如此。必须仔细检查。 【参考方案1】:

看起来你可以用这个简单的、很多更便宜的UPDATE查询和RETURNING子句替换整个函数:

UPDATE table1
SET    val = val + 1
WHERE  status IS NULL
RETURNING id, name AS t1, data AS t2;

如果可能存在竞争条件,请考虑:

Postgres UPDATE … LIMIT 1

您可以按原样运行此查询,无需函数包装。如果您想要一个函数包装器,请在前面添加 RETURN QUERY 以直接返回结果。代码示例:

PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"

【讨论】:

我很抱歉,应该更仔细地考虑这一点。在这一点上,我基本上是在玩这个功能。目标是从外部代码运行该函数以处理从选择返回的数据,然后更新每个条目以标记它本质上已被触摸。添加了数据库正在运行的完整创建和 PostgreSQL 版本。我也会试一试你发布的内容。 对预期目标的更完整思考。外部代码将调用该函数以查找其将处理的状态属性为 NULL 的任何记录。然后,我希望该函数更新每条记录的计数器属性,以指示它们已被外部代码处理了多少次。 试一试,但遇到错误,说明没有结果数据的目的地。但是,我想我知道发生了什么。从我的外部代码运行该函数正在正确运行一切;但它没有将更新提交到表。我切换逻辑先处理更新,然后返回查询。我的代码看到了更新的值,但表本身没有更新。 @Tony:我在上面添加了更多内容来解决您看到的错误。 非常感谢。可能并不奇怪,PL/pgSQL 对我来说是非常新的。看了一下那个新帖子,这很有意义,而且看起来比我现在拥有的更好。

以上是关于PL/pgSQL 函数在 pgAdmin 之外无法正确运行的主要内容,如果未能解决你的问题,请参考以下文章

有一个PL / pgSQL免费环境可以为PostgreSQL开发吗?

有没有为 PostgreSQL 开发的 PL/pgSQL 免费环境?

如何在 PL/pgSQL 中创建嵌套函数?

在 PL/pgSQL 函数中使用变量

如何使用 pl/pgsql 将具有动态元素名称的 JSON 数据转换为行?

在 PL/pgSQL 中调用另一个函数内部的函数