关于plpgsql:带有FOREACH循环的PostgreSQL PL / pgSQL语法错误

PostgreSQL PL/pgSQL syntax error with FOREACH loop

我正在尝试通过编写一些简单的程序来学习PL / pgSQL。 为了了解FOREACH循环,我编写了以下内容:

1
2
3
4
5
6
7
8
9
10
11
CREATE OR REPLACE FUNCTION test(INT[]) RETURNS void AS $$  
DECLARE                                                    
    window INT;                                            
BEGIN                                                      
    FOREACH window IN ARRAY $1                              
    LOOP                                                    
        EXECUTE 'SELECT $1' USING window;                  
    END LOOP;                                              
$$ LANGUAGE plpgsql;                                        

SELECT test(ARRAY [30,60]);

我希望此代码段将首先打印30,然后打印60。 但是,出现以下错误。

1
2
3
4
5
6
7
8
psql:loop.sql:11: ERROR:  syntax error at END OF INPUT
LINE 7:         EXECUTE 'SELECT $1' USING window;
                                                ^
psql:loop.sql:13: ERROR:  FUNCTION test(INTEGER[]) does NOT exist
LINE 1: SELECT test(ARRAY [30,60]);
               ^
HINT:  No FUNCTION matches the given name AND argument types. You might need
 TO ADD explicit TYPE casts.

因此,函数定义存在语法错误,但是我不明白错误是什么以及如何修复它。 我将不胜感激。 谢谢!


您的函数被声明为returns void,因此您无法从中返回任何内容。 如果要返回多个值,则需要使用returns setof integer

但是它有更多的问题。

  • 您应该给参数起一个名字(不是错误,而是好的编码风格)
  • 要从函数返回值,您需要使用return。 要返回多个值(由于returns setof),您需要使用return next
  • 不需要动态SQL返回值,您可以直接返回变量。
  • 同样不是错误,但是:window是关键字,我不会使用具有该名称的变量。
  • 应用所有这些,您的函数应如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE OR REPLACE FUNCTION test(p_input INT[])
      RETURNS setof INTEGER
    AS
    $$  
    DECLARE                                                    
      l_value INT;                                            
    BEGIN                                                      
        FOREACH l_value IN ARRAY p_input                            
        LOOP                                                    
            RETURN NEXT l_value;
        END LOOP;                                              
    END;
    $$
    LANGUAGE plpgsql;

    我不确定您是否知道,但是已经有一个内置函数可以实现相同的功能:unnest()