dette er et interessant spørgsmål!
Når Oracle støder på en fejl, ruller det den aktuelle erklæring tilbage , ikke transaktionen. En sætning er enhver instruktion på øverste niveau, den kan være en SQL-sætning (INSERT, UPDATE...) eller en PL/SQL-blok.
Det betyder, at når en sætning (for eksempel en pl/sql-procedure kaldet fra java) returnerer en fejl, vil Oracle sætte transaktionen i samme logiske tilstand som før opkaldet. Dette er enormt nyttigt, du behøver ikke bekymre dig om halvt udførte procedurer (**).
Denne tråd på AskTom dækker det samme emne:
[udsagnet] sker enten HELT, eller også sker det HELT IKKE, og den måde, der fungerer på, er, at databasen gør det logiske svar til:
begin
savepoint foo;
<<your statement>>
exception
when others then rollback to foo;
RAISE;
end;
Denne funktion er efter min mening grunden til, at det er meget nemmere at skrive databasekode (*) i pl/sql end på noget andet sprog.
(*) kode, der interagerer med en Oracle DB selvfølgelig, jeg formoder, at de native proceduresprog i de andre DBMS har lignende funktioner.
(**) Dette vedrører kun DML, da DDL ikke er transaktionelle i Oracle. Vær også forsigtig med nogle DBMS-pakker, der opdaterer dataordbogen (såsom DBMS_STATS
), laver de ofte DDL-lignende ændringer og udsteder commits. Se dokumentationen i tilfælde af tvivl.
Opdatering: denne adfærd er et af de vigtigste begreber i PL/SQL, jeg vil give et lille eksempel for at demonstrere atomiciteten af pl/sql-udsagn :
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 har rullet transaktionen tilbage til punktet, lige før du kalder p1. Der er ikke udført halvt arbejde. Det er, som om proceduren p1 aldrig var blevet kaldt.