2012-11-06 48 views
3

我可能在這裏扭曲postgres,但基本上,我想要做的是取一個字符串變量,並將它傳遞給一個sql命令(在這種情況下COPY)只使用psql。如何從postgresql中的plpgsql函數返回的SELECT查詢中提取字符串(或文本)?

所以這就是我想出的。這些命令被分成2個文件,因爲我希望能夠在其他情況下使用mydb_functions:

文件一:mydb_functions - 1.0.sql(在共享/擴展和mydb_functions.control也設置爲。手冊中給出一個文件名,返回完整的文件路徑,這是純粹做是爲了在下面add_data.sql的COPY語句,整潔

CREATE OR REPLACE FUNCTION fpn(filename text) RETURNS TEXT as ' 
    DECLARE 
    mypath text := ''/path/to/my/directory/''; 
    BEGIN 
    RETURN mypath || filename; 
    END 
' LANGUAGE plpgsql; 

文件中的兩個:。add_data.sql這僅僅存在於數據複製到現有的注意:由於CREATE EXTENSION命令,需要以超級用戶權限運行psql。

CREATE EXTENSION IF NOT EXISTS mydb_functions; 
-- haven't figured out how to create a function without arguments yet. 
CREATE OR REPLACE FUNCTION test (dummyvar text) RETURNS text as '  
    DECLARE 
    filepath RECORD; 
    BEGIN 
    SELECT * INTO filepath from fpn(''mydatafile.data''); 
    COPY tablename (columnname) FROM filepath; 
    END 
' LANGUAGE plpgsql; 

我被卡住的部分是如何從文件路徑記錄中提取文本以在COPY命令中使用。任何提示,以更簡單的方式來實現這一點也是受歡迎的。我認爲創建一個表來存儲變量比這更容易。但我想完成最後一步。

回答

0

如果您的問題正在運行COPY帶有動態目標路徑,請使用EXECUTE運行特定SQL查詢format

CREATE OR REPLACE FUNCTION test() RETURNS text as $$ 
    DECLARE 
    filepath RECORD; 
    BEGIN 
    SELECT * INTO filepath from fpn('mydatafile.data'); 
    EXECUTE format('COPY tablename (columnname) FROM %L', filepath); 
    END 
$$ LANGUAGE plpgsql; 

看到,這個失敗:

DO 
$$ 
DECLARE 
    somevar text; 
BEGIN 
    somevar := '/tmp/somepath.csv'; 
    COPY tablename(columnname) FROM somevar; 
END; 
$$; 

但這個工程:

DO 
$$ 
DECLARE 
    somevar text; 
BEGIN 
    somevar := '/tmp/somepath.csv'; 
    EXECUTE format('COPY tablename(columnname) FROM %L', somevar); 
END; 
$$; 

參見:

format()%L說明符自動引號文字。 %I對標識符也一樣。


如果我原本以爲,你在談論從外部獲取數據到psql,你可能會發現psql變量和變量代換有用:

$ psql -v filepath=/path/to/my/directory/mydatafile.data regress 
regress=> SELECT :'filepath'; 
       ?column?     
--------------------------------------- 
/path/to/my/directory/mydatafile.data 
(1 row) 

注意,冒號加引號,然後變量名稱被引用。奇怪的語法,我知道。這隻適用於psql;它不會在(比方說)PgAdmin-III中工作。

或者,您可以使用此文檔(類似Unix的外殼專用,不會在Windows' cmd.exe工作)做引用的文本插值:

$ FILEPATH=/path/to/my/directory/mydatafile.data 
$ psql regress <<__END__ 
SELECT '$FILEPATH'; 
__END__ 

       ?column?     
--------------------------------------- 
/path/to/my/directory/mydatafile.data 
(1 row) 

這兩個展示如何插入從shell級別變成psql。從那裏開始,這是在你的功能中使用它的問題。像這樣的,說,與-v filename=myfilename.csv

CREATE OR REPLACE FUNCTION test() RETURNS text as $$ 
    DECLARE 
    filepath RECORD; 
    BEGIN 
    SELECT * INTO filepath from fpn(:'filename'); 
    COPY tablename (columnname) FROM filepath; 
    END 
$$ LANGUAGE plpgsql; 

或者即將與-v filepath=/full/path/to/myfilename.csv

$ psql -v filepath=/path/to/my/directory/mydatafile.data regress 
regress=> COPY tablename (columnname) FROM :'filepath'; 
+0

三江源您詳細的答覆。我很欣賞你花費額外時間展示如何在pl函數中使用psql變量。 – karojosh

相關問題