How to quit a plpgsql procedure - postgresql

In my plpgsql procedure, I start with checking if primary key for the input table exists. If not I raise a notice and want to quit the procedure. Otherwise, I continue with the rest of procedure. I spent a bit of time searching online but no clear answer. Please note that I am referring to a procedure which doesn't return anything so I can't use RETURN.

You can use return.
create or replace procedure test(text)
language plpgsql as $$
begin
raise notice '%', $1;
return;
raise notice 'never executed';
end $$;
call test('hello');
NOTICE: hello
CONTEXT: PL/pgSQL function test(text) line 3 at RAISE
CALL

Related

How to execute PostgreSQL function at specific time interval?

Is there anything similar to setTimeout setTimeInterval in PostgreSQL which allows to execute piece of code (FUNCTION) at specified time interval?
As far as I know only thing that can execute a FUNCTION according to certain event is Triggers but it is not time based but operation driven (INSERT / UPDATE / DELETE / TRUNCATE)
While I could do this in application code, but prefer to have it delegated to database. Anyway I could achieve this in PostgreSQL? May be an extension?
Yes, there is a way to do this. It's called pg_sleep:
CREATE OR REPLACE FUNCTION my_function() RETURNS VOID AS $$
BEGIN
LOOP
PERFORM pg_sleep(1);
RAISE NOTICE 'This is a notice!';
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT my_function();
This will raise the notice every second. You can also make it do other things instead of raising a notice.
OR
You can use PostgreSQL's Background Worker feature.
The following is a simple example of a background worker that prints a message every 5 seconds:
CREATE OR REPLACE FUNCTION print_message() RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'Hello, world!';
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION schedule_print_message() RETURNS VOID AS $$
DECLARE
job_id BIGINT;
BEGIN
SELECT bgw_start_recurring_job(
'print-message',
'print_message',
'5 seconds'
) INTO job_id;
END;
$$ LANGUAGE plpgsql;
SELECT schedule_print_message();

How to re-create function with same name in postgres?

I need to re-create a group of functions but I don't want to check their parameters to use drop if there are functions with the same names but different parameters.
Is this possible to drop/recreate them only by name?
Or is this possible to catch exceptions, raise errors and continue to execute the transaction?
I'm trying to do it using
DO $$
BEGIN
BEGIN
CREATE OR REPLACE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN duplicate_function THEN RAISE NOTICE 'already exists';
END;
END;
$$;
But It completes scripts quietly and does not raise any errors.
You are correct in that 42723 is raised when a named object already, However, it is not a named exception. Thus your exception handles does not recognized, so it takes no action. You can get what you want by directly referencing the SQLSTATE and your error code.
DO $$
BEGIN
BEGIN
CREATE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN SQLSTATE '42723' THEN RAISE NOTICE 'already exists';
END;
END;
$$;
Raise notice sends the text following to sysout, which is often not accessible in a production system. You might want to change to raise exception.

call procedure from a function in postgresql

I have a procedure which has commit in it (postgresql v11), would like to call his procedure from a function. Getting below error as the procedure has commit, when commit is removed it works fine. Is there any work around to be able to call procedure with transaction control statements from a function (I know function does not support transactions and thats why its failing, but want to know if there is any alternative?)
CREATE OR REPLACE FUNCTION public.f()
RETURNS text
LANGUAGE plpgsql
AS $function$
BEGIN
raise notice 'Starting Function!!!';
call public.p();
return 'success' ;
END;
$function$;
CREATE OR REPLACE PROCEDURE public.p() LANGUAGE plpgsql AS $$
DECLARE src_schema TEXT;
BEGIN
raise notice 'Starting Procedure!!!';
commit;
RETURN;
END;
$$;
-- if the procedure has commit then its failing
imaods=> select public.f();
NOTICE: Starting Function!!!
NOTICE: Starting Procedure!!!
ERROR: invalid transaction termination
CONTEXT: PL/pgSQL function p() line 5 at COMMIT
SQL statement "CALL public.p()"
PL/pgSQL function f() line 4 at CALL
-- if the commit is removed from the procedure then it works fine
imaods=> CREATE OR REPLACE PROCEDURE public.p() LANGUAGE plpgsql AS $$
imaods$> DECLARE src_schema TEXT;
imaods$> BEGIN
imaods$> raise notice 'Starting Procedure!!!';
imaods$> RETURN;
imaods$> END;
imaods$> $$;
CREATE PROCEDURE
imaods=>
imaods=> select public.f();
NOTICE: Starting Function!!!
NOTICE: Starting Procedure!!!
f
---------
success
(1 row)
The documentation explains that:
Transaction control is only possible in CALL or DO invocations from the top level or nested CALL or DO invocations without any other intervening command. For example, if the call stack is CALL proc1() → CALL proc2() → CALL proc3(), then the second and third procedures can perform transaction control actions. But if the call stack is CALL proc1() → SELECT func2() → CALL proc3(), then the last procedure cannot do transaction control, because of the SELECT in between.
The reason is that you cannot have transaction management in PostgreSQL functions.

Amazon redshift stored procedure, CONTINUE cannot be used outside a loop;

Im building a stored procedure in amazon redshift.
This is an example of what im trying to do.
CREATE OR REPLACE PROCEDURE test_sp1()
LANGUAGE plpgsql
AS $$
DECLARE v_test RECORD;
BEGIN
FOR v_test IN select * from pg_user
LOOP
RAISE INFO 'before loop';
CONTINUE;
RAISE INFO 'after loop';
END LOOP;
END;
$$;
CALL test_sp1();
This piece of code gives me an exception
"[42601][500310] Amazon Invalid operation: CONTINUE cannot be used outside a loop".
Why can i not use continue in this loop?
The error appears to be happening when CONTINUE passes control to the beginning of the loop but there's no more iterating to be done.

How to run a PostgreSQL function

I am struggling to execute a PostgreSQL function. I am trying to read the documentation on the side but still no use. I am using Toad Extension for eclipse to develop/run the function
So far, this is what I have written
CREATE OR REPLACE FUNCTION dbName.function_name()
RETURNS VOID AS
$BODY$
DECLARE
x_cur CURSOR FOR select * from dbName.x;
x_row RECORD;
BEGIN
OPEN x_cur;
RAISE NOTICE 'Cursor opened';
LOOP
FETCH x_cur INTO x_row;
EXIT WHEN NOT FOUND;
END LOOP;
CLOSE x_cur;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
I executed the script and then ran select dbName.function_name(); in the sql worksheet and I don't see any output.
I remember writing functions on plsqldeveloper was so easy and interactive and i am struggling with PostgreSQL, could you guys help me getting a headstart.
I dont see any problem using pgAdmin.
The function return VOID, but the RAISE NOTICE show the message.
I simplify the function
CREATE OR REPLACE FUNCTION function_name()
RETURNS VOID AS
$BODY$
DECLARE
BEGIN
RAISE NOTICE 'Cursor opened';
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
And execute the function
SELECT function_name();