如何在postgres动态SQL中使用带引号的字符串内的变量

时间:2017-11-05 03:25:38

标签: postgresql plpgsql dynamic-sql

我使用plpgsql创建了以下函数,该函数有3个参数。

CREATE OR REPLACE FUNCTION public.most_service_calls(
    comp_id integer,
    calls integer,
    months integer)
    RETURNS TABLE(state character varying, city character varying, cust_name character varying, num_calls bigint, cost numeric) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
    ROWS 1000
AS $BODY$

Begin
return query execute                   

'select * from 
(select l.state, l.city, l.cust_name, count(distinct a.svc_ord_nbr) num_calls, 
  round(avg(a.std_labr_net_amt_dcrncy) + avg(a.travel_net_amt_dcrncy), 2)
    from dmt_mas_svc_ord_fact a
    inner join dmt_mas_cust_dim b on a.shipto_cust_id = b.cust_id
    inner join store_location l on b.cust_name = l.cust_name
    inner join company co on b.cust_lvl_2_nbr = co.company_nbr
    where b.sap_sls_org_name like ''%Stanley US%''
       and a.create_dtm >= now() - interval '' $3 months''
       and co.company_id = $1
    group by l.state, l.city, l.cust_name
    order by l.state, l.city, l.cust_name ) q
 where num_calls >= $2'
 using comp_id, calls, months;

 end;

$BODY$;

由于引用了查询,所有单引号字符串都是双引号。三个变量由$1$2$3表示。它是字符串中的变量导致麻烦。 a.create_dtm >= now() - interval '' $3 months''

当我运行该函数时,似乎忽略了我提供的第三个参数。因此,以下所有内容都会返回相同的结果。

select * from most_service_calls(1,5,1)
select * from most_service_calls(1,5,12)
select * from most_service_calls(1,5,24)

事实证明,'{'}内的$3被视为3,因为结果与查询中3 months硬编码的查询匹配。

在带引号的查询中将变量包含在字符串中的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您的问题并非特定于动态SQL - 即使在普通的SQL查询中,您也无法引用带引号的字符串中的占位符。

相反,您可以使用:

$3 * interval '1 month'

或:

($3 || ' months')::interval

第一种形式将您提供的数值乘以一个月的间隔。第二个构造一个指定月数的字符串,然后将其转换为间隔。