2011-07-28 48 views
2

我想創建一個引用PostgreSQL 8.4中的臨時表的函數。根據我的研究,似乎最好的方法是使用EXECUTE命令從定義的字符串執行查詢。在函數中使用EXECUTE時PostgreSQL語法錯誤

不幸的是,我在嘗試創建函數時出現了一個奇怪的語法錯誤。

我現在的功能定義如下:

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)是否有更好的方式來編寫這樣的引用臨時表的函數?

回答

6

我認爲你的問題是你正在使用的語言。 EXECUTE使用SQL語言:

EXECUTE用於執行預先準備好的語句。由於預準備語句僅在會話期間存在,因此準備好的語句必須由當前會話中早先執行的PREPARE語句創建。

是不一樣的EXECUTE in PL/pgSQL

通常情況下,你會想裏面生成你的PL/pgSQL函數動態命令,也就是說,命令,每次都會涉及不同表或不同數據類型他們被執行。 PL/pgSQL正常嘗試緩存命令的計劃(如第39.10.2節所述)在這種情況下不起作用。爲了處理這樣的問題,提供了EXECUTE聲明:

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

您使用的是SQL EXECUTE(其執行準備好的語句)當您想使用的PL/pgSQL的EXECUTE(其中執行一個字符串作爲SQL)。

試試這個:

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)函數」的更多信息,請檢查manual

OTOH如果您嘗試創建PL/pgSQL函數(這不是您在問題中顯示的內容),那麼您需要將函數轉換爲PL/pgSQL function

+0

我不能只需將查詢包含在正文中即可因爲它引用了一個在函數創建時不存在的臨時表。唯一的方法是使用PL/pgSQL函數嗎? –

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