PostgreSQL cannot begin/end transactions in PL/pgSQL

前端 未结 2 597
悲哀的现实
悲哀的现实 2020-12-16 09:28

I am seeking clarification of how to ensure an atomic transaction in a plpgsql function, and where the isolation level is set for this particular change to the database.

相关标签:
2条回答
  • 2020-12-16 10:01

    A plpgsql function automatically runs inside a transaction. It all succeeds or it all fails. The manual:

    Functions and trigger procedures are always executed within a transaction established by an outer query — they cannot start or commit that transaction, since there would be no context for them to execute in. However, a block containing an EXCEPTION clause effectively forms a subtransaction that can be rolled back without affecting the outer transaction. For more about that see Section 42.6.6.

    So, if you need to, you can catch an exception that theoretically might occur (but is very unlikely).
    Details on trapping errors in the manual.

    Your function reviewed and simplified:

    CREATE FUNCTION foo(v_weather text
                      , v_timeofday text
                      , v_speed text
                      , v_behavior text)
      RETURNS SETOF custombehavior AS
    $func$
    BEGIN
    
    DELETE FROM custombehavior
    WHERE  weather = 'RAIN'
    AND    timeofday = 'NIGHT'
    AND    speed = '45MPH';
    
    INSERT INTO custombehavior (weather, timeofday, speed, behavior)
    SELECT v_weather, v_timeofday, v_speed, v_behavior
    WHERE  NOT EXISTS (
       SELECT FROM defaultbehavior
       WHERE  a = 'RAIN'
       AND    b = 'NIGHT'
       AND    c = '45MPH'
       );
    
    RETURN QUERY
    SELECT * FROM custombehavior WHERE ... ;
    
    END
    $func$  LANGUAGE plpgsql;
    

    If you actually need to begin/end transactions like indicated in the title look to SQL procedures in Postgres 11 or later (CREATE PROCEDURE). Related:

    • In PostgreSQL, what is the difference between a “Stored Procedure” and other types of functions?
    0 讨论(0)
  • 2020-12-16 10:17
    START TRANSACTION;
    select foo() ;
    COMMIT;
    

    "Unfortunately Postgres has no stored procedures, so you always need to manage the transaction in the calling code" – a_horse_with_no_name

    Transaction in an exception block - how?

    0 讨论(0)
提交回复
热议问题