2014-01-06 34 views
0

如何在postgresql中使用executeif exists語句編寫函數?使用if和exists執行

CREATE FUNCTION replace_value(var_id char, var_data text, table_name char) RETURNS void AS $$ 
BEGIN 
    IF EXISTS EXECUTE'(SELECT id FROM ' ||table_name|| ' WHERE id = '||var_id||')' 

    THEN EXECUTE 'UPDATE ' ||table_name||' 
      SET (id, data) = '||(var_id, var_data)||';' 

    ELSE EXECUTE 'INSERT INTO ' ||table_name||' (id, data) 
      VALUES '||(var_id, var_data)||';' 

    END IF; 
    RETURN; 

END; 
$$ LANGUAGE plpgsql; 

我也將使用table_name作爲傳遞給函數和一些變量在這個例子中'var_id''var_data'參數。我知道在postgresql函數中使用表名只能在使用execute語句時使用。

回答

1

EXECUTE是plpgsql語句,您不能將兩個語句合併在一起。您的代碼還有其他兩個問題 - SQL注入漏洞和競爭條件。

一個變種(失敗,當更多的客戶會嘗試插入相同的數據)

DECLARE rc int; 
BEGIN 
    EXECUTE format('UPDATE %I SET data=$1 WHERE id=$2', table_name) 
    USING data, var_id; 
    GET DIAGNOSTICS rc = ROW_COUNT; 
    IF rc = 0 THEN 
    EXECUTE format('INSERT INTO %I(id, data) VALUES($1,$2)', table_name) 
     USING var_id, data; 
    END IF; 
END; 

,或者像一些你做了:

DECLARE rc int; 
BEGIN 
    EXECUTE format('SELECT id FROM %I WHERE id=$1 FOR UPDATE', table_name) 
    USING var_id; 
    GET DIAGNOSTICS rc = ROW_COUNT; 
    if rc = 0 THEN 
    EXECUTE format('INSERT INTO %I(id, data) VALUES($1,$2)', table_name) 
     USING var_id, data; 
    ELSE 
    EXECUTE format('UPDATE %I SET data=$1 WHERE id=$2', table_name) 
     USING data, var_id; 
    END IF; 
END 
+0

它'真的管用謝謝。哪個例子更好用?第一個還是第二個?你寫了一個變種(當更多的客戶嘗試插入相同的數據時會失敗),第二種方式更好? – ZiupeX

+0

第一個變體應該快一點 - 當某些條件成立時,兩個變體都可能失敗。選擇一個或多個取決於事務隔離級別和負載 - 多少次衝突。不能說,有什麼更好 - 我更喜歡第一個,但是我的第二個變體在某些特定用例中可能會更好。 –