从连接的字符串调用函数

问题描述 投票:0回答:1

我有两根弦:

  • 'UPP'
  • ‘呃’

以及值,例如“a”。

我需要调用函数

UPPER
(由两个字符串合成)并将值作为参数传递。
我该怎么做?

实际上,我需要将函数

crosstab()
与列计数器连接起来......

sql postgresql plpgsql dynamic-sql
1个回答
2
投票

使用动态 SQL 的函数的存根可能如下所示:

CREATE OR REPLACE FUNCTION f_exec(text, text, text, OUT result text)
  RETURNS text
  LANGUAGE plpgsql AS
$func$
BEGIN
    EXECUTE 'SELECT ' || $1  || $2 || '($1)'  -- last ($1) not a reference to func param
    INTO   result
    USING  $3;
END
$func$;

致电:

SELECT f_exec('up', 'per', 'a')

不要混淆,

$1
EXECUTE
内部有自己的作用域,指的是
USING
子句传入的参数,而不是外部函数参数。

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

警告

上面对动态 SQL 的幼稚使用会导致 SQL 注入

阅读有关 dba.SE 的相关问题下的建议以及手册中“安全地编写

SECURITY DEFINER
函数”章节。

在这种特殊情况下,有一个聪明的方法可以避免 SQLi

CREATE OR REPLACE FUNCTION f_exec(func1 text, func2 text, param text
                                , OUT result text)
  LANGUAGE plpgsql AS
$func$
DECLARE
   funcname text := (func1 || func2)::regproc;
BEGIN
   EXECUTE 'SELECT ' || funcname || '($1)::text'
   INTO   result
   USING  param;
END
$func$;

转换为对象标识符类型

regproc
有效地排除了通过
$1
$2
注入除有效函数名称之外的任何内容的尝试。
USING
子句已经中和了通过
$3
(
param
) 注入代码的尝试。

还有:

  • 使用参数名称以减少混乱。
  • 从函数定义中省略
    RETURNING
    子句,因为
    OUT
    参数会处理它。
  • 将函数的结果转换为
    text
    ,因为我们不知道函数的实际返回类型,并且 Postgres 中的每个数据类型都可以转换为
    text

    该函数仍然需要接受
    IN
    类型的单个
    text
    参数,否则会出现异常。
© www.soinside.com 2019 - 2024. All rights reserved.