问题
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
回答1:
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:
- Your "constants" are
Char(15), but aren't 15 characters long, so will be padded with spaces; you should probably useVarChar(15), or even justtext(unlike MS SQL, in Postgres, all strings are stored out-of-page dynamically, and aVarCharis essentially justtextwith a maximum length constraint). - Your intermediate variable (which can probably be refactored out) is of type
Date, notTimestamp, 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. :)
回答2:
It's the underscore between HOUR_CONST and Char(15) You should enter "HOUR_CONST Char(15)" instead of "HOUR_CONST_Char(15)"
来源:https://stackoverflow.com/questions/19839650/pl-pgsql-no-function-matches-the-given-name-and-argument-types-you-might-need