我的动态查询postgres函数内部有什么问题?

时间:2016-08-13 05:58:21

标签: postgresql plpgsql postgresql-9.1

我有一个PL / pgSQL函数,它将表名作为动态参数。当我更新现有查询以将表名作为动态参数时,这就是我的功能:

DECLARE rec RECORD; 
BEGIN 
  EXECUTE 'insert into stat_300_8_0(ts, target, data)
               select distinct timestamp-(timestamp%3600) as wide_row_ts,
                      target, array[]::real[] as data
               from ' || temp_table_name || ' as temp 
               where class_id=8
                 and subclass_id=0 
                 and not exists (select ts from stat_300_8_0 
                                 where ts=temp.timestamp-(temp.timestamp%3600)
                                 and target=temp.target)'; 

  FOR rec IN EXECUTE 'SELECT DISTINCT timestamp AS ts 
                      FROM ' || temp_table_name ||
                    ' WHERE class_id=8' 
  LOOP 
      EXECUTE 'update stat_300_8_0 as disk_table
               set data[new_data.start_idx:new_data.end_idx] = array[data_0,data_1]
               from (select timestamp-(timestamp%3600) as wide_row_ts,
                            (timestamp%3600)/300 * 2 + 1 as start_idx,
                            ((timestamp%3600 / 300) + 1) * 2 as end_idx,
                            target, data_0, data_1
                     from ' || temp_table_name ||
                   ' where class_id=8 and subclass_id=0
                       and timestamp=rec.ts) as new_data
               where disk_table.ts=new_data.wide_row_ts
                 and disk_table.target=new_data.target';
  END LOOP; 
END;

然而,当执行此功能时,我收到错误

ERROR:  missing FROM-clause entry for table "rec"

但是,rec在上面代码的第一行中声明。我无法确定我的查询有什么问题。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:2)

补充Eelke的回答:

  1. 假设temp_table_name是一个参数,你真的,真的想通过quote_ident()运行它,因为否则有人可以创建一个名称可以将sql注入你的函数的表。

  2. 不是在那里建议的更改,而是最好使用EXECUTE...USING,因为这样可以为您提供有关值的参数化(从而防止SQL注入)。您可以将rec.ts更改为$1,然后添加到结尾USING ts.rec(在引用的执行字符串之外)。这为您提供了一个更安全的execute内的参数化语句。但是参数不能包含表名,因此它不会使您免于上述第一点。