我有以下查询,我想将其变成一个函数。我已经为1 company_id = 26304
编写了SQLSELECT 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
答案 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||'