PostgreSQL Select into with double precision always returns null when 运行 in PL/pgSQL function

PostgreSQL Select into with double precision always returns null when run in PL/pgSQL function

我在 PL/pgSQL 中有一个函数试图恢复某个日期范围内的一些数据。我遇到的问题是我似乎无法将双精度存储在变量中。无论我做什么,在函数内部 运行ning 时,值始终为 null。当我从 psql 命令行 运行 查询时,它 return 向我提供了正确的数据。我还可以 运行 对另一列不是双精度类型的查询,它工作正常。例如,如果我将列更改为 "total_impressions_for_date_range",它将 return 给我正确的数据。

我正在使用 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_horse_with_no_name 和帕特里克。这确实是我称为 revenue 的占位符的问题,它与我的查询重叠。两个不起作用的查询都是双精度的,这让我很吃惊。恰好这两个也是我与列名重叠的占位符。

2 个要点。

  1. 我采用了 a_horse_with_no_name 建议的占位符 p_ 命名方案,以免 运行 再次陷入此问题。
  2. Post 一个完整的代码示例,专家可以更快地识别它。

首先,不再支持 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');
...

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