对以编程方式调用的表进行迭代的函数

时间:2018-09-05 19:49:00

标签: postgresql

我需要一个使用标识符的函数来选择dos表,并返回具有这些表中过程值的另一个表。

让我们考虑以下表格:

sum1_suffix

 id | digit1 
----+--------
  1 |      2
  2 |      8
  3 |      7
  4 |      5

sum2_suffix

 id | digit2 
----+--------
  1 |      7
  2 |      3
  3 |      9
  4 |      1

我的功能:

CREATE OR REPLACE FUNCTION public.add(IN tablesuffix character varying)
  RETURNS TABLE(result integer) AS
$BODY$
DECLARE 
    var_r record;
    tabla_s1 character varying;
    tabla_s2 character varying;
    cadena_sql TEXT; --for debugging
BEGIN
 tabla_s1 := quote_ident(CONCAT('sum1_',tablesuffix));
 tabla_s2 := quote_ident(CONCAT('sum2_',tablesuffix));
EXECUTE     
--cadena_sql :=
 'FOR var_r IN( SELECT ' || 
        tabla_s1 ||'.digit1 , '||tabla_s2 ||'.digit2 
   FROM '||tabla_s1||','||tabla_s2||
 ' WHERE '||tabla_s1||'.id ='|| tabla_s2||'.id)
 LOOP
        result := var_r.digit1 + var_r.digit2
        RETURN NEXT;
 END LOOP;';
 RAISE NOTICE 'cadena sql es %',cadena_sql;
END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION public.add(character varying)
  OWNER TO postgres;

最后,我调用该函数:

select * from add('suffix');

但是我得到这个错误:

ERROR:  syntax error at or near "FOR"
LINE 1: FOR var_r IN( SELECT sum1_code.digit1 , sum2_code.digit2 
        ^

我也尝试修改此行:

'FOR var_r IN(SELECT ' || 

以这种方式:

'FOR '||var_r ||' IN(SELECT ' || 

但随后出现下一个错误:

ERROR:  record "var_r" is not assigned yet
DETAIL:  The tuple structure of a not-yet-assigned record is indeterminate.
CONTEXT:  SQL statement "SELECT 'FOR '||var_r ||' IN(SELECT ' || 
...........

(注意,我没有用过FORMAT()来执行,因为在实际查询中,我大约有20个 I%参数,对我来说更具可读性,不要使用这种方式,至少直到我已经解决了主要问题。)

1 个答案:

答案 0 :(得分:1)

我注意到该函数存在几个错误:

第一

您不能将控件结构与EXECUTE

一起使用
EXECUTE     
--cadena_sql :=
 'FOR var_r IN( SELECT ' || 
        tabla_s1 ||'.digit1 , '||tabla_s2 ||'.digit2 
   FROM '||tabla_s1||','||tabla_s2||
 ' WHERE '||tabla_s1||'.id ='|| tabla_s2||'.id)
 LOOP
        result := var_r.digit1 + var_r.digit2
        RETURN NEXT;
 END LOOP;';    

第二

没有+运算符来改变字符类型。

result := var_r.digit1 + var_r.digit2

考虑到这些要点,也许这可以解决

CREATE OR REPLACE FUNCTION public.add(IN tablesuffix character varying)
  RETURNS TABLE(result integer) AS
$BODY$
DECLARE 
    var_r record;
    tabla_s1 character varying;
    tabla_s2 character varying;
    cadena_sql TEXT; --for debugging
BEGIN
 tabla_s1 := quote_ident(CONCAT('sum1_',tablesuffix));
 tabla_s2 := quote_ident(CONCAT('sum2_',tablesuffix));

--cadena_sql :=
 FOR var_r IN EXECUTE 'SELECT ' || 
        tabla_s1 ||'.digit1 , '||tabla_s2 ||'.digit2 
   FROM '||tabla_s1||','||tabla_s2||
 ' WHERE '||tabla_s1||'.id ='|| tabla_s2||'.id'
 LOOP
        result := var_r.digit1::int + var_r.digit2::int;
        RETURN NEXT;
 END LOOP;
 RAISE NOTICE 'cadena sql es %',cadena_sql;
END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION public.add(character varying)
  OWNER TO postgres;