Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL: Rolling back a transaction within a plpgsql function?

Coming from the MS SQL world, I tend to make heavy use of stored procedures. I'm currently writing an application uses a lot of PostgreSQL plpgsql functions. What I'd like to do is rollback all INSERTS/UPDATES contained within a particular function if I get an exception at any point within it.

I was originally under the impression that each function is wrapped in it's own transaction and that an exception would automatically rollback everything. However, that doesn't seem to be the case. I'm wondering if I ought to be using savepoints in combination with exception handling instead? But I don't really understand the difference between a transaction and a savepoint to know if this is the best approach. Any advice please?

CREATE OR REPLACE FUNCTION do_something(
         _an_input_var int
                ) RETURNS bool AS $$
        DECLARE
                _a_variable int;
        BEGIN
                INSERT INTO tableA (col1, col2, col3)
                        VALUES (0, 1, 2);

                INSERT INTO tableB (col1, col2, col3)
                        VALUES (0, 1, 'whoops! not an integer');

                -- The exception will cause the function to bomb, but the values 
                -- inserted into "tableA" are not rolled back.    

                RETURN True;
END; $$ LANGUAGE plpgsql;
like image 256
jamieb Avatar asked Mar 11 '10 02:03

jamieb


2 Answers

A function does represent a transaction. You do not have to wrap a function in BEGIN/COMMIT.

like image 75
Joshua D. Drake Avatar answered Sep 25 '22 17:09

Joshua D. Drake


You can't use commit or rollback command into the function, but you can use your function into a committed transaction,

BEGIN TRANSACTION; SELECT do_something(); COMMIT;

This SQL script only commits if there are no exceptions in do_something, then, it will rolling back the transaction of the function.

like image 38
Peter Krauss Avatar answered Sep 24 '22 17:09

Peter Krauss