2

我正在尝试dateadd()使用 PL/PgSQL 编写一个函数。我希望能够添加从秒到年到日期/时间戳的任何内容。拼凑了一个功能(来自在线获得的片段等),并提出了这个“实现”:

CREATE OR REPLACE FUNCTION dateadd(diffType VARCHAR(15), incrementValue int, inputDate timestamp) RETURNS timestamp AS $$
DECLARE
   YEAR_CONST Char(15) := 'year';
   MONTH_CONST Char(15) := 'month';
   DAY_CONST Char(15) := 'day';
   HOUR_CONST Char(15) := 'hour';
   MIN_CONST Char(15) := 'min';
   SEC_CONST Char(15) := 'sec';

   dateTemp Date;
   intervals interval;
BEGIN
   IF lower($1) = lower(YEAR_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' year' as interval) into intervals;
   ELSEIF lower($1) = lower(MONTH_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' months' as interval) into intervals;
   ELSEIF lower($1) = lower(DAY_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' day' as interval) into intervals;
   ELSEIF lower($1) = lower(HOUR_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' hour' as interval) into intervals;
   ELSEIF lower($1) = lower(MIN_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' minute' as interval) into intervals;
   ELSEIF lower($1) = lower(SEC_CONST) THEN
       select cast(cast(incrementvalue as character varying) || ' second' as interval) into intervals;
   END IF;

   dateTemp:= inputdate + intervals;

   RETURN dateTemp;
END;
$$ IMMUTABLE LANGUAGE plpgsql;

但是,当我尝试使用该功能时,出现以下错误:

template1=# select dateadd('hour', 1, getdate());
ERROR:  function dateadd(unknown, integer, timestamp with time zone) does not exist
LINE 1: select dateadd('hour', 1, getdate());
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
template1=# 

为什么PG找不到该功能?

我在 Ubuntu 12.0.4 LTS 上运行 PG 9.3

4

2 回答 2

11

您会自责:出错的那一行(以及接下来的几行)与之前的那一行之间的区别在于您不小心在错误的位置添加了下划线:

你有

HOUR_CONST_Char(15) := 'hour';

它应该是

HOUR_CONST Char(15) := 'hour';

编辑

更新后的问题受到 Postgres 稍微挑剔的类型系统的影响:您的getdate()函数正在返回timestamp with time zone,但您dateadd接受timestamp(ie timestamp without time zone)。使用 Postgres 的简写value::type,这应该可以工作(SQLFiddle 演示,使用now()代替getdate()

select dateadd('hour', 1, getdate()::timestamp);

但是,您还有其他一些奇怪的类型选择:

  • 您的“常量”是Char(15),但不是 15 个字符长,因此将用空格填充;您可能应该使用VarChar(15),甚至只是text(与 MS SQL 不同,在 Postgres 中,所有字符串都动态存储在页外,并且 aVarChar本质上只是text具有最大长度约束)。
  • 您的中间变量(可能会被重构)是 type Date, not Timestamp,因此会将输入截断为仅日期部分,没有时间。

最后,我会注意到一个基本的优化:你不需要lower()你的常量,因为你已经知道它们是小写的。:)

于 2013-11-07T15:23:09.077 回答
0

它是 HOUR_CONST 和 Char(15) 之间的下划线 您应该输入“HOUR_CONST Char(15)”而不是“HOUR_CONST_Char(15)”

于 2013-11-07T15:22:56.383 回答