如何将参数传递给日期函数

How to pass a parameter into a date function

我正在尝试创建一个简单的函数,但似乎无法将参数传递给日期函数。
这是函数:

CREATE OR REPLACE FUNCTION test(source int,days text)
RETURNS integer AS $totals$
declare
    totals integer;
BEGIN

   select 
           count(id) into totals
     from  ad
    where
       createdate::date = date(current_date - interval '' day) and
       source = ;

   RETURN totals;

END;
$totals$ LANGUAGE plpgsql;

这是无效语法:interval '' day。变量不只是在 SQL 变为 运行 之前交换到位,您需要将正确类型的值传递给函数。

您可能打算将字符串 'day' 连接到字符串 (text) 变量 </code> 的末尾,也称为 <code>days(不是文字字符串'')。所以 || 'day'days || 'day'.

因为这不是一个单一的文字,你需要一个明确的转换,而不仅仅是一个类型标签,所以像 CAST( || 'day' AS interval)(days || 'day')::interval.

已经阐明了您的语法错误。但是,这可以通过多种方式更简单、更快和更清晰。

CREATE OR REPLACE FUNCTION test(_source int, _days int)
  RETURNS integer AS
$func$
SELECT count(*)::int
FROM   ad a
WHERE  a.source = 
AND    a.createdate::date = current_date - 
$func$  LANGUAGE sql STABLE;
  • 首先,要从 date 中减去天数,您可以 减去 integer 数字。因此,我在这里使用 integer 参数。

    • How do I determine the last day of the previous month using PostgreSQL?
  • 像这样的简单函数不需要 plpgsql。改用 SQL 函数 - 在更大查询的上下文中可以是 "inlined",因此在某些情况下优化得更好。

  • 函数可以是STABLE:

  • 您的函数中存在 命名冲突source 显然也是一个列名。尽量避免这种情况。通常的做法是在变量和参数前加上下划线(否则没有特殊含义)。您还可以 table 限定列名称 and/or 在参数名称前加上函数名称(或使用位置参数)以使其明确。我在这里都做了。

  • 假设id是你的PK列,因此定义了NOT NULLcount(*)count(id)一样,更短更便宜。我转换为 integer,因为 count() 将 return a bigint.

但是,我怀疑你命名不准确的列 createdate 实际上不是 date,而是 timestamp(问题中缺少基本的 table 定义)。在这种情况下,以不同的方式表达查询会更有效:

CREATE OR REPLACE FUNCTION test(_source int, _days int)
  RETURNS integer AS
$func$
SELECT count(*)::int
FROM   ad a
WHERE  a.source = 
AND    a.createdate >= now() - interval '1 day' * 
AND    a.createdate <  now() - interval '1 day' * ( - 1)
$func$ LANGUAGE sql STABLE;
  • 这个表达式是 sargable,因此效率更高。它还可以在 (createdate) 上使用普通的 index,或者在 (source, createdate) 上使用更好 - 对于大 tables 很重要。

  • 还展示了另一种减去天数的方法。您可以乘以 interval '1 day'。相关:

    • Query using two column values to create range