我正在尝试创建一个简单的函数,我似乎无法将参数传递给日期函数 这是功能:
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;
答案 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 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;
此表达式为sargable,因此效率更高。它还可以在(createdate)
上使用简单的索引,或者在(source, createdate)
上使用更好 - 对于大型表格非常重要。
还演示了减去天数的另一种方法。您可以乘以interval '1 day'
。相关: