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

时间:2015-06-10 14:04:09

标签: sql postgresql parameter-passing plpgsql date-arithmetic

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

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 '$2' day) and
       source = $1;

   RETURN totals;

END;
$totals$ LANGUAGE plpgsql;

2 个答案:

答案 0 :(得分:0)

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

您可能打算将字符串'day'连接到字符串(text)变量$2的末尾,也称为days(不是文字字符串{{ 1}})。所以'$2'$2 || 'day'

由于这不是单个文字,因此您需要显式转换,而不仅仅是类型标签,因此类似days || 'day'CAST($2 || 'day' AS interval)

答案 1 :(得分:0)

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

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

  • 你不需要像这样的简单函数的plpgsql。使用 SQL函数代替 - 这可以是"内联"在更大的查询的上下文中,因此在某些情况下更好地优化。

  • 该功能可以是 STABLE

  • 您的功能内置了命名冲突source显然也是列名。尽量避免这种情况。通常的做法是在变量和参数前加下划线(否则没有特殊含义)。您还可以使用函数名称(或使用位置参数)对列名称和/或前缀参数名称进行表格限定,使其明确无误。我在这里做了两件事。

  • 假设id是您的PK列,因此定义为NOT NULLcount(*)count(id)的作用相同,更短,更便宜。我转向integer,因为count()将返回bigint

然而,在这里走出困境,我怀疑你的名字createdate不准确,实际上不是date而是timestamp(基本表定义)在问题中遗漏了)。在这种情况下,以不同方式表达查询效率要高得多:

CREATE OR REPLACE FUNCTION test(_source int, _days int)
  RETURNS integer AS
$func$
SELECT count(*)::int
FROM   ad a
WHERE  a.source = $1
AND    a.createdate >= now() - interval '1 day' * $2
AND    a.createdate <  now() - interval '1 day' * ($2 - 1)
$func$ LANGUAGE sql STABLE;
  • 此表达式为sargable,因此效率更高。它还可以在(createdate)上使用简单的索引,或者在(source, createdate)上使用更好 - 对于大型表格非常重要。

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