在函数中使用EXECUTE时出现PostgreSQL语法错误

时间:2011-07-28 15:15:49

标签: function postgresql syntax-error execute temp-tables

我正在尝试创建一个引用PostgreSQL 8.4中的临时表的函数。基于我的研究,似乎最好的方法是使用EXECUTE命令从定义的字符串执行我的查询。

不幸的是,在尝试创建函数时,我遇到了一个奇怪的语法错误。

我目前的功能定义如下:

CREATE OR REPLACE FUNCTION example() RETURNS void AS $$
  EXECUTE 'INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3 from temp_table';
$$ LANGUAGE SQL;

我得到的错误是:

ERROR:  syntax error at or near "'INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3 from temp_table'"
LINE 2:   execute 'INSERT INTO table1 (col1, col2, col3) SELECT col1...

无论字符串文字中究竟是什么,似乎都会得到相同的错误。

我的问题是,1)使用EXECUTE功能的正确语法是什么,2)是否有更好的方法来编写这样一个引用临时表的函数?

4 个答案:

答案 0 :(得分:11)

我认为您的问题是您正在使用的语言。 SQL语言中的EXECUTE

  

EXECUTE用于执行先前准备的语句。由于预准备语句仅在会话期间存在,因此预准备语句必须由先前在当前会话中执行的PREPARE语句创建。

EXECUTE in PL/pgSQL不同:

  

通常,您需要在PL / pgSQL函数中生成动态命令,即每次执行时都会涉及不同表或不同数据类型的命令。 PL / pgSQL正常尝试缓存命令计划(如第39.10.2节所述)在这种情况下不起作用。要处理此类问题,请提供EXECUTE语句:

EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ];

当您想要使用PL / pgSQL EXECUTE(将字符串作为SQL执行)时,您正在使用SQL EXECUTE(执行预准备语句)。

试试这个:

CREATE OR REPLACE FUNCTION example() RETURNS void AS $$
BEGIN
    EXECUTE 'INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3 from temp_table';
END;
$$ LANGUAGE PLPGSQL;

或者,另一个似乎更接近你似乎想要做的事情的例子:

create or replace function example(tname text) returns void as $$
begin
    execute 'insert into ' || tname || ' (name) values(''pancakes'')';
end;
$$ language plpgsql;

这会将'pancakes'插入到您在函数的tname参数中传递的表中。

答案 1 :(得分:0)

EXECUTE用于执行预准备语句,并且只需要预准备的语句名称作为参数。

如果您尝试执行SQL语句(如您的示例中所示),只需将其包含在函数体中即可。

检查manual以获取有关“查询语言(SQL)函数”的更多信息。

OTOH如果您正在尝试创建PL / pgSQL函数(这不是您在问题中显示的内容),那么您需要将函数转换为PL/pgSQL function

答案 2 :(得分:0)

这是我测试的一个示例,我使用EXECUTE运行select并将其结果放在游标中。

<强> 1。创建表格:

create table people (
  nickname varchar(9),
  name varchar(12),
  second_name varchar(12),
  country varchar(30)
  );

<强> 2。创建功能:

CREATE OR REPLACE FUNCTION fun_find_people (col_name text, col_value varchar)
RETURNS void AS
$BODY$
DECLARE
    local_cursor_p refcursor;
    row_from_people RECORD;

BEGIN
    open local_cursor_p FOR
        EXECUTE 'select * from people where '|| col_name || ' LIKE ''' || col_value || '%'' ';

    raise notice 'col_name: %',col_name;
    raise notice 'col_value: %',col_value;

    LOOP
        FETCH local_cursor_p INTO row_from_people; EXIT WHEN NOT FOUND;

        raise notice 'row_from_people.nickname: %',  row_from_people.nickname ;
        raise notice 'row_from_people.name: %', row_from_people.name ;
        raise notice 'row_from_people.country: %', row_from_people.country;
    END LOOP;
END;
$BODY$ LANGUAGE 'plpgsql'

第3。运行功能 select fun_find_people('name', 'Cristian'); select fun_find_people('country', 'Chile');

答案 3 :(得分:0)

或者,您可以使用DO在匿名代码块中运行它。
根据{{​​3}}(强调我):

  

DO执行一个匿名代码块,或者换句话说,以一种程序语言执行一个短暂的匿名函数。

     

将代码块视为没有参数的函数的主体,并返回void。将其解析并执行一次。


这使您可以运行通常无法运行的构造SQL,而不必强制您构建调用它的函数:

DO $$
BEGIN
    execute 'ALTER DATABASE ' || current_database() || ' SET timezone TO ''UTC''';
    execute 'SET timezone TO ''UTC''';
END;
$$

代替:

CREATE OR REPLACE FUNCTION fix_database_timezone()
RETURNS void AS
$BODY$
BEGIN
    execute 'ALTER DATABASE ' || current_database() || ' SET timezone TO ''UTC''';
    execute 'SET timezone TO ''UTC''';
END;
$BODY$ LANGUAGE 'plpgsql';

fix_database_timezone();