Search code examples
postgresqljdbctransactionscommitautocommit

Execute postgreSQL stored procedure as one transaction


I'm using PostgreSQL 9.3 and I have some stored procedures created which contains several statements. I'm calling this stored procedures in a Java application with the help of a prepared statement.

Now I've read that each statement inside the stored procedure is executed as a transaction, i.e. one commit after each statement. But what I want is to have the whole stored procedure executed as one transaction, i.e. only one commit.

How can I do this? Perhaps deactivating autocommit on the JDBC level?


Solution

  • Well, basically stored procedures are atomic in nature and executed as one transaction.

    CREATE TABLE xxx (id int PRIMARY KEY);
    
    CREATE OR REPLACE FUNCTION f() RETURNS void AS $$
    DECLARE
      len int;
    BEGIN
      RAISE NOTICE 'Transaction ID: %', TXID_CURRENT();
      INSERT INTO xxx VALUES (1);
    
      RAISE NOTICE 'Transaction ID: %', TXID_CURRENT();
      INSERT INTO xxx VALUES (2);
    
      RAISE NOTICE 'Transaction ID: %', TXID_CURRENT();
      SELECT COUNT(*) FROM xxx INTO len;
      RAISE NOTICE 'Number of records: %', len;
    
      RAISE NOTICE 'Transaction ID: %', TXID_CURRENT();
    
      -- results in unique constraint violation
      UPDATE xxx SET id = 3;
    END;
    $$ LANGUAGE plpgsql;
    

    Then try invoking f() from psql.

    stackoverflow=# show autocommit;
     autocommit 
    ------------
     on
    (1 row)
    
    stackoverflow=# SELECT f();
    NOTICE:  Transaction ID: 15086
    NOTICE:  Transaction ID: 15086
    NOTICE:  Transaction ID: 15086
    NOTICE:  Number of records: 2
    NOTICE:  Transaction ID: 15086
    ERROR:  duplicate key value violates unique constraint "xxx_pkey"
    DETAIL:  Key (id)=(3) already exists.
    CONTEXT:  SQL statement "UPDATE xxx SET id = 3"
    PL/pgSQL function f() line 20 at SQL statement
    
    stackoverflow=# SELECT * FROM xxx;
    id 
    ----
    (0 rows)