PostgreSQL Select into with double precision在PL/pgSQL函数中运行时总



我在PL/pgSQL中有一个函数,它试图回退一些数据的日期范围。我遇到的问题是,我似乎无法将双精度存储在变量中。无论我做什么,当在函数内运行时,值总是空的。当我从psql命令行运行查询时,它返回给我正确的数据。我还可以在另一列上运行查询,这不是双精度类型,它工作得很好。例如,如果我将列更改为"total_impressions_for_date_range",它将返回正确的数据。

我正在使用PostgreSQL 8.4

CREATE OR REPLACE FUNCTION rollback_date_range_revenue(campaign_id int, 
  begin_date timestamp, end_date timestamp, autocommit boolean)
RETURNS void AS $BODY$
DECLARE
  total_impressions_for_date_range        bigint;
  total_clicks_for_date_range             bigint;
  total_revenue_for_date_range            double precision;
  total_cost_for_date_range               double precision;
BEGIN
  SELECT sum(revenue) INTO total_revenue_for_date_range
  FROM ad_block_summary_hourly
  WHERE ad_run_id IN (
      SELECT ad_run_id FROM ad_run WHERE ad_campaign_id = campaign_id)
    AND ad_summary_time >= begin_date
    AND ad_summary_time < end_date
    AND (revenue IS NOT NULL);
  RAISE NOTICE 'Total revenue for given date range and campaign % was %',
    campaign_id, total_revenue_for_date_range;

当我运行这个时,我总是得到收入的空值

SELECT rollback_date_range_revenue(8818, '2015-07-20 18:00:00'::timestamp, 
'2015-07-20 20:00:00'::timestamp, false);
NOTICE:  Total revenue for given date range and campaign 8818 was <NULL>

当我从函数外的命令行运行它时,它工作得很好

    select sum(revenue) from ad_block_summary_hourly where ad_run_id in ( 
select ad_run_id from ad_run where ad_campaign_id = 8818) and ad_summary_time 
>= '2015-07-20 18:00:00'::TIMESTAMP and ad_summary_time < '2015-07-20 
20:00:00'::TIMESTAMP ;
       sum    
    ----------
     3122.533
    (1 row)

编辑

感谢a_hor_with_no_name和Patrick。这确实是一个问题与占位符我叫收入重叠与我的查询。这两个不能工作的查询都是双精度查询,这让我很吃惊。碰巧的是,这两个也是我与列名重叠的占位符。

有两件事可以从中吸取教训。

  1. 我采用了a_horse_with_no_name建议的p_占位符命名方案,以避免再次发生此问题。
  2. 发布一个完整的代码示例,这可以被专家更快地识别出来。

首先,PostgreSQL 8.4不再支持,所以你应该尽快升级到9.4。其次,您的函数显然被简化了,因为没有使用一些声明的变量,并且没有END子句。这两点加在一起,给你一个答案有点猜测,但这里有。

尝试将double precision转换为文本,或将其转换为to_char()RAISE NOTICE期望插入表达式的字符串;可能在8.4中这不是自动的。

您还可以改进您的查询:

...
SELECT sum(sh.revenue) INTO total_revenue_for_date_range
FROM ad_block_summary_hourly sh
JOIN ad_run r USING (ad_run_id)
WHERE r.ad_campaign_id = campaign_id
  AND sh.ad_summary_time BETWEEN begin_date AND end_date;
RAISE NOTICE 'Total revenue for given date range and campaign % was %',
  campaign_id, to_char(total_revenue_for_date_range, '9D999');
...

问题的另一个潜在原因(由于缺乏信息而再次猜测)是函数参数或变量与两个表中的任何一个的列名之间的名称冲突。

最新更新