繁体   English   中英

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

[英]How to pass a parameter into a date function

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

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;

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

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

因为这不是单个文字,所以您需要显式转换,而不仅仅是类型标签,因此需要使用CAST($2 || 'day' AS interval)(days || 'day')::interval

@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;
  • 此表达式可修饰 ,因此效率更高。 它还可以在(createdate)上使用普通索引 ,或者在(source, createdate)上使用普通索引 -对于大表很重要。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM