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