调试
您的功能正在做的事情可以做得更简单。语法错误的实际原因在这里:
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
看起来您正在尝试强制startDate
转换为timestamp
,这从一开始就是无稽之谈,因为您的参数startDate
已声明为timestamp
。
它也不起作用。我在这里引用手册:
为避免语法歧义,type '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
。
- 不要使用大小写混合的标识符,除非您确切地知道自己在做什么。
- 从结尾减去开头以获得正数或应用绝对值运算符。
@
由于减去日期(而不是减去时间戳,它产生一个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$;
同样的调用。