我正在尝试创建一个引用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)是否有更好的方法来编写这样一个引用临时表的函数?
答案 0 :(得分:11)
我认为您的问题是您正在使用的语言。 SQL语言中的EXECUTE:
EXECUTE
用于执行先前准备的语句。由于预准备语句仅在会话期间存在,因此预准备语句必须由先前在当前会话中执行的PREPARE
语句创建。
通常,您需要在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();