Demo#1 | |
---|---|
{code:sql | borderStyle=solid} -- 문장의 부수적인 결과(트리거)까지 문장의 일부분으로 간주 SQL> create table t2 ( cnt int ); |
Table created.
SQL> insert into t2 values ( 0 );
1 row created.
SQL> commit;
Commit complete.
SQL> create table t (x int check ( x>0 ) );
Table created.
SQL> create trigger t_trigger
2 before insert or delete on t for each row
3 begin
4 if ( inserting ) then
5 update t2 set cnt = cnt + 1;
6 else
7 update t2 set cnt = cnt - 1;
8 end if;
9 dbms_output.put_line( 'I fired and update ' || sql%rowcount || ' rows');
10 end;
11 /
Trigger created.
SQL> set serveroutput on;
SQL> insert into t values ( 1 );
I fired and update 1 rows
1 row created.
SQL> insert into t values ( -1 );
I fired and update 1 rows
insert into t values ( -1 )
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C00158277) violated
SQL> select * from t2;
CNT
|
|{code:sql|borderStyle=solid}
Savepoint statement1;
Insert into t values ( 1 );
If error then rollback to statement1;
Savepoint statement2;
Insert into t values ( -1 );
If error then rollback to statement2;
-- Sybase/SQL Server 는 insert(t) 와 update(t2)가 별개임?
-- Oracle 은 만약 update(t2)의 트리거에 의해 delete(t3) 하는 경우(혹은 그 이상)에도 자연스럽게 원자성이 보장됨
|
Demo#2 | |
---|---|
{code:sql | borderStyle=solid} – PL/SQL 익명 블록을 문장으로 간주 SQL> create or replace procedure p 2 as 3 begin 4 insert into t values ( 1 ); 5 insert into t values ( -1 ); 6 end; 7 / |
Procedure created.
SQL> delete from t;
I fired and update 1 rows
1 row deleted.
SQL> update t2 set cnt = 0;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from t;
no rows selected
SQL> select * from t2;
CNT
SQL> begin
2 p;
3 end;
4 /
I fired and update 1 rows
I fired and update 1 rows
begin
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C00158277) violated
ORA-06512: at "SCOTT.P", line 5
ORA-06512: at line 2
SQL> select * from t;
no rows selected
SQL> select * from t2;
CNT
|
|{code:sql|borderStyle=solid}
Savepoint statement1;
begin p; end;
If error then rollback to statement1;
|
Demo#3 | ||
---|---|---|
{code:sql | borderStyle=solid} – WHEN OTHERS 를 통해 어떤 오류가 발생 해도 무시 하도록 함 (ROLLBACK 안됨) SQL> begin 2 p; 3 exception 4 when others then 5 dbms_output.put_line( 'Error!!!! ' | sqlerrm ); 6 end; 7 / I fired and update 1 rows I fired and update 1 rows Error!!!! ORA-02290: check constraint (SCOTT.SYS_C00158277) violated |
PL/SQL procedure successfully completed.
SQL> select * from t;
X
SQL> select * from t2;
CNT
|
h3. (on) WHEN OTHERS
||Demo#4||
|{code:sql|borderStyle=solid}
-- RAISE/RAISE_APPLICATION_ERROR를 통해 예외가 다시 발생하도록 처리하지 않은 WHEN OTHERS 예외 핸들러는 위험함 (저자는 버그로 봄)
-- 저자가 WHEN OTHER 를 디스 한 결과 아래와 같은 결과를 확인할 수 있음 (11gR1 계획 당시 WHEN OTHERS 를 제거를 제안 함)
SQL> alter session set PLSQL_Warnings = 'enable:all';
Session altered.
SQL> create or replace procedure some_proc( p_str in varchar2 )
2 as
3 begin
4 dbms_output.put_line( p_str );
5 exception
6 when others
7 then
8 -- call some log_error() routine
9 null;
10 end;
11 /
SP2-0804: Procedure created with compilation warnings
SQL> show errors procedure some_proc;
Errors for PROCEDURE SOME_PROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/1 PLW-05018: unit SOME_PROC omitted optional AUTHID clause;
default value DEFINER used
6/9 PLW-06009: procedure "SOME_PROC" OTHERS handler does not end in
RAISE or RAISE_APPLICATION_ERROR
|
Demo#5 | ||
---|---|---|
{code:sql | borderStyle=solid} – WHEN OTHERS 를 통해 ROLLBACK 하지만 나쁜 코드 (WHEN OTHERS 로 예외를 가로 챘고, 이미 제공 하는 기능을 명시적으로 코딩 함) SQL> begin 2 savepoint sp; 3 p; 4 exception 5 when others then 6 rollback to sp; 7 dbms_output.put_line( 'Error!!!! ' | sqlerrm ); 8 end; 9 / I fired and update 1 rows I fired and update 1 rows Error!!!! ORA-02290: check constraint (SCOTT.SYS_C00158277) violated |
PL/SQL procedure successfully completed.
SQL> select * from t;
no rows selected
SQL> select * from t2;
CNT
|
h3. (on) 트랜잭션 수준의 원자성
h6. (1) 트랜잭션의 목적 : 데이터베이스를 일관적인 상태에서 다음의 일관적인 상태로 전환
h3. (on) DDL과 원자성
h6. (1) DDL 시작 시 묵시적으로 기존 트랜잭션을 COMMIT (WHY?)
h6. (2) DDL 성공시 COMMIT 실패시 ROLLBACK