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.