2012-02-11 114 views
1

我經常在postgresql中使用複製函數,我想我會創建一個函數來使用它。 所以我們可以說我下表如何將參數傳遞給函數中的pgsql命令?

create table users 
(
    userid serial primary key, 
    prefix varchar(10) not null, 
    firstname varchar(255) not null, 
    lastname varchar(255) not null, 
    email varchar(500) not null, 
    password varchar(255) not null, 
    created timestamp not null, 
    modified timestamp not null 
); 

與下面的函數具有

create function getUsersCSV() 
RETURNS void AS 
$BODY$ 
    BEGIN 
    COPY (select * from users) 
    TO 'c:\temp\users.csv' 
    WITH HEADER 
    CSV QUOTE '"' DELIMITER ','; 
    END 
$BODY$ 
LANGUAGE PLPGSQL; 

功能的作品,但如果我改變功能

create function getUsersCSV(filepath varchar) 
RETURNS void AS 
$BODY$ 
    BEGIN 
    COPY (select * from users) 
    TO filepath 
    WITH HEADER 
    CSV QUOTE '"' DELIMITER ','; 
    END 
$BODY$ 
LANGUAGE PLPGSQL; 

它拋出下面的語法錯誤 錯誤:在「filepath」處或附近的語法錯誤 SQL狀態:42601

無論如何要參數化複製命令的目標值嗎?

+0

您使用的是哪個版本的PostgreSQL? – 2012-02-11 08:19:55

+0

[plpgsql:連接變量到FROM子句]的可能重複(http://stackoverflow.com/questions/6258345/plpgsql-concatenation-of-variable-into-from-clause) – 2012-02-11 08:24:33

回答

2

您可以用execute做到這一點:

create function get_users_csv(filepath text) returns void as $$ 
declare 
    cp_cmd text; 
begin 
    cp_cmd := 'copy (select * from users) to ' 
      || quote_literal(filepath) 
      || ' with header csv quote ''"'' delimiter '','''; 
    execute cp_cmd; 
end; 
$$ language plpgsql; 

不要忘了,以防萬一您filepath使用quote_literal。你也可以使用美元報價,如果你不喜歡所有的一倍,單引號:

create function get_users_csv(filepath text) returns void as $$ 
declare 
    cp_cmd text; 
begin 
    cp_cmd := $q$copy (select * from users) to $q$ 
      || quote_literal(filepath) 
      || $q$ with header csv quote '"' delimiter ','$q$; 
    execute cp_cmd; 
end; 
$$ language plpgsql; 

但我發現美元報價是相當難看比文本塊的任何其他。

+0

對於美元引用+1,這是一個祝福,如果你需要在一個字符串中包含單引號。 (所以,不需要查詢字符串的第一部分。)簡化'(從用戶中選擇*)到'用戶'。 – 2012-02-11 14:59:05

+1

在這種情況下,您必須是超級用戶,因此您必須使用安全定義函數。有必要檢查路徑,因爲沒有精確的檢查,有人可能會破壞你的數據 – 2012-02-11 15:23:01

相關問題