2016-03-18 75 views
0

我想在PostgreSQL函數中將表作爲參數傳遞,並且我無法在第一個代碼中找到正確的關鍵字(應該代替table)線:表作爲PostgreSQL函數的參數

CREATE FUNCTION test.fcttest(table) 
RETURNS SETOF test.out_table 
AS $$ 
    INSERT INTO test.out_table /* obviously, the schema for this table is what it should be, an int column for A.id and a varchar(30) column for A.another_field */ 
     SELECT A.id, A.another_field 
     FROM $1 A; 
    SELECT A.id, A.another_field 
     FROM $1 A; 
$$ 
LANGUAGE SQL; 

或者它可能只是不能這樣工作?如果是這樣,我該怎麼做? (另外,我猜可能還有與我的功能有關的SQL注入相關問題,但現在請忽略它們,這是針對安全環境中的原型,因此我暫時不必擔心它。或者,如果你確實解決了這個問題,請在答案的單獨部分中這樣做,這樣我就可以理解什麼是地址:))。

謝謝。

回答

1

你不能傳遞一個表作爲例如參數,該表的只有名稱:

CREATE FUNCTION test.fcttest(tbl text) RETURNS SETOF test.out_table AS $$ 
BEGIN 
    EXECUTE format('INSERT INTO test.out_table ' 
        'SELECT id, another_field FROM %I', tbl); 
    RETURN QUERY EXECUTE format('SELECT id, another_field FROM %I', tbl); 
END; 
$$ LANGUAGE plpgsql; 

當路過你需要execute a dynamic command表名。你只能在plpgsql函數中做到這一點。使用format() function%I修飾符可防止SQL注入。使用RETURN NEXT QUERY短語返回行,並再次使用動態命令。

請注意,此邏輯插入一組記錄到表test.out_table,然後返回相同的一組記錄。不知道這是你真正想要的。

+0

好吧,我想我明白它是如何工作的,謝謝,我正在儘快嘗試。出於好奇,如果我只想插入並且什麼也不返回,我不得不將第1行改爲'... RETURNS void AS $$',將第5-6行改爲'RETURN END;',對吧? –

+0

另一個後續:如果我正在執行兩個表之間的連接,那麼對於'EXECUTE ...'行(特別是'... FROM%I',tbl ...'部分)參數? –

+1

這很簡單。假設你有'tbl1'和'tbl2'作爲參數,那麼你只要把'%I'放在任何你想要表名(標識符,因此'%I')的地方。 '格式'('SELECT * FROM%1 $ I JOIN%2 $ I ON%1 $ I.field =%2 $ I.col',tbl1,tbl2)格式替換每個佔位符(%I,%L或%s)與函數的下一個參數(tbl1,tbl2)。您可以使用'%1 $ I'語法「重複使用」以前使用的參數。參見'format()'文檔(鏈接在答案中)。 – Patrick