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

问题描述 投票:0回答:5

我正在尝试创建一个引用 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)是否有更好的方法来编写这样引用临时表的函数?

database postgresql function syntax-error execute
5个回答
19
投票

我认为你的问题是你使用的语言。 SQL 语言中的EXECUTE

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

与 PL/pgSQL 中的 EXECUTE 不同:

您常常希望在 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
 参数中传递的表中。


0
投票

EXECUTE

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

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

查看

手册,了解有关“查询语言 (SQL) 函数”的更多信息。

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

PL/pgSQL 函数


0
投票
这是我测试的一个示例,我使用 EXECUTE 运行选择并将其结果放入游标中。

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');


    


0
投票
或者,您可以使用

DO

 在匿名代码块内运行它。
根据
文档(强调我的):

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();
    

0
投票

执行语句

  • 可用于 PL/pgSQL 函数和过程 (

    LANGUAGE plpgsql

    )。

  • 不能在 SQL 函数和过程中使用 (

    LANGUAGE SQL

    ),否则会出错。

例如,您可以在 PL/pgSQL 函数

EXECUTE

 中使用 
my_func()
 语句,如下所示。 *
我的帖子详细解释了如何在 PL/pgSQL 函数中使用 EXECUTE
 语句:

CREATE FUNCTION my_func() RETURNS VOID AS $$ BEGIN EXECUTE 'UPDATE person SET age = 13 WHERE id = 2'; END; $$ LANGUAGE plpgsql;
    
© www.soinside.com 2019 - 2024. All rights reserved.