0

我有两个字符串:

  • 'UPP'
  • '呃'

和值,例如'a'。

我需要调用函数UPPER(从两个字符串合成)并将值作为参数传递。
我怎样才能做到这一点?

(实际上,我需要将函数交叉表与列计数器连接起来......)

4

1 回答 1

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子句传入的参数,而不是外部函数参数。

此相关答案或手册中执行动态命令一章中的更多背景信息。

警告

这为SQL 注入打开了大门!
阅读关于 dba.SE 的相关问题下的建议以及手册中的“安全地编写SECURITY DEFINER函数”一章。

在这种特殊情况下,有一种避免 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;

转换为对象标识符类型regproc$1有效地清除了通过and注入除有效函数名之外的任何内容的所有尝试$2。该子句已经消除了通过( )USING注入代码的尝试。$3param

还:

  • 使用参数名称以减少混淆。
  • 从函数定义中省略RETURNING子句,因为OUT参数会处理它。
  • 将函数的结果转换为 ,text因为我们不知道函数的实际返回类型,并且 Postgres 中的每个数据类型都可以转换为text.
    该函数仍然需要接受一个IN类型的参数,text否则会出现异常。
于 2013-02-05T18:08:46.910 回答