Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Setzt Oracle die Transaktion bei einem Fehler zurück?

das ist eine interessante Frage!

Wenn Oracle auf einen Fehler stößt, wird die aktuelle Anweisung rückgängig gemacht , nicht die Transaktion. Eine Anweisung ist eine beliebige Anweisung der obersten Ebene, sie kann eine SQL-Anweisung (INSERT, UPDATE...) oder ein PL/SQL-Block sein.

Das bedeutet, wenn eine Anweisung (z. B. eine von Java aufgerufene pl/sql-Prozedur) einen Fehler zurückgibt, versetzt Oracle die Transaktion in den gleichen logischen Zustand wie vor dem Aufruf. Dies ist immens hilfreich, Sie müssen sich keine Gedanken über halb ausgeführte Prozeduren (**) machen.

Dieser Thread auf AskTom behandelt dasselbe Thema:

[die Anweisung] geschieht entweder VOLLSTÄNDIG oder VOLLSTÄNDIG NICHT, und die Art und Weise, wie dies funktioniert, ist, dass die Datenbank das logische Äquivalent zu Folgendem ausführt:

begin
   savepoint foo;
   <<your statement>>
exception
   when others then rollback to foo; 
                    RAISE;
end;

Dieses Feature ist meiner Meinung nach der Grund, warum es viel einfacher ist, Datenbankcode (*) in pl/sql zu schreiben als in jeder anderen Sprache.

(*) Code, der natürlich mit einer Oracle-DB interagiert, ich nehme an, die nativen prozeduralen Sprachen der anderen DBMS haben ähnliche Funktionen.

(**) Dies betrifft nur DML, da DDL in Oracle nicht transaktional sind. Seien Sie auch vorsichtig mit einigen DBMS-Paketen, die das Datenwörterbuch aktualisieren (wie DBMS_STATS ), nehmen sie häufig DDL-ähnliche Änderungen vor und geben Commits aus. Ziehen Sie im Zweifelsfall die Dokumentation zu Rate.

Aktualisierung: Dieses Verhalten ist eines der wichtigsten Konzepte in PL/SQL. Ich werde ein kleines Beispiel geben, um die Atomizität der pl/sql-Anweisungen zu demonstrieren :

SQL> CREATE TABLE T (a NUMBER);

Table created

SQL> CREATE OR REPLACE PROCEDURE p1 AS
  2  BEGIN
  3     -- this statement is successful
  4     INSERT INTO t VALUES (2);
  5     -- this statement will raise an error
  6     raise_application_error(-20001, 'foo');
  7  END p1;
  8  /

Procedure created

SQL> INSERT INTO t VALUES (1);

1 row inserted

SQL> EXEC p1;

begin p1; end;

ORA-20001: foo
ORA-06512: at "VNZ.P1", line 5
ORA-06512: at line 2

SQL> SELECT * FROM t;

         A
----------
         1

Oracle hat die Transaktion auf den Punkt kurz vor dem Aufruf von p1 zurückgesetzt. Es gibt keine halbe Arbeit. Es ist, als wäre die Prozedur p1 nie aufgerufen worden.