[ORACLE - dokumentacja] PL/SQL default EXCEPTION handler
=?iso-8859-2?Q?Piotr_Pli=BFga?= - 28-03-2006 00:02
[ORACLE - dokumentacja] PL/SQL default EXCEPTION handler
Witam, mam następujący problem. Tabela z jedną kolumną typu NUMBER(1)
Przypadek A)
1 SQL> INSERT INTO tabela VALUES(1); 2 SQL> INSERT INTO tabela VALUES('a'); 3 SQL> COMMIT;
w wyniku błędu w drugiej lini Oracle wykona "statement-level rollback", nastepnie COMMIT -> w tabeli znajdzie sie wiersz z lini 1 SQL> - dokładnie liczva JEDEN.
Działa tak - jak się spodziewamy :-)
Przypadek B) - to samo tylko blok PL/SQL
BEGIN INSERT INTO tabela VALUES(1); INSERT INTO tabela VALUES('a'); COMMIT; END; /
Proszę zwrócić uwagę, że nie ma bloku EXCEPTION.
Zadanie ======= Nie udało mi się znaleźć konstruktywnego wytłumaczenia w dokumentacji ORACLE-a (SQL, PL/SQL, Conncept), że w tym przypadku nastąpi obsługa błędu... no właśnie gdzie? Skoro nie ma bloku EXCEPTION?
Wiem, że nastąpi ROLLBACK i żaden z wierszy nie trafi do bazy danych, tylko gdzie dokładnie to jest napisane?
W całym zadaniu chodzi o spór akademicki typu "prove it works like designed"... i właściwie tylko o to... Gdyby był blok EXCEPTION i obsługa wyjątku to nie ma sporu :-)
Pozdrawiam, Piotr
Pozdrawiam, Piotr Pliżga -- Oracle Database Administrator www.metrogroup.pl
dap - 28-03-2006 00:02
Piotr Pliżga wrote: > Witam, > mam następujący problem. Tabela z jedną kolumną typu NUMBER(1) > > Przypadek A) > > 1 SQL> INSERT INTO tabela VALUES(1); > 2 SQL> INSERT INTO tabela VALUES('a'); > 3 SQL> COMMIT; > > w wyniku błędu w drugiej lini Oracle wykona "statement-level rollback", > nastepnie COMMIT -> w tabeli znajdzie sie wiersz z lini 1 SQL> - dokładnie > liczva JEDEN. > > Działa tak - jak się spodziewamy :-) > > Przypadek B) - to samo tylko blok PL/SQL > > BEGIN > INSERT INTO tabela VALUES(1); > INSERT INTO tabela VALUES('a'); > COMMIT; > END; > / > > Proszę zwrócić uwagę, że nie ma bloku EXCEPTION. > > Zadanie > ======= > Nie udało mi się znaleźć konstruktywnego wytłumaczenia w dokumentacji > ORACLE-a (SQL, PL/SQL, Conncept), że w tym przypadku nastąpi obsługa > błędu... no właśnie gdzie? Skoro nie ma bloku EXCEPTION? > > Wiem, że nastąpi ROLLBACK i żaden z wierszy nie trafi do bazy danych, tylko > gdzie dokładnie to jest napisane? > > W całym zadaniu chodzi o spór akademicki typu "prove it works like > designed"... i właściwie tylko o to... Gdyby był blok EXCEPTION i obsługa > wyjątku to nie ma sporu :-)
Moze tak: transaction
A logical unit of work that comprises one or more SQL statements executed by a single user. According to the ANSI/ISO SQL standard, with which Oracle is compatible, a transaction begins with the user's first executable SQL statement. A transaction ends when it is explicitly committed or rolled back by the user.
W 1 wypadku kazdy insert byl swoja wlasna transakcja, a w 2 transakcja zaczela sie od begin a zakonczyla, wiec 1 insert nie zostal uznany.
> BEGIN begin INSERT INTO tabela VALUES(0); end ;
> INSERT INTO tabela VALUES(1); > INSERT INTO tabela VALUES('a'); > COMMIT;
begin INSERT INTO tabela VALUES(3); end ;
> END; > /
wiecej tu When an error occurs, an exception is raised. That is, normal execution stops and control transfers to the exception-handling part of your PL/SQL block or subprogram. Internal exceptions are raised implicitly (automatically) by the run-time system. User-defined exceptions must be raised explicitly by RAISE statements, which can also raise predefined exceptions.
Wynika z tego,ze yyjatek jest zawsze robiony dla danego bloku (mozna dodac tez savepointy), bo w razie bledu szuka jego obslugi w bloku znajdujacym sie wyzej.
http://localhost/ora9i/appdev.920/a9..._errs.htm#1049
....ale ...
How Oracle Does Implicit Rollbacks
Before executing an INSERT, UPDATE, or DELETE statement, Oracle marks an implicit savepoint (unavailable to you). If the statement fails, Oracle rolls back to the savepoint. Normally, just the failed SQL statement is rolled back, not the whole transaction. However, if the statement raises an unhandled exception, the host environment determines what is rolled back.
If you exit a stored subprogram with an unhandled exception, PL/SQL does not assign values to OUT parameters. Also, PL/SQL does not roll back database work done by the subprogram.
http://localhost/ora9i/appdev.920/a9...6_ora.htm#1990
dap - 28-03-2006 00:02
begin begin insert into test2 values(0) ; -- commit ; end ;
insert into test2 values(1) ; insert into test2 values('a'); commit ;
begin insert into test2 values(3) ; commit ; end ;
end ; /
tu nie bedzie zadnego wpisu , bo w razi wyjatku caly wyjatek jest propagowany wyzjej ( do innego bloku, albo programu).
begin begin insert into test2 values(0) ; commit ; end ;
insert into test2 values(1) ; insert into test2 values('a'); commit ;
begin insert into test2 values(3) ; commit ; end ;
end ; /
to bedzie 0 bo commitem zaznaczylismy poczatek nowej transakcji.
Ja bym to tak rozumial...
dap
=?ISO-8859-2?Q?Pawe=B3_Matejski?= - 28-03-2006 00:02
Użytkownik Piotr Pliżga napisał: > Witam, > mam następujący problem. Tabela z jedną kolumną typu NUMBER(1) > > Przypadek A) > > 1 SQL> INSERT INTO tabela VALUES(1); > 2 SQL> INSERT INTO tabela VALUES('a'); > 3 SQL> COMMIT; > > w wyniku błędu w drugiej lini Oracle wykona "statement-level rollback", > nastepnie COMMIT -> w tabeli znajdzie sie wiersz z lini 1 SQL> - dokładnie > liczva JEDEN. > > Działa tak - jak się spodziewamy :-) > > Przypadek B) - to samo tylko blok PL/SQL > > BEGIN > INSERT INTO tabela VALUES(1); > INSERT INTO tabela VALUES('a'); > COMMIT; > END; > / > > Proszę zwrócić uwagę, że nie ma bloku EXCEPTION. > > Zadanie > ======= > Nie udało mi się znaleźć konstruktywnego wytłumaczenia w dokumentacji > ORACLE-a (SQL, PL/SQL, Conncept), że w tym przypadku nastąpi obsługa > błędu... no właśnie gdzie? Skoro nie ma bloku EXCEPTION?
W kliencie, którym tu pewnie jest SQL'plus, który wyswietlił wyjatek i czeka na następne polecenia.
> Wiem, że nastąpi ROLLBACK i żaden z wierszy nie trafi do bazy danych, tylko > gdzie dokładnie to jest napisane?
Nie nastąpi, jesli go nie wpiszesz. W tym drugim przypadku wciąż jestes w transakcji, tyle że pustej (choć tego nie jestem pewien, a nie mam jak sprawdzić). Inaczej mówiąc cofnięta nie została cała transakcja, a tylko ostatnia instrukcja (tu rozumiana przez wszystko pomiedzy BEGIN END);
> W całym zadaniu chodzi o spór akademicki typu "prove it works like > designed"... i właściwie tylko o to... Gdyby był blok EXCEPTION i obsługa > wyjątku to nie ma sporu :-)
Żeby dowieść jak to działa, zrob insert przed blokiem a po bloku wykonaj commit. :)
-- P.M.
=?iso-8859-2?Q?Piotr_Pli=BFga?= - 28-03-2006 00:02
Zwracam uwagę na fakt, że nie ma jawnie bloku EXCEPTION...
@dap - nie mogę się zgodzić z tym, że każdy SQL jest transakcją. Transakcja kończy w tym przypadku z COMMIT - natomiast w drugiej linii wykonywany jest "statement-level rollback". Natomiast co do bloku PL/SQL - gdybym dopisał EXPCEPTION WHEN OTHERS THEN ROLLBACK to jest oczywiste, że kończy się transakcja i następuje wycofanie (ROLLBACK) zmian niezatwierdzonych. Natomiast tutaj nie mam nigdzie jawnego bloku EXCEPTION więc kto wskaże miejsce w dokumentacji PL/SQL gdzie jest napisane, że "domyślny blok EXCEPTION wykonuje ROLLBACK lub w przypadku błędu w bloku EXCEPTION jest wykonywane ..."
Przychylam się do wytłumaczenia o propagacji wyjątków... Tak zresztą też jest opisane w dokumentacji Oracle-a... No dobrze, ale nadal nie mamy jawnej obsługi pt. EXCEPTION WHEN OTHERS THEN ROLLBACK;
Jeżeli nie mamy bloku PL/SQL to wytłumaczenie jest proste "statementp-level rollback", następnie COMMIT, koniec transakcji, jeden wiersz w bazie.
@P.M - też jestem skłonny założyć, że blok PL/SQL traktowany jest jako pojedynczy statment, więc działa to tak: a) statement-level rollback w drugiej linii bloku PL/SQL; b) błąd, więc -> propagacja wyjątku; c) statement-level rollback "bloku" (jeżeli założyć, że blok to pojedynczy statement);
Wiem jak działa, natomiast nadal brak dowodu... w postaci jawnego wytłumaczenia w dokumentacji. Nie musi być w jednym rozdziale - może być kilku aby było spójne.
Pozdrawiam, Piotr Pliżga -- Oracle Database Administrator www.metrogroup.pl
dap - 29-03-2006 00:26
Dobrze sprobujmy inaczej:
Pytanie brzmi dlaczego w PL/SQL za pomoca programu SQLPLUS wyjatek w anonimowym bloku powoduje wycofanie wszystkich transakcji z bloku.
1. Jak Oracle obługuje wyjatki - propaguje je dalej, do kolejnego bloku albo do srodowiska(programu) w ktorym dana transakcja zotala wywolana.
http://localhost/ora9i/appdev.920/a9..._errs.htm#1193 Catching Unhandled Exceptions
Remember, if it cannot find a handler for a raised exception, PL/SQL returns an unhandled exception error to the host environment, which determines the outcome. For example, in the Oracle Precompilers environment, any database changes made by a failed SQL statement or PL/SQL block are rolled back.
2. W tym wypadku jest to SQLPLUS, a on traktuje caly blok PL/SQL jako jedna transakcje, dlatego wystepuje standardowo wycofanie calego bloku.
http://localhost/ora9i/server.920/a9...13.htm#1012156
SET AUTO[COMMIT]{ON|OFF|IMM[EDIATE]|n}
Controls when Oracle commits pending changes to the database. ON commits pending changes to the database after Oracle executes each successful INSERT, UPDATE, or DELETE command or PL/SQL block. OFF suppresses automatic committing so that you must commit changes manually (for example, with the SQL command COMMIT). IMMEDIATE functions in the same manner as the ON option. n commits pending changes to the database after Oracle executes n successful SQL INSERT, UPDATE, or DELETE commands or PL/SQL blocks. n cannot be less than zero or greater than 2,000,000,000. The statement counter is reset to zero after successful completion of n INSERT, UPDATE or DELETE commands or PL/SQL blocks, a commit, a rollback, or a SET AUTOCOMMIT command.
!-> to jest chyba to co szukales <-! Note: For this feature, a PL/SQL block is considered one transaction, regardless of the actual number of SQL commands contained within it.
dap
=?ISO-8859-2?Q?Witek_=A6wierzy?= - 02-04-2006 00:11
dap wrote: > Dobrze sprobujmy inaczej: > > Pytanie brzmi dlaczego w PL/SQL za pomoca programu SQLPLUS wyjatek w > anonimowym bloku powoduje wycofanie wszystkich transakcji z bloku. > Nie spowoduje ! Np.: begin insert ... commit; insert_powodujacy_wyjatek; commit; end; / - pierwszy INSERT z bloku zostanie wprowadzony, drugi wycofany
> > 1. Jak Oracle obługuje wyjatki - propaguje je dalej, do kolejnego bloku > albo do srodowiska(programu) w ktorym dana transakcja zotala wywolana. Gdy wyjatek _NIE_JEST_OBSLUGIWANY_ w danym bloku, to nastepuje przerwanie wykonywania owego bloku i propagacja wyjatku do srodowiska wolajacego. Gdy wyjatek _JEST_OBSLUGIWANY_, to nastepuje przerwanie wykonania bloku, wykonanie instrukcji w odp. bloku WHEN WYJATEK THEN i zakonczenie bloku kodem = 0 (sukces) - w takiej sytuacji o wystapieniu wyjatku srodowisko wolajace (czymkolwiek by nie bylo owo srodowisko wolajace - sql*plusem, nadblokiem, czy czymkolwiek innym, co sobie mozesz wyobrazic ) > > 2. W tym wypadku jest to SQLPLUS, a on traktuje caly blok PL/SQL jako > jedna transakcje, dlatego wystepuje standardowo wycofanie calego bloku. > > http://localhost/ora9i/server.920/a9...13.htm#1012156 > transakcja, a blok plsql to sa dwie _ZUPELNIE_ _ROZNE_ sprawy, nijak sie majace do siebie. Gdy w bloku PLSQL nie ma commita, to transakcja _NIE_ZOSTANIE_ZATWIERDZONA_ pozdrawiam Witek Swierzy wswier@sgh.waw.pl
dap - 04-04-2006 00:08
Witek Świerzy wrote: > dap wrote: > >> Dobrze sprobujmy inaczej: >> >> Pytanie brzmi dlaczego w PL/SQL za pomoca programu SQLPLUS wyjatek w >> anonimowym bloku powoduje wycofanie wszystkich transakcji z bloku. >> > Nie spowoduje ! > Np.: > begin > insert ... > commit; > insert_powodujacy_wyjatek; > commit; > end; > / > - pierwszy INSERT z bloku zostanie wprowadzony, drugi wycofany
Jasne Po commit transakcja jest zakonczona i de facto nie jest juz transakcja, wiec tym bardziej nie mozna jej wycofac, ale mozna wycofac wszystkie inne rozpoczete transakcje i o tym pisalem. W poscie powyzej cytowalem opis dzialania implicite rollback.
>> >> 1. Jak Oracle obługuje wyjatki - propaguje je dalej, do kolejnego >> bloku albo do srodowiska(programu) w ktorym dana transakcja zotala >> wywolana. > > Gdy wyjatek _NIE_JEST_OBSLUGIWANY_ w danym bloku, to nastepuje > przerwanie wykonywania owego bloku i propagacja wyjatku do srodowiska > wolajacego. > Gdy wyjatek _JEST_OBSLUGIWANY_, to nastepuje przerwanie wykonania bloku, > wykonanie instrukcji w odp. bloku WHEN WYJATEK THEN i zakonczenie bloku > kodem = 0 (sukces) - w takiej sytuacji o wystapieniu wyjatku srodowisko > wolajace (czymkolwiek by nie bylo owo srodowisko wolajace - sql*plusem, > nadblokiem, czy czymkolwiek innym, co sobie mozesz wyobrazic )
Chyba nie do konca - opisywalem sytuacje gdy wyjatek nie jest obslugiwany besposrednio w tym samym bloku - tak jak w pytaniu. Wyjatek zawsze jest propagowny wyzej, nie ma bezposredniego wyskoczenie z bardzo zagniezdzonego bloku bezposrednio do srodowiska wywolujacego - no chyba, ze jako srodowisko wywolujace rozumiesz inny blok (tak przynajmniej jest w 10g - popatrz na kod ponizej).
Popatrz tu - wyjatek jest propagowany do kazdego bloku wyzej - zaden z blokow go nie obsluguje i dlatego konczy sie on w SQLPLUSIE.
23:20:39 SQL> begin begin insert into test2 values(0) ; begin insert into test2 values('a'); end ; commit ; end ;
insert into test2 values(1) ; commit ;
begin insert into test2 values(3) ; commit ; end ;
end ; / 23:20:40 2 23:20:40 3 23:20:40 4 23:20:40 5 23:20:40 6 23:20:40 7 23:20:40 8 23:20:40 9 23:20:40 10 23:20:40 11 23:20:40 12 23:20:40 13 23:20:40 14 23:20:40 15 23:20:40 16 23:20:40 17 23:20:40 18 23:20:40 19 begin * ERROR at line 1: ORA-01722: invalid number ORA-06512: at line 5
Elapsed: 00:00:00.00 23:20:40 SQL> select * from test2 ;
no rows selected
Tu natomiast wyjatek jest obslugiwany w bloku o 1 wyzej, gdyby pojawialo sie wyjscie bezposrednio do SQLPLUS to bylo by 3 insertow.
23:24:18 SQL> begin begin insert into test2 values(0) ; begin insert into test2 values('a'); end ; commit ; exception when others then null ; end ;
insert into test2 values(1) ; commit ;
begin insert into test2 values(3) ; commit ; end ;
end ; / 23:24:20 2 23:24:20 3 23:24:20 4 23:24:20 5 23:24:20 6 23:24:20 7 23:24:20 8 23:24:20 9 23:24:20 10 23:24:20 11 23:24:20 12 23:24:20 13 23:24:20 14 23:24:20 15 23:24:20 16 23:24:20 17 23:24:20 18 23:24:20 19 23:24:20 20 23:24:20 21 PL/SQL procedure successfully completed.
Elapsed: 00:00:00.16 23:24:20 SQL> select * from test2 ;
A ---------- 0 1 3
Elapsed: 00:00:00.00 23:24:25 SQL>
>> 2. W tym wypadku jest to SQLPLUS, a on traktuje caly blok PL/SQL jako >> jedna transakcje, dlatego wystepuje standardowo wycofanie calego bloku. >> >> http://localhost/ora9i/server.920/a9...13.htm#1012156 >> > transakcja, a blok plsql to sa dwie _ZUPELNIE_ _ROZNE_ sprawy, nijak sie > majace do siebie. Gdy w bloku PLSQL nie ma commita, to transakcja > _NIE_ZOSTANIE_ZATWIERDZONA_
Wlasnie wyglada, ze dla SQLPLUS z anonimowym blokiem jest inaczej blok PL/SQL = transakcja - i stad pytanie pytanie PP, gdzie w dokumentacji Oracle mozna znalezc, ze bylo to zamierzone dzialanie.
Ponizej kod pokazuje insert do bazy danych w bloku PL/SQL bez zatwierdzenia, (dokladnie tak samo jak w wypadku zwyklego SQL).
SQL> SQL> select * from test2 ; SP2-0640: Not connected SQL> conn / as sysdba Connected. SQL> select * from test2 ;
no rows selected
SQL> begin begin insert into test2 values(0) ; end ;
insert into test2 values(1) ;
begin insert into test2 values(3) ; end ;
end ; / 2 3 4 5 6 7 8 9 10 11 12 13 14
PL/SQL procedure successfully completed.
SQL> select * from test2;
A ---------- 0 1 3
SQL> disc Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production SQL> conn / as sysdba Connected. SQL> select * from test2 ;
A ---------- 0 1 3
SQL>
Pozdrawiam dap
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
Oracle 19g +Insert +Insert +Insert...
[oracle] zapytanie dynamiczne z =?ISO-8859-2?Q?=22dynamiczn=B1_?==?ISO-8859-2?Q?nazw=B1_tabeli=22?=
[Oracle] jak =?ISO-8859-2?Q?ograniczy=E6_pami=EA=E6_dla_se?==?ISO-8859-2?Q?rwera=3F?=
=?ISO-8859-2?Q?=5BOT=5D_Zdany_egzamin_Oracle_1Z0-007_a?==?ISO-8859-2?Q?_brak_informacji_na_stronie_Prometric_-_czy?==?ISO-8859-2?Q?_co=B6_nie_tak=3F?=
jak to =?ISO-8859-2?Q?zrobi=E6=2E=2E=2E=3F_TSQL_sql_server?==?ISO-8859-2?Q?_?=
[oracle] czy da =?ISO-8859-2?Q?si=EA_z_poziomu_procedury_?==?ISO-8859-2?Q?zrobi=E6_kopi=EA_zapasow=B1=3F?=
[oracle 10g] czy =?ISO-8859-2?Q?mo=BFna_wy=B3=B1czy=E6_wszys?==?ISO-8859-2?Q?tkie_wi=EAzy_w_schemacie=3F?=
MSSQL Express czy Oracle Express
=?iso-8859-2?q?[oracle]_Jak_sprawdzi=E6_wielko=B6=E6_tabeli_=3F=3F?=
=?ISO-8859-2?Q?Poszukjue_ksi=B1=BFki_"Oracle_?= =?ISO-8859-2?Q?optymalizacja_wydajno=B6ci"..?=
zanotowane.pldoc.pisz.plpdf.pisz.plfelgiuzywane.xlx.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|