在postgresql错误中创建函数

问题描述 投票:0回答:2
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”;

sql postgresql plpgsql
2个回答
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
投票

函数不是简单地连接您给它的变量并运行生成的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的风险和复杂性。

© www.soinside.com 2019 - 2024. All rights reserved.