Postgresql function invocation - postgresql

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

Related

function does not exists in postgreSQL .. Why ?

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

postgresql create function dynamically insert value into different table

I want to create a function that can dynamically insert any data type value into any table and multiple columns. But my function can only insert one value to one column:
CREATE OR REPLACE FUNCTION public.dynamic_insert(
tablename character varying,
columname character varying,
datatype character varying,
valuee text
)
RETURNS void
LANGUAGE 'plpgsql'
COST 100
VOLATILE AS
$BODY$
begin
Execute format('insert into %I ('||columname||')
values (cast($1 as '||datatype||'))',tablename,columname);
end;
$BODY$;
Can any one help?
I don't understand your idea clearly. I guess that you want to write one function to insert into table with list of column and values you specify.
If I guess correctly. I suggest some function like this:
CREATE OR REPLACE FUNCTION public.dynamic_insert(
tablename character varying,
columname character varying[],
datatype character varying[],
valuee character varying[]
)
RETURNS void AS
$BODY$
DECLARE
var_sql varchar;
var_sql_column varchar := '';
var_sql_values varchar := '';
begin
var_sql_column := CONCAT('("',ARRAY_TO_STRING(columname, '","'),'")');
FOR i IN 1..ARRAY_LENGTH(columname,1)
LOOP
var_sql_values := var_sql_values || quote_literal(valuee[i]) || '::' || datatype[i] || ',';
END LOOP;
var_sql_values := CONCAT('(',regexp_replace(var_sql_values, ',$', '', 'g'),')');
var_sql := CONCAT('INSERT INTO ', quote_ident(tablename), var_sql_column, ' VALUES ', var_sql_values);
IF (var_sql IS NOT NULL) THEN
EXECUTE(var_sql);
END IF;
end;
$BODY$;
LANGUAGE 'plpgsql'
COST 100
VOLATILE;
Hopefully it matches your require.
p/s: with my experience, just choose one solution between Format, and String concatenation, don't use both in one query, it makes me hard to view and find bug.
------------- Update for question below -----------------------------------
For the Loop please refer the document here
Basically, it will run from 1 to n (with n is the number elements in array) and build a query.
One simple thing to view how it run is you can put some print out data into you function, such as RAISE. Please refer it document here

Postgresql return text variable value

I created a function. Firstly I declared a variable When a result return I want to return variable result but I get an error. How can I solve?
Error
ERROR: column "exist-user" does not exist
CREATE OR REPLACE FUNCTION savepromotionadmin(
IN p_first_name character varying,
IN p_last_name character varying,
IN p_gsm character varying,
IN p_email character varying,
IN p_password character varying,
IN p_level smallint)
RETURNS text AS
$BODY$
DECLARE
result text;
p_user_id bigint=(select id from user where email=p_email and gsm=p_gsm);
p_check_user bigint=(select id from promotion_admin where email=p_email and gsm=p_gsm);
BEGIN
IF p_user_id is not null THEN
IF p_check_user is null THEN
insert into promotion_admin(user_id, first_name, last_name, gsm, email, level, password)
values(p_user_id, p_first_name, p_last_name, p_gsm, p_email, p_level, md5(p_password));
IF found THEN
result:="added";
return result;
ELSE
result:="error";
return result;
END IF;
ELSE
result:="exist-user";
return result;
END IF;
ELSE
result:="error";
return result;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 1000;
When you assign a data to a variable, you use the quote literal sign '. The quote indent sign " is for specify name of database object such as database name, table name, column name.
So, the code result:="exist-user" will assign data of column exist-user to variable result, and of course that column is not exists.
You can read more here
The " are only for object-names (tables, columns etc.), for text you have to use '
change result:="added"; to result:='added'; and everything is fine

write a function in pl/pgsql

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.

How to call a function, PostgreSQL

I'm trying to use a function with PostgreSQL to save some data. Here is the create script:
-- Function: "saveUser"(integer, character varying, character varying, character varying, character varying, character varying)
-- DROP FUNCTION "saveUser"(integer, character varying, character varying, character varying, character varying, character varying);
CREATE OR REPLACE FUNCTION "saveUser"("pUserID" integer, "pName" character
varying, "pLastName" character varying, "pUserName" character varying,
"pPassword" character varying, "peMail" character varying)
RETURNS boolean AS
$BODY$
BEGIN
SELECT 1
FROM "USERS"
WHERE "userID" = $1;
IF FOUND THEN
UPDATE "USERS"
SET "name" = $2,
"lastName" = $3,
"userName" = $4,
"password" = $5,
"eMail" = $6
WHERE "userID" = $1;
ELSE
INSERT INTO "USERS"
("name", "lastName", "userName", "password", "eMail")
VALUES
($2, $3, $4, $5, $6);
END IF;
END;$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION "saveUser"(integer, character varying, character varying, character varying, character varying, character varying) OWNER TO postgres;
PostreSQL Documentation states that to call a function which does not return any resultset, it is sufficient to write only its name and properties. So I try to call the function like this:
"saveUser"(3, 'asd','asd','asd','asd','asd');
But I get the error below:
ERROR: syntax error at or near ""saveUser""
LINE 1: "saveUser"(3, 'asd','asd','asd','asd','asd')
^
********** Error **********
ERROR: syntax error at or near ""saveUser""
SQL state: 42601
Character: 1
I have other functions which return a resultset. I use SELECT * FROM "fnc"(...) to call them and it works. Why am I getting this error?
EDIT: I am using pgAdmin III Query tool and trying to execute the SQL Statements there.
The function call still should be a valid SQL statement:
SELECT "saveUser"(3, 'asd','asd','asd','asd','asd');
For Postgresql you can use PERFORM. PERFORM is only valid within PL/PgSQL procedure language.
DO $$ BEGIN
PERFORM "saveUser"(3, 'asd','asd','asd','asd','asd');
END $$;
The suggestion from the postgres team:
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
We can have two ways of calling the functions written in pgadmin for postgre sql database.
Suppose we have defined the function as below:
CREATE OR REPLACE FUNCTION helloWorld(name text) RETURNS void AS $helloWorld$
DECLARE
BEGIN
RAISE LOG 'Hello, %', name;
END;
$helloWorld$ LANGUAGE plpgsql;
We can call the function helloworld in one of the following way:
SELECT "helloworld"('myname');
SELECT public.helloworld('myname')
if your function does not want to return anything you should declare it to "return void" and then you can call it like this "perform functionName(parameter...);"
I had this same issue while trying to test a very similar function that uses a SELECT statement to decide if a INSERT or an UPDATE should be done. This function was a re-write of a T-SQL stored procedure.
When I tested the function from the query window I got the error "query has no destination for result data". I finally figured out that because I used a SELECT statement inside the function that I could not test the function from the query window until I assigned the results of the SELECT to a local variable using an INTO statement. This fixed the problem.
If the original function in this thread was changed to the following it would work when called from the query window,
$BODY$
DECLARE
v_temp integer;
BEGIN
SELECT 1 INTO v_temp
FROM "USERS"
WHERE "userID" = $1;
you declare your function as returning boolean, but it never returns anything.