Need your help please , can't understand why i got the following error , i am not a professional postgresql developer ..
As you can see the function created , so why the function not exist occurred ?
create or replace function loginAttempt (u_email character varying, u_password character varying, date_time timestamptz, OUT attempt smallint) returns smallint AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email) VALUES (u_password, date_time, attempt_nu, email);
IF attempt = 3 THEN INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
END;
$$ LANGUAGE plpgsql;
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1);
ERROR: function loginattempt(unknown, unknown, timestamp with time zone, integer) does not exist
LINE 1: select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987',...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 8
You have defined the last parameter as an OUT parameter, that means you can't pass a value for it.
You need to use:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now());
As you are not writing to the parameter attempts I don't see a reason to define it as an out parameter to begin with. You can simply return the value if you need it:
create or replace function loginAttempt (u_email character varying, u_password character varying, u_date_time timestamptz, u_attempt smallint)
returns smallint
AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email)
VALUES (u_password, u_date_time, u_attempt, u_email);
IF u_attempt = 3 THEN
INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
return u_attempt;
END;
$$ LANGUAGE plpgsql;
As the value 1 is assumed to be an integer, you need to cast that value when calling the function:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1::smallint);
Online example: https://rextester.com/YNIQ55561
Related
PostgreSQL 14
TABLE
CREATE TABLE IF NOT EXISTS settings.tbl_tmp
(
pk_sys_qr_settings_id bigint NOT NULL DEFAULT nextval('settings.tbl_tmp_pk_sys_qr_settings_id_seq'::regclass),
sin_product smallint DEFAULT 0,
vhr_key character varying(10) COLLATE pg_catalog."default" NOT NULL,
vhr_value character varying(250) COLLATE pg_catalog."default",
CONSTRAINT tbl_tmp_pkey PRIMARY KEY (pk_sys_qr_settings_id),
CONSTRAINT tbl_tmp_vhr_key_key UNIQUE (vhr_key)
)
--FUNCTION 1 - CALL FROM fn_test
CREATE OR REPLACE FUNCTION fn_test1(sinProduct SMALLINT,
vhrKey VARCHAR(10),
vhrValue VARCHAR(250))
RETURNS VOID AS $$
BEGIN
INSERT INTO settings.tbl_tmp
(sin_product, vhr_key, vhr_value)
VALUES
(sinProduct, vhrKey, vhrValue);
END;
$$ LANGUAGE plpgsql;
FUNCTION 2
CREATE OR REPLACE FUNCTION fn_test(sinProduct SMALLINT,
vhrKey VARCHAR(10),
vhrValue VARCHAR(250))
RETURNS VOID AS $$
DECLARE
a SMALLINT;
BEGIN
BEGIN
SELECT * FROM fn_test1(1::SMALLINT, 'Anil-5'::VARCHAR(10), 'KV-5'::VARCHAR(250));
INSERT INTO settings.tbl_tmp
(sin_product, vhr_key, vhr_value)
VALUES
(sinProduct, vhrKey, vhrValue);
END;
END;
$$ LANGUAGE plpgsql;
--ERROR
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function fn_test(smallint,character varying,character varying) line 7 at SQL statement
SQL state: 42601
Quote from the manual
Sometimes it is useful to evaluate an expression or SELECT query but discard the result, for example when calling a function that has side-effects but no useful result value. To do this in PL/pgSQL, use the PERFORM statement:
As the called function doesn't return anything to begin with, it's safe to use perform.
So use:
perform fn_test1(1::SMALLINT, 'Anil-5'::VARCHAR(10), 'KV-5'::VARCHAR(250));
Instead of select * from fn_test(..)
As you are using Postgres 14, you could also use a procedure in both cases, as you don't want to return a result.
I've written a postgresql function shown as follows
CREATE OR REPLACE FUNCTION public."UpdateTx"(IN "instructionId" character varying,IN txdata character varying,IN txdetail character varying,IN txstatus character varying,IN resid character varying,IN "timestamp" bigint)
RETURNS character varying
LANGUAGE 'plpgsql'
VOLATILE
PARALLEL UNSAFE
COST 100
AS $BODY$DECLARE updateClause varchar;
BEGIN
IF instructionId = '' THEN
RAISE EXCEPTION 'instruction id is missing';
END IF;
IF txstatus = '' THEN
RAISE EXCEPTION 'tx status is missing';
END IF;
updateClause := CONCAT('txstatus= ', txstatus);
IF txData != '' THEN
updateClause = CONCAT(updateClause, ', ', 'txdata=', txdata);
END IF;
EXECUTE 'UPDATE transactions SET $1 WHERE instructionid=instructionid' USING updateClause;
END;
$BODY$;
So it expects 5 varchar & 1 bigint as input arguments.
I've tried to execute the following SQL query
Select UpdateTx('123'::varchar, 'test'::varchar, 'test'::varchar, 'test'::varchar, 'test2'::varchar, 4124::bigint)
but it keeps showing this error message
ERROR: function updatetx(character varying, character varying, character varying, character varying, character varying, bigint) does not exist
LINE 1: Select UpdateTx('123'::varchar, 'test'::varchar, 'test'::var...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 8
Is the syntax incorrect?
Appreciate any suggestions or answers :)
Your immediate problem is that your function is declared as case-sensitive (with surrounding double quotes), but you call it in a case-insensitive manner (without the quotes, which, to Postgres, is equivalent to all lower caps). The names just do not match.
But there is more to it:
the way you pass variables is not OK; instead of concatenating part of the query into variable updateClause, you should pass a parameter for each value that needs to be passed to the variable - but better yet, you don't actually need dynamic SQL for this
Don't use variables that conflict with column names
I suspect that you want nulls instead of empty string (it makes much more sense to indicate the "lack" of a value)
the function needs to return something
I also notice that you are not using all arguments that are passed to function
Here is a function code, that, at least, compiles. You can start from there and adapt it to your exact requirement:
CREATE OR REPLACE FUNCTION public.UpdateTx(
IN pInstructionId character varying,
IN pTxdata character varying,
IN pTxdetail character varying, -- not used in the function
IN pTxstatus character varying,
IN pResid character varying, -- not used in the function
IN pTimestamp bigint - - not used in the function
)
RETURNS character varying
LANGUAGE plpgsql
VOLATILE
PARALLEL UNSAFE
COST 100
AS $BODY$
BEGIN
IF pInstructionId IS NULL THEN
RAISE EXCEPTION 'instruction id is missing';
END IF;
IF pTxstatus IS NULL THEN
RAISE EXCEPTION 'tx status is missing';
END IF;
UPDATE transactions
SET txstatus = pTxstatus, txData = COALESCE(pTxdata, txData)
WHERE instructionid = pInstructionId;
RETURN 1; -- put something more meaningful here
END;
$BODY$;
You would invoke it as follows:
select UpdateTx(
'123'::varchar,
'test'::varchar,
'test'::varchar,
'test'::varchar,
'test2'::varchar,
4124::bigint
)
Demo on DB Fiddle
This is my query.
select origindept, `count(am_course_name)` as total_course
from am_courseoffered
group by origindept;
I am trying to create a function who will return this query.
CREATE OR REPLACE FUNCTION getcourse ()
RETURNS TABLE (
course_origindept character varying,
course_ count(am_course_name) character varying
)
AS $$
BEGIN
RETURN QUERY select origindept, count(am_course_name) as number_total_course
from am_courseoffered
group by origindept;
END; $$
LANGUAGE 'plpgsql';
There are some error in my function.
ERROR: syntax error at or near "character"
LINE 4: course_ count(am_course_name) character varying
How i create function who will return this query.
Off the top of my head, the count function should return a datatype of bigint, so I would think declaring the count as a varchar would cause a datatype mismatch. Something like this should fix that:
CREATE OR REPLACE FUNCTION getcourse ()
RETURNS TABLE (
course_origindept character varying,
course_count bigint -- change here
) AS $$
BEGIN
RETURN QUERY
select origindept, count(am_course_name) as number_total_course
from am_courseoffered
group by origindept;
END;
$$
LANGUAGE plpgsql;
I do have to ask, though... is this an academic exercise to understand functions? The use case is questionable enough, as a view would be more appropriate.
I want to execute this function. But it got error said
ERROR:
syntax error at or near ":="
LINE 7: select result:=MAX(path_history_id)as path INTO result from...
In this function I want to:
execute select with (MAX) and it will return maximum id from a table;
catch that value (it is an integer value);
put that value into last select query where condition.
I cant find a way in postgresql to do this.
CREATE OR REPLACE FUNCTION memcache(IN starting_point_p1 character varying, IN ending_point_p1 character varying)
RETURNS TABLE(path integer, movement_id_out integer, object_id_fk_out integer, path_history_id_fk_out integer, walking_distance_out real, angel_out real, direction_out character varying, time_stamp_out timestamp without time zone, x_coordinate_out real, y_coordinate_out real, z_coordinate_out real) AS
$BODY$
DECLARE result int;
BEGIN
select result:=MAX(path_history_id)as path INTO result from path_history_info where starting_point=starting_point_p1 and ending_point =ending_point_p1 and achieve='1';
return query
select * from movement_info where path_history_id_fk=result;
END;
$BODY$
LANGUAGE plpgsql
Syntax Error
The first query inside your function needs to be changed as follows:
select MAX(path_history_id)as path INTO result
from path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';
A single Query
You don't actually need a stored procedure for this. A single query can achieve the same result.
select * from movement_info where path_history_id_fk =
(SELECT MAX(path_history_id) FROM path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';
I am trying to create a function in postgres that would insert a row if it doesn't exist and return the row's id (newly created or existing).
I came up with this:
CREATE OR REPLACE FUNCTION
get_enttype(name character varying, module character varying)
RETURNS integer LANGUAGE SQL STABLE AS $$
SELECT typeid FROM enttypes WHERE name = $1 AND module = $2
$$;
CREATE OR REPLACE FUNCTION
ensure_enttype(name character varying, module character varying)
RETURNS integer LANGUAGE SQL AS $$
SELECT CASE WHEN get_enttype($1, $2) IS NULL
THEN
INSERT INTO enttypes(name, module) VALUES ($1, $2) RETURNING typeid
ELSE
get_enttype($1, $2)
END
$$;
It however raises a syntax error because of INSERT inside CASE. I managed to fix this problem by creating a separate function with this INSERT and using this function in CASE. It works as expected, but this fix seems a little strange. My question is - can I fix this without creating another function?
No, you can't use INSERT inside CASE in an sql function. You can, however:
Use a PL/PgSQL function with IF ... ELSE ... END statements; or
Use a writable common table expression (wCTE) or INSERT INTO ... SELECT query
Pure SQL can do it:
create or replace function ensure_enttype(
name character varying, module character varying
) returns integer language sql as $$
insert into enttypes(name, module)
select $1, $2
where get_enttype($1, $2) is null
;
select get_enttype($1, $2);
$$;