简体   繁体   English

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

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

I am trying to create a simple function and I cannot seem to pass in a parameter into the date function. 我正在尝试创建一个简单的函数,但似乎无法将参数传递给date函数。
Here is the 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 '$2' day) and
       source = $1;

   RETURN totals;

END;
$totals$ LANGUAGE plpgsql;

This is invalid syntax: interval '$2' day . 这是无效的语法: interval '$2' day The variable isn't just swapped into place before the SQL is run, you need to pass the right kind of value to the function. 在运行SQL之前,变量不只是交换到位,还需要将正确的值传递给函数。

You probably meant to concatenate the string 'day' onto the end of the string ( text ) variable $2 , also known as days (not the literal string '$2' ). 您可能打算将字符串'day'连接到字符串( text )变量$2的末尾,也称为days (不是文字字符串'$2' )。 So $2 || 'day' 因此$2 || 'day' $2 || 'day' or days || 'day' $2 || 'day'days || 'day' days || 'day' . days || 'day'

Since this is then not a single literal, you need an explicit cast, not just a type label, so something like CAST($2 || 'day' AS interval) or (days || 'day')::interval . 因为这不是单个文字,所以您需要显式转换,而不仅仅是类型标签,因此需要使用CAST($2 || 'day' AS interval)(days || 'day')::interval

@IMSoP already shed light upon your syntax error. @IMSoP已经发现您的语法错误。 However, this can be simpler, faster and cleaner in multiple ways. 但是,这可以通过多种方式更简单,更快和更清洁。

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;
  • First of all, to subtract days from a date , you can can just subtract an integer number. 首先,要从date减去天数,您可以只减去一个integer Accordingly I use an integer parameter here. 因此,我在这里使用一个integer参数。

  • You don't need plpgsql for a simple function like this. 您不需要像这样的简单函数就可以使用plpgsql。 Use an SQL function instead - which can be "inlined" in the context of a bigger query, and thus optimized better in certain cases. 改用SQL函数 -在较大的查询上下文中可以“内联”,因此在某些情况下可以进行更好的优化。

  • The function can be STABLE : 该函数可以是STABLE

  • You had a naming conflict built into your function. 您的函数中存在命名冲突 source is obviously also a column name. source显然也是列名。 Try to avoid that. 尽量避免这种情况。 A common practice is to prepend variables and parameters with an underscore (which has no special meaning otherwise). 常见的做法是在变量和参数前加上下划线(否则没有特殊含义)。 You can also table-qualify column names and/or prepend parameter names with the function name (or use positional parameters) to be unambiguous. 您还可以使用函数名称(或使用位置参数)对列名和/或参数名进行表限定,以使它们明确。 I did both here. 我都在这里

  • Assuming id is your PK column and thus defined NOT NULL , count(*) does the same as count(id) , a bit shorter and cheaper. 假设id是您的PK列,因此定义了NOT NULLcount(*)count(id)相同,但更短,更便宜。 I cast to integer , because count() will return a bigint . 我将其转换为integer ,因为count()将返回bigint

However , going out on a limb here, I suspect your inaccurately named column createdate is not actually a date but a timestamp (essential table definition is missing in the question). 但是 ,在这里,我怀疑您命名不正确的列createdate实际上不是date而是timestamp (问题中缺少必需的表定义)。 In that case it's much more efficient to phrase the query differently: 在这种情况下,用不同的词组查询效率更高:

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;
  • This expression is sargable and thus more efficient. 此表达式可修饰 ,因此效率更高。 It can also use a plain index on (createdate) , or better on (source, createdate) - important for big tables. 它还可以在(createdate)上使用普通索引 ,或者在(source, createdate)上使用普通索引 -对于大表很重要。

  • Also demonstrating an alternative way to subtract days. 还演示了减去天数的另一种方法。 You can multiply the interval '1 day' . 您可以将interval '1 day'相乘。 Related: 有关:

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

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