6

我在 Postgres 中有一个函数:

CREATE OR REPLACE FUNCTION upsert(sql_insert text, sql_update text) 
RETURNS integer AS
$BODY$
BEGIN
 EXECUTE sql_insert;
 RETURN 1;
EXCEPTION WHEN unique_violation THEN
 EXECUTE sql_update; 
 RETURN 2;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION upsert(text, text) OWNER TO dce;

我通常使用这个查询来调用那个函数:

select upsert(
  $$INSERT INTO zz(a, b) VALUES (66, 'hahahaha')$$,
  $$UPDATE zz SET a=66, b='hahahaha' WHERE a=66$$
)

有用。不幸的是,我的查询字符串不能包含$$,如下所示:

select upsert(
  $$INSERT INTO zz(a, b) VALUES (66, 'ha$$hahaha')$$,
  $$UPDATE zz SET a=66, b='hahahaha' WHERE a=66$$
)

我已阅读Postgres 文档,但仍需要帮助。

4

1 回答 1

12

改用不同的美元报价

选择 upsert(
    $unique_token$ INSERT INTO zz(a, b) VALUES (66, 'ha$$hahaha') $unique_token$ ,
    $unique_token2$ UPDATE zz SET a=66, b='hahahaha' WHERE a=66 $unique_token2 $
   )

每个结束都必须匹配每个开始。这两对不必是不同的,但这样是最安全的。

这仍然留下了美元引号可能在字符串中匹配的理论上的机会。

如果您手动构建查询,只需$在字符串中检查。如果您从变量构建查询,则可以quote_literal(querystring)改用。

还有方便的format()功能。

看:

旁白:我假设您知道这种形式的动态 SQL 极易受到 SQL 注入的攻击?任何此类事情都应该只用于非常私密或非常安全的用途。

于 2012-02-14T05:15:42.990 回答