web-dev-qa-db-fra.com

BEGIN - END bloquer les transactions atomiques en PL / SQL

Cette information devrait être facile à trouver, mais je n’ai pas eu de chance.

Quand j'ai un BEGIN - ENDbloque dans un fichier PL/SQL, se comporte-t-il comme une transaction atomique, essayant de s’engager en frappant le bloc END et, en cas de problème, annule les modifications?

Sinon, comment puis-je m'assurer que le code à l'intérieur du bloc BEGIN-END se comporte comme une transaction atomique et comment le bloc se comporte-t-il "par défaut"?

EDIT: Je cours à partir d’une procédure stockée et j’utilise un bloc implicite, je pense.

52
Jan Kratochvil

D'abord, BEGIN..END ne sont que des éléments syntaxiques et n’ont rien à voir avec des transactions.

Deuxièmement, dans Oracle, toutes les instructions DML individuelles sont atomiques (c’est-à-dire qu’elles réussissent intégralement ou annulent les modifications intermédiaires lors du premier échec) (sauf si vous utilisez l’option EXCEPTIONS INTO, que je ne décrirai pas ici).

Si vous souhaitez qu'un groupe d'instructions soit traité comme une transaction atomique unique, procédez comme suit:

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 cette manière, toute exception entraînera l'annulation des instructions de ce bloc, mais toutes les instructions exécutées avant ce bloc ne seront pas annulées.

Notez que je n'inclus pas de COMMIT - en général, je préfère que le processus appelant lance le commit.


Il est vrai qu'un bloc BEGIN..END sans gestionnaire d'exception le gérera automatiquement pour vous:

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

Si une exception est déclenchée, toutes les insertions et les mises à jour seront annulées. mais dès que vous souhaitez ajouter un gestionnaire d'exceptions, il ne sera pas restauré. Donc, je préfère la méthode explicite utilisant des points de sauvegarde.

67
Jeffrey Kemp

Les blocs BEGIN-END sont les blocs de construction de PL/SQL, et chaque unité PL/SQL est contenue dans au moins un de ces blocs. L'imbrication de blocs BEGIN-END au sein de blocs PL/SQL est généralement effectuée pour intercepter certaines exceptions et gérer cette exception spéciale, puis déclencher des exceptions non liées. Néanmoins, en PL/SQL, vous (le client) devez toujours émettre une validation ou une annulation pour la transaction.

Si vous souhaitez avoir des transactions atomiques dans une transaction contenant PL/SQL, vous devez déclarer un PRAGMA AUTONOMOUS_TRANSACTION dans le bloc de déclaration. Cela garantira que tout DML dans ce bloc peut être validé ou annulé indépendamment de la transaction qui le contient.

Cependant, vous ne pouvez pas déclarer ce pragma pour les blocs imbriqués. Vous ne pouvez le déclarer que pour:

  • Blocs PL/SQL anonymes de niveau supérieur (non imbriqués)
  • Élément de liste
  • Fonctions et procédures locales, autonomes et packagées
  • Méthodes d'un type d'objet SQL
  • Déclencheurs de base de données

Référence: Oracle

7
Wolf

Vous ne mentionnez pas s'il s'agit d'un bloc PL/SQL anonyme ou déclaratif, c'est-à-dire. Package, procédure ou fonction. Cependant, en PL/SQL, une COMMIT doit être faite explicitement pour enregistrer votre/vos transaction (s) dans la base de données. Le COMMIT enregistre toutes les transactions non enregistrées dans la base de données à partir de la session de votre utilisateur actuel .

Si une erreur se produit, la transaction effectue implicitement un ROLLBACK.

C'est le comportement par défaut pour PL/SQL.

0
OraNob