使用execute with if存在

时间:2014-01-06 10:58:21

标签: sql postgresql

如何使用executeif exists语句在postgresql中编写函数?

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'。我知道只有在使用execute语句时才能在postgresql函数中使用表名。

1 个答案:

答案 0 :(得分: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