PostgreSQL使用双精度的Select into在PL / pgSQL函数中运行时始终返回null

时间:2015-07-27 23:06:14

标签: postgresql postgresql-8.4

我在PL / pgSQL中有一个函数试图为日期范围备份一些数据。我遇到的问题是我似乎无法将双精度存储在变量中。无论我做什么,在函数内部运行时,值始终为null。当我从psql命令行运行查询时,它返回正确的数据。我也可以在另一个不是double double类型的列上运行查询,它工作正常。例如,如果我将列更改为“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_horse_with_no_name和Patrick。这确实是一个问题,我所谓的收入与我的查询重叠。由于两个不起作用的查询都是双精度,我被抛弃了。恰好是那两个人也是我与列名称重叠的占位符。

要从中汲取的两件事。

  1. 我采用了a_horse_with_no_name建议的占位符的p_命名方案,以免再次遇到此问题。
  2. 发布一个完整的代码示例,专家可以更快地确定这一点。

1 个答案:

答案 0 :(得分:1)

首先,不再支持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,其中列名来自两个表中的任何一个。