表函数抛出ERROR:没有参数$ 1

时间:2014-11-03 21:06:18

标签: function postgresql crosstab

我有以下查询,我想将其变成一个函数。我已经为1 company_id = 26304

编写了SQL
SELECT t.* FROM crosstab(
   $$
    select company_id, row_number() OVER (ORDER BY year DESC) AS rn2, id
    from 
    (select i.company_id, year, f.id, f.created_at,
                 row_number() OVER (PARTITION BY year
                                ORDER BY year DESC, f.created_at DESC NULLS LAST) AS rn
    from
    public.interactions i
    inner join public.financials f on f.interaction_id = i.id
    where company_id = 26304
) t1
    where rn= 1 limit 3
   $$
   ) AS t (company_id int, financial_id_1 int, financial_id_2 int, financial_id_3 int);

此SQL语句将我的数据集转向并按预期返回以下内容:

company_id  financial_id_1  financial_id_2  financial_id_3
26304       6796            6795            6786

但是,当我尝试将其转换为表函数时,它会抛出以下错误:

CREATE FUNCTION public.returnfinancials (int4) RETURNS TABLE (company_id int, financial_id_1 int, financial_id_2 int, financial_id_3 int) 
as
$$
SELECT t.* FROM crosstab(
   '
    select company_id, row_number() OVER (ORDER BY year DESC) AS rn2, id
    from 
    (select i.company_id, year, f.id, f.created_at,
            row_number() OVER (PARTITION BY year ORDER BY year DESC, f.created_at DESC NULLS LAST) AS rn
    from
    public.interactions i
    inner join public.financials f on f.interaction_id = i.id
    where company_id =  $1
) t1
    where rn= 1 limit 3
   '
   ) AS t (company_id int, financial_id_1 int, financial_id_2 int, financial_id_3 int);
$$
LANGUAGE 'sql'

呼叫:

select * from returnfinancials(23)

抛出:

ERROR: there is no parameter $1
 Where: SQL function "returnfinancials" statement 1
Line: 1

2 个答案:

答案 0 :(得分:1)

问题是$1位于文本字符串中。它由crosstab解释为查询,但在crosstab函数调用的上下文中,调用函数的参数不可见。由于crosstab它的自身在执行时没有向查询传递任何参数,因此会出现错误。

要解决此问题,您应该将参数值替换为传递给交叉表的查询字符串。

在您的具体情况下,直接替换是可以的,因为参数是integer

'.... where company_id = '||$1||' .... '

但一般情况下,您应该注意SQL注入,并且始终引用您的参数是最干净和最安全的。请注意,'11'是SQL中的有效整数文字;引用标识符总是合法的,它只是数字的可选

相反,即使是数字,我建议您使用:

'.... where company_id = '||quote_literal($1)||' ....'

或使用format函数构造字符串:

format('.... where company_id = %L ....', $1)

这样,如果有人稍后将company_id更改为非数字类型,那么您将无法获得漂亮的SQL注入漏洞。

答案 1 :(得分:0)

尝试替换

where company_id = $1 

通过

where company_id = '||$1||'