Return ID of last inserted row in PostgreSQL with RETURNING clause - postgresql

I've got a pretty simple function defined like so:
CREATE OR REPLACE FUNCTION create_new_order(....) RETURNS integer AS
$BODY$
BEGIN
PERFORM add_points_to_usage(client_id_p, date_in_p, total_points_p);
INSERT INTO orders (...) VALUES (...)
RETURNING ident;
END;
$BODY$ LANGUAGE plpgsql;
Where I'm struggling is how to actually RETURN the value stored in the ident field back via the RETURNING clause. I've tried setting the value to a variable but that either doesn't work or I'm just messing up the syntax.

You're missing the variable declaration, the INTO clause and the final RETURN:
CREATE OR REPLACE FUNCTION create_new_order(....) RETURNS integer AS
$BODY$
DECLARE
var_ident int;
BEGIN
PERFORM add_points_to_usage(client_id_p, date_in_p, total_points_p);
INSERT INTO orders (...) VALUES (...)
RETURNING ident INTO var_ident;
RETURN var_ident;
END;
$BODY$ LANGUAGE plpgsql;

Related

Create a stored procedure to Delete Records postgres

I have created a function to delete multiple records.In our table contain id as type uuid.
We get the input is like array of ids.
CREATE OR REPLACE FUNCTION public.deletetVersion(item_list uuid[])
RETURNS TABLE(id uuid[])
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
DELETE FROM version WHERE id = ANY(item_list);
END;
$BODY$;
SELECT * from deletetVersion(Array['b6ad1912-e4f1-4419-831a-c70df89ffd63','877898f0-2f3f-4890-a658-898e35ffee3a'])
But i got an error like:
Anyone please help me
ERROR: function deletetversion(text[]) does not exist
it is because the
Array['b6ad1912-e4f1-4419-831a-c70df89ffd63','877898f0-2f3f-4890-a658-898e35ffee3a']
is treated as text[]
try the following
Array['b6ad1912-e4f1-4419-831a-c70df89ffd63'::uuid,'877898f0-2f3f-4890-a658-898e35ffee3a'::uuid]
as a parameter to your function
for example
CREATE OR REPLACE FUNCTION public.test_uuid(item_list uuid[])
RETURNS TABLE(id uuid[])
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
SELECT item_list;
END;
$BODY$;
SELECT * from test_uuid(Array['b6ad1912-e4f1-4419-831a-c70df89ffd63'::uuid])
In case of deletion
CREATE OR REPLACE FUNCTION public.test_uuid(item_list uuid[])
RETURNS VOID
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
DELETE from tableName WHERE id = ANY(item_list);
END;
$BODY$;
Your function should return either setof uuid - i.e. a table of uuid-s - or uuid[]. I would prefer the first. You do not need PL/pgSQL, plain SQL is enough. So the function is:
create or replace function public.deletetVersion(item_list uuid[])
returns setof uuid language 'sql' as
$$
delete from version where id = any(item_list) returning id;
$$;
The version returning an array is a bit more complex:
create or replace function public.deletetVersion(item_list uuid[])
returns uuid[] language 'sql' as
$$
with t(d_id) as
(
delete from version where id = any(item_list) returning id
)
select array_agg(d_id) from t;
$$;
And - as #Ibrahimshamma says - you may need to cast the argument to uuid[].

Postgres INSERT IF parameter is not null

I have a function which takes a parameter, and I want to only insert that param into a table if it's not null. I'm trying something like this:
CREATE OR REPLACE FUNCTION app.some_function(
my_param integer)
RETURNS void
LANGUAGE 'sql'
COST 100
VOLATILE
AS $BODY$
INSERT INTO app.myTable(something)
VALUES(my_param)
ON CONFLICT(something) DO
UPDATE
SET --someConflictLogic
WHERE my_param <> '' AND my_param IS NOT NULL;
$BODY$;
I was hoping the WHERE clause here would cover me, but it's not the case. When I call this function with my_param as NULL, I get:
null value in column "something" violates not-null constraint
So it looks like it's still trying to insert it. How can I correct this condition?
You can turn the insert ... values () into aninsert ... select` with a where clause attached:
CREATE OR REPLACE FUNCTION app.some_function(my_param integer)
RETURNS void
LANGUAGE sql
VOLATILE
AS
$BODY$
INSERT INTO app.myTable(something)
select my_param
where my_param IS NOT NULL
and my_param <> ''
ON CONFLICT(something) DO
UPDATE
SET --someConflictLogic;
$BODY$;
The where clause you used only applies to the DO UPDATE part, not the "primary" insert part.
Unrelated, but: the name of the function language is an identifier. It should be quoted.
You may use IF..THEN and change to plpgsql function
CREATE OR REPLACE FUNCTION app.some_function(
my_param integer)
RETURNS void
LANGUAGE plpgsql
COST 100
VOLATILE
AS $BODY$
IF NULLIF(my_param,'') IS NOT NULL THEN
INSERT INTO app.myTable(something)
VALUES(my_param)
ON CONFLICT(something) DO
UPDATE
SET --someConflictLogic;
END IF;
$BODY$;

Execute update query with IN clause in postgres function

I am trying to create a PostgreSQL function which will update a list of rows. So I want to take a list of text[] as an argument and use the IN clause to execute the query. Also, i want to get the number of rows updated as a returned value.
This worked for me:
CREATE FUNCTION set_mail_isbeingused(list_of_mail_names text[]) RETURNS void AS $$
BEGIN
FOR i in 1 .. array_upper(list_of_mail_names,1)
LOOP
UPDATE mail_isbeingused set isbeingused = 'true' where mailname = list_of_mail_names[i];
END LOOP;
END;
$$
LANGUAGE plpgsql;
But i want to execute it in one update query with IN clause.
CREATE FUNCTION set_mail_isbeingused(list_of_mail_names text[]) RETURNS void AS $$
BEGIN
UPDATE mail_isbeingused set isbeingused = 'true' where mailname in list_of_mail_names;
END;
$$
LANGUAGE plpgsql;
This is what I have been trying to do. Can somebody help me in fixing this?
You need to use the ANY operator with an array. You can't use IN
To obtain the number of rows update, use GET DIAGNOSTICS
CREATE FUNCTION set_mail_isbeingused(list_of_mail_names text[])
RETURNS integer --<< you need to change the return type
AS $$
DECLARE
l_rows integer;
BEGIN
UPDATE mail_isbeingused
set isbeingused = true
where mailname = ANY (list_of_mail_names);
GET DIAGNOSTICS l_rows = ROW_COUNT; --<< get the number of affected rows
RETURN l_rows;
END;
$$
LANGUAGE plpgsql;
Boolean constants don't need to be put into single quotes true is a boolean value 'true' is a string constant.

How do I return the result of a RETURNING clause from a plpgsql function?

I would like to have a fairly generic function that takes an INSERT, UPDATE, or DELETE, which might contain a RETURNING clause, and return that result. A fairly contrived example might be something like this:
CREATE FUNCTION my_insert(sql_insert TEXT) RETURNS record AS $$
DECLARE
result record;
BEGIN
EXECUTE sql_insert INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql;
SELECT my_insert('INSERT INTO foo VALUES (1) RETURNING some_column, another_column');
While this works ok, I don't think that record is the right type here, because RETURNING typically returns a table type. I'd like to return the exact same format from my function as RETURNING does, but I'm not sure how.
Returning record is fine, as long as the SELECT from the function defines the table structure:
SELECT * FROM my_insert('INSERT INTO foo VALUES (1) RETURNING some_column, another_column)
AS f(some_column bigint, another_column timestamp);
If the return value from the my_insert function is always going to be of a certain type, a composite type is maybe a better way to go:
CREATE TYPE my_insert_result AS (
some_column bigint,
another_column timestamp
);
And then change the function to return that type:
CREATE FUNCTION my_insert(sql_insert TEXT) RETURNS my_insert_result AS $$
DECLARE
result my_insert_result;
BEGIN
EXECUTE sql_insert INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM my_insert('INSERT INTO foo VALUES (1) RETURNING some_column, another_column');

function which returns as hstore datatype in postgresql

"hstoredata" is a variable of type hstore which contains key value pairs.
i.e. for ex: "hstoredata" variable contains the key value pairs '"ed"=>"1", "id"=>"1", "age"=>"27"'.
If "hstoredata" variable is passed to the function i.e select sampletest(hstoredata), function is returning as null.
-- Function: sampletest(hstore)
-- DROP FUNCTION sampletest(hstore)
CREATE OR REPLACE FUNCTION sampletest(hstoredata hstore)
RETURNS SETOF void AS
$BODY$
DECLARE
newhstoredata hstore;
BEGIN
newhstoredata := samplehstore(hstoredata);
RAISE NOTICE 'newhstoredata: %', newhstoredata;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION sampletest(hstore)
OWNER TO postgres;
Below is the program for function samplehstore(hstore)
-- Function: samplehstore(hstore)
-- DROP FUNCTION samplehstore(hstore)
CREATE OR REPLACE FUNCTION samplehstore(hstoredata hstore)
RETURNS SETOF void AS
$BODY$
BEGIN
RAISE NOTICE 'hstoredata: %', hstoredata;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION samplehstore(hstore)
OWNER TO postgres;
It's unclear what you're asking precisely, but based on the title, I assume you'd like your function to return something.
If so, the issue here is that you're declaring your function as returning setof void.
Declare it as returning whatever it should, and use return ... or return query ..., depending on what you actually need.