I want to convert this code in Postgres to something shorter that will do the same. I read about upsert but I couldn't understand a good way to implement that on my code. What I wrote works fine, but I want to find a more elegant way to write it. Hope someone here can help me! This is the query:
CREATE OR REPLACE FUNCTION insert_table(
in_guid character varying,
in_x_value character varying,
in_y_value character varying
)
RETURNS TABLE(response boolean) LANGUAGE 'plpgsql'
DECLARE _id integer;
BEGIN
-- guid exists and it's been 10 minutes from created_date:
IF ((SELECT COUNT (*) FROM public.tbl_client_location WHERE guid = in_guid AND created_date < NOW() - INTERVAL '10 MINUTE') > 0) THEN
RETURN QUERY (SELECT FALSE);
-- guid exists but 10 minutes hasen't passed yet:
ELSEIF ((SELECT COUNT (*) FROM public.tbl_client_location WHERE guid = in_guid) > 0) THEN
UPDATE
public.tbl_client_location
SET
x_value = in_x_value,
y_value = in_y_value,
updated_date = now()
WHERE
guid = in_guid;
RETURN QUERY (SELECT TRUE);
-- guid not exist:
ELSE
INSERT INTO public.tbl_client_location
( guid , x_value , y_value )
VALUES
( in_guid, in_x_value, in_y_value )
RETURNING id INTO _id;
RETURN QUERY (SELECT TRUE);
END IF;
END
guidbeing the primary key of tabletbl? Please show the core table definition (CREATE TABLEscript). Data types and constraints on involved columns are relevant. And always declare your version of Postgres.INSERT INTO ... ON CONFLICT ...is very limited in its expressiveness compared to ISO SQL'sMERGE- from what I can tell you cannot elide yourSELECT COUNT(*)...query, but you do need to wrap everything in aTRANSACTION, otherwise concurrent users could invalidate yourpublic.tbl_client_locationtable between theSELECT COUNT(*)and the INSERT/UPDATE statement.MERGE. See: postgresql.org/docs/15/sql-merge.html But it's not needed for this case. Also, a function is wrapped into a transaction automatically, and we certainly don't needcount(*)at all.