Reputation: 68436
I am trying to write a dateadd()
function using PL/PgSQL. I want to be able to add anything from seconds, right up to years to a date/timestamp. have cobbled together a function (from snippets etc obtained online), and have come up with this "implementation":
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;
However, when I try to use the function, I get the following error:
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=#
Why is the function not being found by PG?
I am running PG 9.3 on Ubuntu 12.0.4 LTS
Upvotes: 2
Views: 52176
Reputation: 97783
You'll kick yourself: the difference between the line that's erroring (and the next few) and the one before it is that you've accidentally added an underscore in the wrong place:
You have
HOUR_CONST_Char(15) := 'hour';
It should be
HOUR_CONST Char(15) := 'hour';
EDIT
The updated question is suffering from Postgres's slightly fussy type system: your getdate()
function is returning timestamp with time zone
, but your dateadd
accepts a timestamp
(i.e. timestamp without time zone
). Using the Postgres short-hand for cast of value::type
, this should work (SQLFiddle demo, using now()
in place of getdate()
)
select dateadd('hour', 1, getdate()::timestamp);
However, you have a few other odd type selections:
Char(15)
, but aren't 15 characters long, so will be padded with spaces; you should probably use VarChar(15)
, or even just text
(unlike MS SQL, in Postgres, all strings are stored out-of-page dynamically, and a VarChar
is essentially just text
with a maximum length constraint).Date
, not Timestamp
, so will truncate the input to just the date part, no time.Finally, I'll note one fundamental optimisation: you don't need to lower()
your constants, because you already know they're lower case. :)
Upvotes: 11
Reputation: 493
It's the underscore between HOUR_CONST and Char(15) You should enter "HOUR_CONST Char(15)" instead of "HOUR_CONST_Char(15)"
Upvotes: 0