Function 表函数抛出错误:没有参数$1

Function 表函数抛出错误:没有参数$1,function,postgresql,crosstab,Function,Postgresql,Crosstab,我有下面的查询,我想把它变成一个函数。我已经为1个公司编写了SQL\u id=26304 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 (PA

我有下面的查询,我想把它变成一个函数。我已经为1个公司编写了SQL\u id=26304

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'
电话:

抛出:

试着替换

where company_id = $1 


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

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

在您的特定情况下,可以直接替换,因为参数是一个
整数

'.... where company_id = '||$1||' .... '
但一般来说,您应该小心SQL注入,并且始终引用您的参数是最干净、最安全的。请注意,
'11'
在SQL中是一个有效的整数文本;引用标识符总是合法的,只是数字的可选

因此,即使对于数字,我也建议您使用:

'.... where company_id = '||quote_literal($1)||' ....'
或者使用
format
函数构造字符串:

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

这样,如果以后有人将
company\u id
更改为非数字类型,您就不会得到一个很好的SQL注入漏洞。

如果所有函数都包含一个SQL语句,为什么它需要是一个函数?这将是我为多个公司返回的更大数据集的一部分。类似于以下内容:从公司c中选择公司id、公司名称、城市、州、国家、f.financial_id_1内部连接返回财务(公司id)f on d.companyid=f.companyid try替换
where company_id=$1
by
where company_id='| |$1 | |
。Houari,你太棒了,非常感谢!不要引用语言名称:
language sql
'.... where company_id = '||$1||' .... '
'.... where company_id = '||quote_literal($1)||' ....'
format('.... where company_id = %L ....', $1)