调试
你的函数所做的事情可以用更简单的方法来完成。导致语法错误的实际原因在这里:
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
看起来你试图将startDate
转换为timestamp
,但这本来就是无意义的,因为你的参数startDate
已经声明为timestamp
。
而且它也不起作用。我在这里引用手册中的话:
为避免语法歧义,“string”类型的语法只能用于指定简单文字常量的类型。
它会像这样工作:
SELECT EXTRACT(day FROM startDate - endDate)::int INTO diffDatePart;
但这仍然没有太多意义。你谈论的是“日期”,但仍将参数定义为时间戳
。你可以像这样进行清理:
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 以获得正数或使用绝对值运算符
@
。
由于减去日期(而不是减去时间戳,它产生一个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$;
同一个电话。