2013-07-04 79 views
1

,我實現了檢查,如果一個值出現在一個特定表的特定行的函數:PostgreSQL函數錯誤:列名不存在

CREATE FUNCTION check_if_if_exist(id INTEGER, table_name character(50), table_column character(20)) RETURNS BOOLEAN AS $$ 

DECLARE res BOOLEAN; 

BEGIN 
    SELECT table_column INTO res 
    FROM table_name 
    WHERE table_column = id; 

    RETURN res; 
END; 

$$ LANGUAGE plpgsql 

我已經創建並填寫一個簡單的測試表對於試試這個功能:

CREATE TABLE tab(f INTEGER); 

和我通話功能一樣

SELECT check_if_exist(10, tab, f); 

但我發生這個錯誤:

ERROR: column "prova" does not exist 
LINE 1: SELECT check_if_exist(10, tab, f); 
          ^


********** Error ********** 

ERROR: column "tab" does not exist 
SQL state: 42703 
Character: 27 

爲什麼?

+0

如果您嘗試將其作爲「插入如果不存在」或「更新,插入(如果不存在)」的一部分來完成,請立即停止並閱讀關於PostgreSQL的upsert。如果這不是你正在做的事情,也許編輯並解釋你的真正目標是什麼,因爲很難想象像這樣的功能有沒有更好的方法來使用它。 –

回答

2

你的代碼有沒有機會去工作 - 用不同的表中PLPGSQL打交道時,你需要利用動態查詢,所以EXECUTE需要 - http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
但首先 - 沒有什麼不好的使用PostgreSQL EXISTS - http://www.postgresql.org/docs/current/static/functions-subquery.html#AEN15284代替發明自己的 - 你的解決方案的性能將比使用附帶的電池差很多...
希望這會有所幫助。祝你好運。

2

除了Elmo響應,您必須注意類型。你手上有:

ERROR: column "tab" does not exist 

,因爲SQL解析器不知道如何處理tab這是沒有報價。您的查詢必須是這樣的:

SELECT check_if_exist(10, 'tab', 'f'); 

由於毛毛回答您使用動態查詢,所以即使你引用tab,你會得到錯誤:

ERROR: relation "table_name" does not exist 

所以你可以使用EXECUTE,例如:

CREATE OR REPLACE FUNCTION check_if_exist(id INTEGER, table_name varchar, table_column varchar) RETURNS BOOLEAN AS $$ 
    DECLARE 
     sql varchar; 
     cnt int; 
    BEGIN 
     sql := 'SELECT count(*) FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(table_column) || '=$1'; 
     RAISE NOTICE 'sql %', sql; 
     EXECUTE sql USING id INTO cnt; 
     RETURN cnt > 0; 
    END; 
$$ LANGUAGE plpgsql 

您還可以在函數參數中使用VARCHAR而不是character(N),並使用CREATE OR REPLACE FUNCTION ...而不是CREATE FUNCTION ...這在調試時非常方便。

+4

千萬不要使用直接字符串連接顯示'EXECUTE'。它使該函數成爲SQL注入的向量。上面應該寫成'EXECUTE format('SELECT count(*)FROM%I WHERE%I = $ 1',table_name,table_column)USING id INTO cnt;'或者對於沒有'format'的舊版PostgreSQL版本,應該包裝表格和'quote_ident'調用中的列名。 –

+0

+1爲答案,然而@CraigRinger是正確的與他的顧慮,所以+1也是他。很高興向OP展示如何進行動態查詢和防止SQL注入,但我仍然認爲編寫這個確切的函數正在重新發明輪子。 – ElmoVanKielmo

+0

謝謝,我剛剛編輯答案。當我們可以使用'select exists(select * from my_table where my_column = my_value)'時,我看不到這個函數非常有用。 –