在 Pl/pgSQL 中使用 FOR 循环时,它在 Postgres 11.8 中不起作用

Posted

技术标签:

【中文标题】在 Pl/pgSQL 中使用 FOR 循环时,它在 Postgres 11.8 中不起作用【英文标题】:FOR-loop does NOT work in Postgres 11.8 when using it in Pl/pgSQL 【发布时间】:2020-06-19 08:05:42 【问题描述】:

我正在这个link 和this 上尝试来自PostgreSQLTutorial 网站的FOR 循环示例,this 是正在使用的示例数据库。问题是我无法开始工作是以下 for-loop 示例:

CREATE OR REPLACE FUNCTION for_loop_through_query(
   n INTEGER DEFAULT 10
) 
RETURNS VOID AS $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN SELECT title 
           FROM film 
           ORDER BY title
           LIMIT n 
    LOOP 
    RAISE NOTICE '%', rec.title;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

当我运行select for_loop_through_query(5); 时,我根本没有得到任何结果! 我试过在 DataGrip 和 pgAdmin4 中运行它,PostgreSQL 版本是 11.8Fedora 30 操作系统上。我还尝试用int 而不是INTEGER 替换n 参数类型。 我是否遗漏了什么(命令/附加设置)?非常感谢任何帮助/建议。

P.S.在他们的website 上说已经安装了 PostgreSQL 11.3,所以我猜他们的示例必须在不比我的旧版本那么多的 PostgreSQL 上运行。

更新1: 例外的输出应该是:

注意:学院恐龙 注意:王牌金手指 注意:适应孔 注意:外遇偏见 注意:非洲鸡蛋

我得到的输出:

postgres=# select * FROM version();
                                                version                                                 
--------------------------------------------------------------------------------------------------------
 PostgreSQL 11.8 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2), 64-bit
(1 row)

... 当我执行 2 个以下命令时 sudo su - postgrespsql dvdrental postgres我得到这个输出:

dvdrental=# select for_loop_through_query(5);
NOTICE:  Academy Dinosaur
NOTICE:  Ace Goldfinger
NOTICE:  Adaptation Holes
NOTICE:  Affair Prejudice
NOTICE:  African Egg
 for_loop_through_query 
------------------------

(1 row)

在 DataGrip 和 pgAdmin4 中调用此函数时似乎有什么问题......有什么想法吗?

【问题讨论】:

【参考方案1】:

使用 PostgreSQL 11.8,如果表中有数据,它就可以工作。

请注意,您的函数返回 void,因此您没有真正的结果集:函数应该返回一些数据,否则您可以使用过程。

select * from version();
                                                 version                        

--------------------------------------------------------------------------------
-------------------------
 PostgreSQL 11.8 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (R
ed Hat 4.8.5-39), 64-bit
(1 row)

select * from film;
 title 
-------
 ABC0
 ABC1
 ABC2
 ABC3
 ABC4
 ABC5
 ABC6
 ABC7
 ABC8
(9 rows)

CREATE OR REPLACE FUNCTION for_loop_through_query(
   n INTEGER DEFAULT 10
) 
RETURNS VOID AS $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN SELECT title 
           FROM film 
           ORDER BY title
           LIMIT n 
    LOOP 
    RAISE NOTICE '%', rec.title;
    END LOOP;
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION

select * from for_loop_through_query(5);
NOTICE:  ABC0
NOTICE:  ABC1
NOTICE:  ABC2
NOTICE:  ABC3
NOTICE:  ABC4
 for_loop_through_query 
------------------------

(1 row)

select for_loop_through_query(5);
NOTICE:  ABC0
NOTICE:  ABC1
NOTICE:  ABC2
NOTICE:  ABC3
NOTICE:  ABC4
 for_loop_through_query 
------------------------

(1 row)

由于您的函数不返回任何数据,您可以在 pgAdmin4 仅在 Messages 选项卡中获得 RAISE NOTICE 消息

NOTICE:  ABC0
NOTICE:  ABC1
NOTICE:  ABC2
NOTICE:  ABC3
NOTICE:  ABC4
NOTICE:  ABC5
NOTICE:  ABC6
NOTICE:  ABC7
NOTICE:  ABC8

Successfully run. Total query runtime: 54 msec.
1 rows affected.

【讨论】:

但我确实在表中有数据 请使用psql 发布您的输出并详细说明您的预期输出:通知消息?函数结果? 更新了我的问题,正如您在上一条评论中提出的,请看一下 要在客户端应用程序中拥有RAISE NOTICE 消息,您需要有一个能够从数据库端检索此数据的应用程序:pgAdmin 知道如何执行此操作,但我无法告知数据网格(RAISE NOTICE 消息与SELECT 语句等通常 DML 返回的数据不同 true,我已经在 DataGrip 中检查了类似的“消息”选项卡/选项(如在 pgAdmin4 中),并且它确实以“输出”控制台的形式...显然我已经监督它向我展示了 ResultSet 的附加选项卡。再一次感谢你。 :)

以上是关于在 Pl/pgSQL 中使用 FOR 循环时,它在 Postgres 11.8 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

PL/pgSQL“for循环”+选择基本示例(“hello world”)

PostgreSQL vs Oracle:PL/pgSQL 的“编译时”检查

PL/pgSQL 函数 - 遍历特定列并在循环中执行第二个查询

PL/pgSQL 循环遍历多个模式、表和行

PostgreSQL-PL/pgSQL控制结构

关于 Pl/pgsql 中游标的一些错误