如何将参数传递给日期函数
How to pass a parameter into a date 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 '' day) and
source = ;
RETURN totals;
END;
$totals$ LANGUAGE plpgsql;
这是无效语法:interval '' day
。变量不只是在 SQL 变为 运行 之前交换到位,您需要将正确类型的值传递给函数。
您可能打算将字符串 'day'
连接到字符串 (text
) 变量 </code> 的末尾,也称为 <code>days
(不是文字字符串''
)。所以 || 'day'
或 days || 'day'
.
因为这不是一个单一的文字,你需要一个明确的转换,而不仅仅是一个类型标签,所以像 CAST( || 'day' AS interval)
或 (days || 'day')::interval
.
已经阐明了您的语法错误。但是,这可以通过多种方式更简单、更快和更清晰。
CREATE OR REPLACE FUNCTION test(_source int, _days int)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM ad a
WHERE a.source =
AND a.createdate::date = current_date -
$func$ LANGUAGE sql STABLE;
首先,要从 date
中减去天数,您可以 减去 integer
数字。因此,我在这里使用 integer
参数。
- How do I determine the last day of the previous month using PostgreSQL?
像这样的简单函数不需要 plpgsql。改用 SQL 函数 - 在更大查询的上下文中可以是 "inlined",因此在某些情况下优化得更好。
函数可以是STABLE
:
您的函数中存在 命名冲突。 source
显然也是一个列名。尽量避免这种情况。通常的做法是在变量和参数前加上下划线(否则没有特殊含义)。您还可以 table 限定列名称 and/or 在参数名称前加上函数名称(或使用位置参数)以使其明确。我在这里都做了。
假设id
是你的PK列,因此定义了NOT NULL
,count(*)
和count(id)
一样,更短更便宜。我转换为 integer
,因为 count() 将 return a bigint
.
但是,我怀疑你命名不准确的列 createdate
实际上不是 date
,而是 timestamp
(问题中缺少基本的 table 定义)。在这种情况下,以不同的方式表达查询会更有效:
CREATE OR REPLACE FUNCTION test(_source int, _days int)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM ad a
WHERE a.source =
AND a.createdate >= now() - interval '1 day' *
AND a.createdate < now() - interval '1 day' * ( - 1)
$func$ LANGUAGE sql STABLE;
这个表达式是 sargable,因此效率更高。它还可以在 (createdate)
上使用普通的 index,或者在 (source, createdate)
上使用更好 - 对于大 tables 很重要。
还展示了另一种减去天数的方法。您可以乘以 interval '1 day'
。相关:
- Query using two column values to create range
我正在尝试创建一个简单的函数,但似乎无法将参数传递给日期函数。
这是函数:
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 '' day) and
source = ;
RETURN totals;
END;
$totals$ LANGUAGE plpgsql;
这是无效语法:interval '' day
。变量不只是在 SQL 变为 运行 之前交换到位,您需要将正确类型的值传递给函数。
您可能打算将字符串 'day'
连接到字符串 (text
) 变量 </code> 的末尾,也称为 <code>days
(不是文字字符串''
)。所以 || 'day'
或 days || 'day'
.
因为这不是一个单一的文字,你需要一个明确的转换,而不仅仅是一个类型标签,所以像 CAST( || 'day' AS interval)
或 (days || 'day')::interval
.
CREATE OR REPLACE FUNCTION test(_source int, _days int)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM ad a
WHERE a.source =
AND a.createdate::date = current_date -
$func$ LANGUAGE sql STABLE;
首先,要从
date
中减去天数,您可以 减去integer
数字。因此,我在这里使用integer
参数。- How do I determine the last day of the previous month using PostgreSQL?
像这样的简单函数不需要 plpgsql。改用 SQL 函数 - 在更大查询的上下文中可以是 "inlined",因此在某些情况下优化得更好。
函数可以是
STABLE
:您的函数中存在 命名冲突。
source
显然也是一个列名。尽量避免这种情况。通常的做法是在变量和参数前加上下划线(否则没有特殊含义)。您还可以 table 限定列名称 and/or 在参数名称前加上函数名称(或使用位置参数)以使其明确。我在这里都做了。假设
id
是你的PK列,因此定义了NOT NULL
,count(*)
和count(id)
一样,更短更便宜。我转换为integer
,因为 count() 将 return abigint
.
但是,我怀疑你命名不准确的列 createdate
实际上不是 date
,而是 timestamp
(问题中缺少基本的 table 定义)。在这种情况下,以不同的方式表达查询会更有效:
CREATE OR REPLACE FUNCTION test(_source int, _days int)
RETURNS integer AS
$func$
SELECT count(*)::int
FROM ad a
WHERE a.source =
AND a.createdate >= now() - interval '1 day' *
AND a.createdate < now() - interval '1 day' * ( - 1)
$func$ LANGUAGE sql STABLE;
这个表达式是 sargable,因此效率更高。它还可以在
(createdate)
上使用普通的 index,或者在(source, createdate)
上使用更好 - 对于大 tables 很重要。还展示了另一种减去天数的方法。您可以乘以
interval '1 day'
。相关:- Query using two column values to create range