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”;
答案 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
与适当的值(可能为text
或varchar
)等进行比较。
所有这一切,如果你真的需要动态SQL查询,偶尔发生,但如果你设计好数据库则不常见,你可以使用a plpgsql
function with an EXECUTE
statement。
在这种情况下,您可能只希望输入为code
的值,并且查询要明确检查:
SELECT code, name from tbl where code = $1;
然后,您可以为不同的用例添加变体函数,或者使用显式布尔标志(如search_by_name
)来选择不同的查询,所有这些都没有动态SQL的风险和复杂性。