在postgresql错误

时间:2017-10-27 09:49:58

标签: sql postgresql plpgsql

CREATE OR REPLACE FUNCTION increment(key character varying)
RETURNS character varying AS $$
BEGIN
       SELECT code, name from tbl where $1;
END;
$$ LANGUAGE plpgsql;


select * from increment('code = ''ati'' ');

=>通知错误“where $ 1”;

2 个答案:

答案 0 :(得分:1)

您尝试做的是修剪SQL注入,例如:

t=# CREATE OR REPLACE FUNCTION increment(key character varying)
RETURNS character varying AS $$
BEGIN
 return format('SELECT code, name from tbl where %s',$1);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION
Time: 1.179 ms
t=# select * from increment('code = ''ati'' ');
                   increment
------------------------------------------------
 SELECT code, name from tbl where code = 'ati'
(1 row)

但你不能控制返回的语句,请看这里:

t=# select * from increment('true; drop table b;');
                      increment
------------------------------------------------------
 SELECT code, name from tbl where true; drop table b;
(1 row)

答案 1 :(得分:1)

函数不是简单地连接你给它的变量并运行生成的SQL,所以你不能将整个WHERE子句作为参数传递给它。

最大的原因是安全性:对函数的输入最终可能来自不受信任的用户(例如来自网站的输入),并且您不希望它们能够随意更改您的查询。使用它也很尴尬:如果你想搜索姓氏O'Reilly,如果他们没有跟踪'是否被转义,函数就会中断。

因此,查询和数据保持独立 - WHERE $1唯一有效的时间是$1是否为布尔值。同样,WHERE name=$1只会将name与适当的值(可能为textvarchar)等进行比较。

所有这一切,如果你真的需要动态SQL查询,偶尔发生,但如果你设计好数据库则不常见,你可以使用a plpgsql function with an EXECUTE statement

在这种情况下,您可能只希望输入为code的值,并且查询要明确检查:

SELECT code, name from tbl where code = $1;

然后,您可以为不同的用例添加变体函数,或者使用显式布尔标志(如search_by_name)来选择不同的查询,所有这些都没有动态SQL的风险和复杂性。