SQL> create table LookupTable( key number, value varchar2(100) );
SQL> insert into LookupTable( key, value ) values ( 1, 'YAMAHA' );
SQL> insert into LookupTable( key, value ) values ( 2, 'YAMAHA' );
SQL> commit;
SQL> create or replace function lookup( l_input number ) return varchar2
2 deterministic
3 as
4 l_output LookupTable.value%TYPE;
5 begin
6 select value into l_output from LookupTable where key = l_input;
7 return l_output;
8 end;
9 /
함수가 생성되었습니다
SQL> create table big_table nologging
2 as
3 (select 1 no FROM DUAL CONNECT BY LEVEL < 1001
4 union all
5 select 2 FROM DUAL CONNECT BY LEVEL < 1001)
6 /
SQL> create index t_no_idx on big_table(no);
select /*+ index(t t_no_idx) */ (select lookup(t.no) from dual )
from big_table t
where t.no > 0
위 쿼리 실행 후 다른 세션에서 update LookupTable set value='YAMAHA2'; commit;
결과값 {1,'YAMAHA'},{2,'YAMAHA2'}
쿼리 시작 시점 {1,'YAMAHA'},{2,'YAMAHA'}
Current시점 {1,'YAMAHA2'},{2,'YAMAHA2'}
실제 캐시에는 어느 쪽도 아닌, 일관성 없는 값을 갖게 됩니다.
해결 방법 :
SQL> select l.value
2 from big_table t, LookupTable l
3 where l.key(+) = t.no
SQL> select (select value from LookupTable where key = t.no )
2 from big_table t;
SQL> delete from LookupTable;
1 행이 삭제되었습니다.
SQL> insert into LookupTable values( 1, 'YAMAHA' );
1 개의 행이 만들어졌습니다.
SQL> commit;
커밋이 완료되었습니다.
SQL> create table t
2 as
3 select 1 no from dual;
테이블이 생성되었습니다.
SQL> select no, lookup(no) value from t;
NO VALUE
---------- -----------
1 YAMAHA
SQL> create index t_idx on t( lookup(no) );
인덱스가 생성되었습니다.
SQL> select no, lookup(no) value, lookup(1) value2 from t
2 where lookup(no) = 'YAMAHA';
NO VALUE VALUE2
---------- ----------- -------------
1 YAMAHA YAMAHA
SQL> update LookupTable set value = 'YAMAHA2' where key = 1;
1 행이 갱신되었습니다.
SQL> commit;
커밋이 완료되었습니다.
SQL> select no, lookup(no) value, lookup(1) value2 from t
2 where lookup(no) = 'YAMAHA';
NO VALUE VALUE2
------------ --------- ------------
1 YAMAHA YAMAHA2
SQL> alter index t_idx rebuild
2 /
인덱스가 변경되었습니다.
SQL> select no, looKup(no) value, lookup(1) value2 from t
2 where lookup(no) = 'YAMAHA'
SQL> /
선택된 레코드가 없습니다.
SQL> select no, lookup(no) value, lookup(1) value2 from t
2 where lookup(no) = 'YAMAHA2'
SQL> /
NO VALUE VALUE2
---------- --------- --------------------------------------------
1 YAMAHA2 YAMAHA2
FBI를 만드는 경우 외에도, update문으로 반정규화 컬럼을 갱신하거나 insert문 가공 테이블에 레코드를 삽입할때도 중간에 값이 변경되면 일관성 없는 상태로 값들이 영구 저장될 수 있다.
- 강좌 URL : http://www.gurubee.net/lecture/3128
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.