调试
你的函数正在做的事情可以简单得多。语法错误的实际原因在这里:
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
您似乎正在尝试将startDate 转换为timestamp,这首先是无稽之谈,因为您的参数startDate 已经声明为timestamp。
它也不起作用。我引用the manual here:
为避免语法歧义,类型'string'的语法只能是
用于指定简单文字常量的类型。
它会像这样工作:
SELECT EXTRACT(day FROM startDate - endDate)::int INTO diffDatePart;
但这仍然没有多大意义。您在谈论“日期”,但仍将您的参数定义为timestamp。你可以像这样对你拥有的东西进行消毒:
CREATE OR REPLACE FUNCTION f_date_diff()
RETURNS int AS
$BODY$
DECLARE
start_date date;
end_date date;
date_diff int;
BEGIN
SELECT evt_start_date FROM events WHERE evt_id = 5 INTO start_date;
SELECT evt_start_date FROM events WHERE evt_id = 6 INTO end_date;
date_diff := (endDate - startDate);
RETURN date_diff;
END
$BODY$ LANGUAGE plpgsql;
-
DECLARE 只需要一次。
-
date 列声明为正确类型 date。
- 请勿使用大小写混合的标识符,除非您确切知道自己在做什么。
- 从end中减去start得到一个正数或应用absolute value operator
@。
-
由于减去 日期(而不是减去 时间戳,得到 interval)已经得到 integer,简化为:
SELECT (startDate - endDate) INTO diffDatePart;
甚至更简单的 plpgsql 赋值:
diffDatePart := (startDate - endDate);
简单查询
您可以通过简单的查询来解决简单的任务 - 使用子查询:
SELECT (SELECT evt_start_date
FROM events
WHERE evt_id = 6)
- evt_start_date AS date_diff
FROM events
WHERE evt_id = 5;
或者您可以 CROSS JOIN 将基表添加到自身(每个实例 1 行,这样没关系):
SELECT e.evt_start_date - s.evt_start_date AS date_diff
FROM events e
,events s
WHERE e.evt_id = 6
AND s.evt_id = 5;
SQL 函数
如果你为了某个目的坚持一个函数,就用一个简单的sql函数:
CREATE OR REPLACE FUNCTION f_date_diff(_start_id int, _end_id int)
RETURNS int LANGUAGE sql AS
$func$
SELECT e.evt_start_date - s.evt_start_date
FROM events s, events e
WHERE s.evt_id = $1
AND e.evt_id = $2
$func$;
呼叫:
SELECT f_date_diff(5, 6);
PL/pgSQL 函数
如果你坚持使用 plpgsql ...
CREATE OR REPLACE FUNCTION f_date_diff(_start_id int, _end_id int)
RETURNS int LANGUAGE plpgsql AS
$func$
BEGIN
RETURN (SELECT evt_start_date
- (SELECT evt_start_date FROM events WHERE evt_id = _start_id)
FROM events WHERE evt_id = _end_id);
END
$func$;
同样的电话。