DBMS가 제공하는 Sequence 기능을 사용하는 것이 가장 좋으나, 이를 사용할 수 없는 경우 별도 구현해야 함
create table seq_tab (
gubun varchar2(1),
seq number,
constraint pk_seq_tab primary key(gubun, seq)
)
organization index;
create or replace function seq_nextval(l_gubun number) return number
as
pragma autonomous_transaction; -- 메인 트랜젝션에 영향을 주지 않고 서브 트랜젝션만 따로 커밋
l_new_seq seq_tab.seq%type;
begin
update seq_tab
set seq = seq + 1
where gubun = l_gubun;
select seq into l_new_seq
from seq_tab
where gubun = l_gubun;
commit;
return l_new_seq;
end;
/
begin
update tab1
set col1 = :x
where col2 = :y ;
insert into tab2
values (seq_nextval(123), :x, :y, :z);
loop
-- do anything ...
end loop;
commit;
exception
when others then
rollback;
end;
/
선분이력을 추가하고 갱신할 때 발생할 수 있는 동시성 이슈를 해결한 사례
declare
cur_dt varchar2(14);
begin
select 고객ID
from 부가서비스이력
where 고객ID = 1
and 종료일시 = to_date('99991231235959', 'yyyymmddhh24miss')
for update nowait ;
select 고객ID
from 고객
where 고객ID = 1
for update nowait ;
cur_dt := to_char(sysdate, 'yyyymmddhh24miss') ; -- ①
update 부가서비스이력 -- ②
set 종료일시 = to_date(:cur_dt, 'yyyymmddhh24miss') - 1/24/60/60
where 고객ID = 1
and 부가서비스ID = 'A'
and 종료일시 = to_date('99991231235959', 'yyyymmddhh24miss') ;
insert into 부가서비스이력(고객ID, 부가서비스ID, 시작일시, 종료일시) -- ③
values (1, 'A', to_date(:cur_dt, 'yyyymmddhh24miss'),
to_date('99991231235959', 'yyyymmddhh24miss')) ;
commit; -- ④
end;