This question already has an answer here:
PL/PgSQL calling a function inside a loop giving error
(1 answer)
Closed 6 years ago.
I have created two functions. I want to run that functions inside a main function. When I run the main function I get an error. How can I solve this problem?
NOTICE: The rows affected scrap_v15=0
CONTEXT: SQL statement "Select update_scrap_v15()"
PL/pgSQL function all_functions() line 15 at SQL statement
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 all_functions() line 15 at SQL statement
This is my first function
CREATE OR REPLACE FUNCTION update_scrap_v15() RETURNS void AS
$BODY$
DECLARE
scrap_d integer;
BEGIN
update public.scrap_v15_src t2 set scrap = 66 where scrap= 0 and il like '%src%';
GET DIAGNOSTICS scrap_d = ROW_COUNT;
RAISE NOTICE 'The rows affected scrap d=%', scrap_d;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update_scrap_v15()
OWNER TO postgres;
This is my second function
CREATE OR REPLACE FUNCTION scrap_type() RETURNS void AS
$BODY$
DECLARE
scrap_t integer;
BEGIN
update public.tmz_001 set scrap_type = '55';
update public.tmz_001 set scrap_dtu = '55';
GET DIAGNOSTICS scrap_t = ROW_COUNT;
RAISE NOTICE 'The rows affected scrap d=%', scrap_t;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION scrap_type()
OWNER TO postgres;
This is my main function
CREATE OR REPLACE FUNCTION all_functions() RETURNS void AS
$BODY$
DECLARE
adm_1 integer; adm_2 integer;
BEGIN
Select update_scrap_v15();
GET DIAGNOSTICS adm_1 = ROW_COUNT;
RAISE NOTICE 'affected=%', adm_1;
Select scrap_type();
GET DIAGNOSTICS adm_2 = ROW_COUNT;
RAISE NOTICE 'affected=%', adm_2;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION all_functions()
OWNER TO postgres;
In postgres if function returning void type that invoke by PERFORM.
Instead:
Select update_scrap_v15();
Use that:
PERFORM update_scrap_v15();
Related
When I try to run a PostgreSQL stored procedure including the "STRICT" option and a record variable (rec) as I try to save (run the create statement) I get the following error:
ERROR: syntax error at or near "rec"
LINE 14: INTO STRICT rec
I' am following the guidelines stated on the official documentation https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
where the only reference missing is that this can or can't be used inside a function or a stored procedure. I guess there should be a reasonable answer to this issue I couldn't found. I was able to succeed running an equivalent code inside a Do block, so it seams there is some incompatibility declaring a record type variable and functions.
This is the function code I was running:
CREATE OR REPLACE FUNCTION test_nodata()
RETURNS TABLE(id int, active boolean)
LANGUAGE plpgsql
AS $$
DECLARE
rec record;
tab VARCHAR ='text_maintenance_news';
BEGIN
RETURN QUERY
SELECT tm.id, tm.active
INTO STRICT rec
FROM text_maintenance_news tm
WHERE tm.active
LIMIT 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE 'Query from % has no data', tab;
END;
$$
As mentioned at the official documents, postgreSQL doesn't consider no data as an error but as a warning that the programmer must handle. Main reason to include the STRICT option.
Do block code (It works!) and result:
DO
LANGUAGE plpgsql
$$
DECLARE
rec record;
tab varchar = 'text_maintenance_news';
BEGIN
SELECT *
INTO STRICT rec
FROM text_maintenance_news
WHERE active
LIMIT 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE 'Query from % return no data', tab;
END;
$$
ERROR: Query from text_maintenance_news return no data
CONTEXT: PL/pgSQL function inline_code_block line 13 at RAISE
SQL state: P0001
I have 2 functions in Postgresql 9.3:
CREATE OR REPLACE FUNCTION Function_A(param_id integer, param_name text)
RETURNS void AS
$BODY$
DECLARE
my_id integer;
my_name text;
BEGIN
my_id = somefunction(param_id);
my_name = somefunction(param_name);
insert into tableA(id, name) values (my_id, my_name);
END
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION Function_A(integer, text)
OWNER TO postgres;
CREATE OR REPLACE FUNCTION Function_B(param_id bigint, param_name text)
RETURNS void AS
$BODY$
DECLARE
BEGIN
insert into tableC(id, name) values (param_id, param_name);
perform Function_A(param_id, param_name);
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION Function_B(bigint, text)
OWNER TO postgres;
So, I have problem, when Function A returns error, Function B does not insert data into table C.
I want something like this:
If Perform Function A returns error resume next, so my Function B can insert data into table C and continue without problem.
Is this possible?
Without the actual SQL code, we cannot actually help you that much. If you want to force a function to continue without caring about errors, then you can use SQL exception syntax
EXCEPTION WHEN OTHERS THEN
-- keep looping
END;
I created a function. I defined returning value void. But I want to show affected row count. How can I do?
CREATE OR REPLACE FUNCTION update() RETURNS void AS
$BODY$
BEGIN
update test_a set name='cde' where name='abc';
update test_b set name='mno' where name='klm';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update()
OWNER TO postgres;
you should look into GET DIAGNOSTICS, since this is a PLpgSQL function. You might also find the Postgres SQL extension RETURNING * for UPDATE/INSERTS useful.
CREATE OR REPLACE FUNCTION update() RETURNS void AS
$BODY$
DECLARE
a_count integer;
b_count integer;
BEGIN
update test_a set name='cde' where name='abc';
GET DIAGNOSTICS a_count = ROW_COUNT;
update test_b set name='mno' where name='klm';
GET DIAGNOSTICS b_count = ROW_COUNT;
RAISE NOTICE 'The rows affected by A=% and B=%', a_count, b_count ;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update()
OWNER TO postgres;
Depending on what you might want to achieve, the special boolean variable "FOUND" could serve; UPDATE, INSERT, and DELETE statements set FOUND true if at least one row is affected, false if no row is affected.
I follow this tutorial in order create a function
http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure
Here is the code
CREATE FUNCTION func1(vtoken character varying, ref1 refcursor, ref2 refcursor)
RETURNS SETOF refcursor AS $BODY$
DECLARE
rec record;
BEGIN
OPEN ref1 FOR
SELECT * FROM table1;
RETURN NEXT ref1;
OPEN ref2 FOR
SELECT * FROM table2;
RETURN NEXT ref2;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;
I want to create another function and call func1.
CREATE OR REPLACE FUNCTION script(vcodebar character varying)
RETURNS void AS
$BODY$
DECLARE
BEGIN
SELECT func1(vtoken,'details', 'amount');
FETCH ALL IN "details";
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
However I receive an error:
FETCH ALL IN "details";
I can not add BEGIN ... COMMIT before call func1, because it's wrapped in a block BEGIN ... END;
How can I use 2 refcursors from the func1 ?
The cursors returned from the function are closed as soon as the call to the function completes. You should wrap the block from the SELECT statement until after the last use of the cursors in a transaction block:
BEGIN
SELECT issue_ticket(vtoken, 'details', 'amount');
FETCH ALL IN "details";
-- More statements
COMMIT; -- or ROLLBACK
"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.