español - procedimientos y funciones oracle pl/sql
BEGIN-END bloquea las transacciones atómicas en PL/SQL (3)
Esta información debería ser fácil de encontrar, pero no he tenido suerte.
Cuando tengo un bloque BEGIN - END
en un PL / SQL, ¿se comporta como una transacción atómica, que intentará comprometerse al presionar el bloque END
y si algo sale mal revierte 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 "por defecto"?
EDITAR: estoy ejecutando un procedimiento almacenado y estoy usando un bloque implícito, creo.
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 utilice la opción EXCEPTIONS INTO, que no entraré aquí).
Si desea que un grupo de declaraciones se trate como una única transacción atómica, 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 forma, cualquier excepción hará que las declaraciones en este bloque se retrotraigan, pero las declaraciones que se ejecutaron antes de este bloque no se revertirán.
Tenga en cuenta que no incluyo un COMPROMISO; por lo general, prefiero que el proceso de llamada emita el compromiso.
Es cierto que un bloque BEGIN..END sin manejador de excepciones lo manejará automáticamente por usted:
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.
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 usuario actual.
Si se produce un error, la transacción realiza un ROLLBACK implícitamente.
Este es el comportamiento predeterminado para PL / SQL.
BEGIN
- Los bloques END
son los bloques de construcción de PL / SQL, y cada unidad PL / SQL está contenida en al menos uno de dichos bloques. Nesting BEGIN
- END
bloques dentro de bloques PL / SQL generalmente se hace 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 contiene 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. Solo puedes declarar esto por:
- Bloques PL / SQL anónimos de nivel superior (no anidados)
- Artículo de lista
- Funciones y procedimientos locales, independientes y empaquetados
- Métodos de un tipo de objeto SQL
- Activadores de base de datos
Referencia: Oracle