带有 CASE 的 Postgres 自定义函数
Posted
技术标签:
【中文标题】带有 CASE 的 Postgres 自定义函数【英文标题】:Postgres custom function with CASE 【发布时间】:2016-12-18 14:39:34 【问题描述】:我有桌子watchers
:
------------------------------------------
time_type | time_count | timestamp_created
------------------------------------------
'hour' | 1 | 2016-12-08 15:56:26.169614
'hour' | 13 | ...
'day' | 5 | ...
我尝试根据time_type
和time_count
值获取整数:
CREATE OR REPLACE FUNCTION af_calculate_range(tt text,tc integer) RETURNS integer AS $$
SELECT tt, CASE tt WHEN 'day' THEN tc * 60 * 60
WHEN 'hour' THEN tc * 60
END
FROM watchers;
$$
LANGUAGE SQL;
SELECT af_calculate_range(time_type, time_count) FROM watchers
但我得到一个错误:
ERROR: return type mismatch in function declared to return integer
DETAIL: Final statement must return exactly one column.
CONTEXT: SQL function "af_calculate_range"
********** Error **********
用法:
SELECT * FROM watchers
WHERE EXTRACT(EPOCH FROM now()) > (EXTRACT(EPOCH FROM timestamp_created) +
af_calculate_range(time_type, time_count) )
如果 time_type
= 'hour'
和 time_count
= 1
输出应该是 3600 秒。
我的例子有什么问题:
我用https://www.postgresql.org/docs/7.4/static/functions-conditional.html
和https://www.postgresql.org/docs/9.1/static/sql-createfunction.html
【问题讨论】:
您为什么要阅读完全过时版本 (7.4) 和已停产版本 (9.1) 的手册? 【参考方案1】:一个函数只能返回一个值,所以你可能打算这样做:
CREATE OR REPLACE FUNCTION af_calculate_range(tt text, tc integer) RETURNS integer AS $$
SELECT CASE WHEN tt = 'day' THEN tc * 60 * 60 -- return a (single) scalar
WHEN tt = 'hour' THEN tc * 60
END
FROM watchers;
$$
LANGUAGE SQL;
但正如@Mureinik 指出的那样,您甚至不需要做SELECT
;直接使用CASE
表达式即可。
【讨论】:
【参考方案2】:您不需要在那里进行查询,因为您将所有值传递给函数 - 只需返回 case
的值:
CREATE OR REPLACE FUNCTION af_calculate_range(tt TEXT, tc INTEGER)
RETURNS INTEGER IMMUTABLE AS $$
BEGIN
RETURN CASE tt WHEN 'day' THEN tc * 60 * 60
WHEN 'hour' THEN tc * 60
END;
END;
$$
LANGUAGE PLPGSQL;
【讨论】:
【参考方案3】:你太复杂了。改为存储interval
select now(), now() + interval '2 days';
now | ?column?
-------------------------------+-------------------------------
2016-12-19 05:23:51.856137-02 | 2016-12-21 05:23:51.856137-02
create table watchers (
the_interval interval,
timestamp_created timestamp
);
insert into watchers (the_interval, timestamp_created) values
('1 hour', '2016-12-08 15:56:26.169614');
现在查询将是:
select *
from watchers
where now() > timestamp_created + the_interval
;
the_interval | timestamp_created
--------------+----------------------------
01:00:00 | 2016-12-08 15:56:26.169614
【讨论】:
我是 sql 新手,它应该是什么样子? @snaggs:已编辑以上是关于带有 CASE 的 Postgres 自定义函数的主要内容,如果未能解决你的问题,请参考以下文章