[英]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 NULL
, count(*)
与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.