我有两个字符串:
值,例如'a'。
我需要调用函数UPPER
(从两个字符串合成)并将值作为参数传递
我怎么能这样做?
(实际上,我需要将函数交叉表与列的计数器连接起来...)
答案 0 :(得分:2)
使用动态SQL的函数的存根可能如下所示:
CREATE OR REPLACE FUNCTION f_exec(text, text, text, OUT result text)
RETURNS text AS
$func$
BEGIN
EXECUTE 'SELECT ' || $1 || $2 || '($1)' -- last $1 not referring func param
INTO result
USING $3;
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT f_exec('up', 'per', 'a')
不要混淆,$1
在EXECUTE
内有自己的作用域,并引用USING
子句传入的参数,而不是外部函数参数。
手册中this related answer或章节Executing Dynamic Commands中的更多背景信息。
这为您打开了 SQL注入!
阅读this related question on dba.SE下的建议以及手册中的"Writing SECURITY DEFINER
Functions Safely"章节。
在这种特殊情况下,有一种智能方式来避免SQLi :
CREATE OR REPLACE FUNCTION f_exec(
func1 text
,func2 text
,param text
,OUT result text) AS
$func$
DECLARE
funcname text := (func1 || func2)::regproc;
BEGIN
EXECUTE 'SELECT ' || funcname || '($1)::text'
INTO result
USING param;
END
$func$ LANGUAGE plpgsql;
object identifier type regproc
的强制转换有效地清除了所有尝试通过$1
和$2
注入除有效函数名称之外的任何内容。 USING
子句已经中和了通过$3
(param
)注入代码的尝试。
此外:
RETURNING
子句,因为OUT
参数负责处理它。text
,因为我们不知道函数的实际返回类型,并且Postgres中的每个数据类型都可以转换为text
。IN
类型的text
个参数,否则会出现异常。