query has no destination for result data - PostgreSQL - sql

I have created the following stored procedure in PostgreSQL:
CREATE OR REPLACE function incomingdel(IN del_ID varchar) RETURNS VOID AS $$
DECLARE xyz integer;
BEGIN
SELECT * INTO xyz FROM incomingcheck(cast(del_ID as integer));
IF xyz <> 1
THEN
SELECT * INTO xyz FROM perfdel(cast(del_ID as integer));
END IF;
END
$$ LANGUAGE plpgsql
even though the function returns VOID, I am still getting
Error: query has no destination for result data
when i execute the function. Can someone please help?
Thanks

When you do SELECT * INTO ... in a PL/pgSQL function you need to supply a variable of type record or of the row type of the row source, even if the function only returns an integer. The functions incomingcheck(int) and perfdel(int) are obviously returning a single integer in which case you can simplify your function:
CREATE FUNCTION incomingdel(del_ID integer) RETURNS VOID AS $$
DECLARE
xyz integer;
BEGIN
xyz := incomingcheck(del_ID);
IF xyz <> 1 THEN
xyz := perfdel(del_ID);
END IF;
-- Do something with xyz
END; $$ LANGUAGE plpgsql;
If the functionality is actually in the called functions (so you do not process the xyz value), then it becomes simpler still:
CREATE FUNCTION incomingdel(del_ID integer) RETURNS VOID AS $$
BEGIN
IF incomingcheck(del_ID) <> 1 THEN
perfdel(del_ID);
END IF;
END; $$ LANGUAGE plpgsql;

Related

Return id of the deleted entry PostgreSQL

I have a function that delete an entry from my table. Also I need to return the id of the deleted entry.
CREATE OR REPLACE FUNCTION mydb.remove_item(item_id_param text)
RETURNS TABLE(id integer)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN QUERY
DELETE FROM mydb.items_table
WHERE item_id = item_id_param;
END;
$BODY$
When I execute the above function, it shows error as;
ERROR: cannot open DELETE query as cursor
CONTEXT: PL/pgSQL function mydb.remove_item(text) line 6 at RETURN QUERY
What is wrong in my function?
You need to use the RETURNING clause in order to return the IDs of the deleted rows:
CREATE OR REPLACE FUNCTION mydb.remove_item(item_id_param int)
RETURNS TABLE(id integer)
LANGUAGE plpgsql
AS $BODY$
BEGIN
RETURN QUERY
DELETE FROM mydb.items_table
WHERE item_id = item_id_param
RETURNING items_table.id; --<< this
END;
$BODY$
;
You do not need plpgsql for this. A simple scalar SQL function will do.
create or replace function mydb.remove_item(item_id_param int) returns int as
$BODY$
DELETE FROM mydb.items_table
WHERE item_id = item_id_param
RETURNING items_table.id;
$BODY$
language sql;

Call an Array result from select function to do update function with postgresql

I'm new with SQL functions and postgreSQL. I just try to select some mails of my compte table to update them afterwards so I create select and update functions but I have always the error:
"ERROR: query "SELECT emailAnonymisation()" returned more than one row
CONTEXT: PL/pgSQL function updateMail() line 5 during statement block local variable initialization"
The problem is in my update function but I don't know if it's only a variable problem or a function logical problem...
My select function
CREATE OR REPLACE FUNCTION emailAnonymisation()
RETURNS table (mail varchar)
LANGUAGE plpgsql
AS $$
BEGIN
return query
SELECT compte.mail
FROM compte
limit 100;
END
$$;
My update function where I call the emailAnonymisation() function and where the problem is I think
CREATE OR REPLACE FUNCTION updateMail()
RETURNS varchar[] AS
$BODY$
DECLARE
_tbl varchar[]:=emailAnonymisation();
t text;
BEGIN
FOREACH t IN ARRAY _tbl
LOOP
EXECUTE '
UPDATE ' || t || '
SET t = REPLACE(SUBSTR(t,LOCATE('#',t) + 1),"X")
WHERE LOCATE('#',t) > 0;';
END LOOP;
END;
$BODY$ LANGUAGE plpgsql;
the update call
select updateMail();
Try using SETOF:
CREATE OR REPLACE FUNCTION emailAnonymisation()
RETURNS SETOF string(mail varchar)
LANGUAGE plpgsql
AS $$
BEGIN
return query
SELECT compte.mail
FROM compte
limit 100;
END
$$;
Ok I have finally found what was the problem with the select I should have a return like this with RETURNS character varying[]
CREATE OR REPLACE FUNCTION emailAnonymisation()
RETURNS character varying[]
AS $$
DECLARE
result character varying[];
BEGIN
SELECT ARRAY( SELECT compte.mail as mail
FROM compte
WHERE mail IS NOT NULL
limit 100)
into result;
return result;
END;
$$
LANGUAGE plpgsql;
And for the update the same type as the select function
CREATE OR REPLACE FUNCTION updateMail()
RETURNS character varying(150) AS
$BODY$
DECLARE
_tbl character varying[]:=emailAnonymisation();
mail text;
endUrl text := '#mail.com';
BeginningUrl text := random_string(15);
BEGIN
FOREACH mail IN ARRAY _tbl
LOOP
UPDATE ' || t || '
SET t = REPLACE(SUBSTR(t,LOCATE('#',t) + 1),"X")
WHERE LOCATE('#',t) > 0;';
END LOOP;

How Do I use or properly return a value from my PostgreSQL function?

CREATE OR REPLACE FUNCTION data.first()
AS $BODY$
DECLARE
res numeric;
BEGIN
PERFORM data.second(5,3,4);
IF(res > 10)THEN
something
ELSEIF(res < 10)THEN
something else
END IF
END;
$BODY$;
=========================================
CREATE OR REPLACE FUNCTION data.second(
a numeric,
b numeric,
c numeric
OUT res numeric
)
RETURNS numeric
AS $BODY$
BEGIN
res = a + b;
END;
$BODY$;
How do I use res in the parent function?
don't specify both OUT and function returns:
t=# CREATE OR REPLACE FUNCTION data.second(
a numeric,
b numeric,
c numeric,
OUT res numeric
)
AS $BODY$
DECLARE
BEGIN
res = a + b;
END;
$BODY$ language plpgsql;
CREATE FUNCTION
if you want to use the return of function ,use select into VAR, perform will just execute function discarding its output:
t=# CREATE OR REPLACE FUNCTION data.first() returns text
AS $BODY$
DECLARE
res numeric;
BEGIN
SELECT data.second(5,3,4) INTO res;
IF(res > 5)THEN
raise info 'second returned %',res;
END IF;
RETURN 'here is the return';
END;
$BODY$ language plpgsql;
CREATE FUNCTION
finaly:
t=# select * from data.first();
INFO: second returned 8
first
--------------------
here is the return
(1 row)
https://www.postgresql.org/docs/current/static/plpgsql.html

PL/PgSQL Dynamic Subqueries

I am creating a trigger that runs a check raises an exception if it passes. To do this I need to use a dynamic call because I only have the table name as a string. I am using PostgreSQL but I can't figure out how there execute command works. When I do this:
CREATE OR REPLACE FUNCTION bleep() RETURNS table(id INT) AS $bleep$
BEGIN
RETURN QUERY EXECUTE 'SELECT (id) from Applicant';
END;
$bleep$ LANGUAGE plpgsql;
SELECT * from bleep();
It works perfectly and I get back a table of id's from Applicant. But when I do this:
CREATE OR REPLACE FUNCTION bleep() RETURNS BOOLEAN AS $bleep$
BEGIN
IF (EXISTS (EXECUTE 'SELECT (id) from Applicant')) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
$bleep$ LANGUAGE plpgsql;
It tells me:
ERROR: syntax error at or near "EXECUTE" Position: 87
This is just a toy example I made to figure out how this works and I have read lots of docs and guides. If I can figure out this toy example I can make the full trigger work since I tried it with hardcoding a table name. How can I make this work?
CREATE OR REPLACE FUNCTION bleep() RETURNS BOOLEAN AS $bleep$
DECLARE
res bool;
BEGIN
EXECUTE 'SELECT exists (select 1 from Applicant)' INTO res;
return res;
END;
$bleep$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION bleep() RETURNS BOOLEAN AS $bleep$
BEGIN
return query EXECUTE 'SELECT exists (select 1 from Applicant)';
END;
$bleep$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION bleep() RETURNS
BOOLEAN AS $bleep$
BEGIN
IF (EXISTS (SELECT id from Applicant)) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
$bleep$ LANGUAGE plpgsql;
I misunderstood your question.
How about this?
CREATE FUNCTION bleep(integer) RETURNS boolean
AS 'select case when count(*) = 0 then false else true end from Applicant where id = $1;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
You can test by SQLFiddle: http://sqlfiddle.com/#!15/33954/1

Declare a variable of a table type in postgres

I need to write a stored procudere like the following:
CREATE OR REPLACE FUNCTION foo() RETURNS TABLE(user_id integer, count bigint) AS $$
some_array integer[];
ret_val __WHAT_TYPE_;
BEGIN
FOR i IN 1 .. array_upper(some_array, 1)
LOOP
//modify the ret_val
END LOOP;
RETURN ret_val;
END $$
LANGUAGE plpgsql;
But I don't know what type of ret_val I should declare?
In a function returning a table you do not need a variable for returned value.
The columns of the table are treated as OUT parameters.
You can assign values to them and use RETURN NEXT, e.g.:
CREATE OR REPLACE FUNCTION foo()
RETURNS TABLE(user_id integer, counts bigint) AS $$
DECLARE
i integer;
BEGIN
FOR i IN 1..4
LOOP
user_id = i;
counts = i* i;
RETURN NEXT;
END LOOP;
END $$
LANGUAGE plpgsql;
SELECT * FROM foo();
user_id | counts
---------+--------
1 | 1
2 | 4
3 | 9
4 | 16
(4 rows)