2012-08-15 13 views
44

Esta información debe ser fácil de encontrar, pero no he tenido suerte.BEGIN - END transacciones atómicas de bloque en PL/SQL

Cuando tengo un bloque BEGIN - END en un PL/SQL, ¿se comporta como una transacción atómica, que intentará comprometerse al golpear el bloque END y, si algo sale mal, retrotrae los cambios?

Si no, ¿cómo me aseguro de que el código dentro del bloque BEGIN - END se comporte como una transacción atómica y cómo se comporta el bloque "de forma predeterminada"?

EDITAR: Estoy ejecutando un procedimiento almacenado y estoy usando un bloque implícito, creo.

+0

Debe emitir instrucciones explícitas 'COMMIT' y' ROLLBACK' (quizás en una sección 'EXCEPTION') si ese es el comportamiento que está buscando. Si realmente desea una transacción atómica, busque AUTONOMOUS_TRANSACTIONS en Oracle. – Ollie

Respuesta

57

En primer lugar, BEGIN..END son elementos meramente sintácticos, y no tienen nada que ver con las transacciones.

En segundo lugar, en Oracle todas las sentencias DML individuales son atómicas (es decir, tienen éxito completo o restituyen cualquier cambio intermedio en la primera falla) (a menos que use la opción EXCEPTIONS INTO, que no entraré aquí) .

Si desea un grupo de instrucciones a ser tratada como una única transacción atómica, usted haría algo como esto:

BEGIN 
    SAVEPOINT start_tran; 
    INSERT INTO .... ; -- first DML 
    UPDATE .... ; -- second DML 
    BEGIN ... END; -- some other work 
    UPDATE .... ; -- final DML 
EXCEPTION 
    WHEN OTHERS THEN 
    ROLLBACK TO start_tran; 
    RAISE; 
END; 

De esta manera, cualquier excepción hará que las declaraciones en este bloque a laminar Atrás, pero las sentencias que se ejecutaron antes de este bloque no se revertirán.

Tenga en cuenta que no incluyo un COMPROMISO: generalmente prefiero el proceso de llamada para emitir el compromiso.


Es cierto que un bloque begin..end sin gestor de excepciones manejará automáticamente para el usuario:

BEGIN 
    INSERT INTO .... ; -- first DML 
    UPDATE .... ; -- second DML 
    BEGIN ... END; -- some other work 
    UPDATE .... ; -- final DML 
END; 

Si se produce una excepción, todas las inserciones y actualizaciones se revertirán ; pero tan pronto como quiera agregar un manejador de excepciones, no se revertirá. Por lo tanto, prefiero el método explícito de usar puntos de rescate.

+0

¿es una transacción si se usan bloques anidados con manejo de excepciones pero sin manejo de excepciones en el bloque principal/externo? –

+0

@JonnyLeeds, no, es una transacción cuando comienzas a ejecutar sentencias DML. –

0

No menciona si se trata de un bloque PL/SQL anónimo o declarativo, es decir. Paquete, procedimiento o función. Sin embargo, en PL/SQL, se debe hacer un COMMIT explícitamente para guardar sus transacciones en la base de datos. COMMIT en realidad guarda todas las transacciones no guardadas en la base de datos de la sesión de su usuario actual.

Si se produce un error, la transacción realiza implícitamente un ROLLBACK.

Este es el comportamiento predeterminado para PL/SQL.

+1

No estoy seguro de que sea correcto decir que la * transacción * realiza una reversión; cualquier cambio no confirmado realizado antes del bloque PL/SQL aún está pendiente y el cliente debe confirmarlo o revertirlo. Cualquier acción que se realice dentro del bloque se revertirá, como si se tratara de un punto de rescate, que creo que es a lo que se refiere. (Como de costumbre, [Tom explica mejor que yo]) (http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:43818437682131)). Tampoco estoy seguro si el OP está preguntando sobre un bloque anidado dentro de un bloque, y si los cambios en el bloque interno se confirmarán/revertirán de forma independiente. –

5

BEGIN - END bloques son los bloques de construcción de PL/SQL, y cada unidad PL/SQL está contenida en al menos uno de esos bloques. Anidando BEGIN - END, los bloques dentro de los bloques PL/SQL generalmente se hacen para atrapar ciertas excepciones y manejar esa excepción especial y luego plantear excepciones no relacionadas. Sin embargo, en PL/SQL usted (el cliente) siempre debe emitir un compromiso o reversión para la transacción.

Si desea tener transacciones atómicas dentro de una transacción que contenga PL/SQL, necesita declarar PRAGMA AUTONOMOUS_TRANSACTION en el bloque de declaración. Esto asegurará que cualquier DML dentro de ese bloque pueda comprometerse o retrotraerse independientemente de la transacción que lo contenga.

Sin embargo, no puede declarar este pragma para bloques anidados. Sólo se pueden declarar esto para:

  • -nivel superior (no anidado) anónimo bloques PL/SQL
  • elemento de la lista
  • local, independiente y funciones y procedimientos
  • métodos de un objeto SQL envasados escriba
  • Base de datos desencadena

Referencia: Oracle

Cuestiones relacionadas