database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 38840 게시물 읽기
No. 38840
프로시져가 무한 루프를 도는 것 같은데요
작성자
최두철(uglyfe)
작성일
2011-09-05 15:32
조회수
7,722

create procedure aaa is

cursor cur is

  select *

  from   [table]

  where [bla_bla_bla]

  for update of [col_stat];

  list cur%rowtype;

begin

  open cur;

  loop

  begin

    fetch cur into list

    exit when cur%notfound;

    [로직 수행... select 만 열심히 합니다]

    update [table]

    set [col_stat] = 'good'

    where current of cur;

    commit;

  exception

    when no_data_found then

      update [table]

      set [col_stat] = 'no data'

      where current of cur;

      commit;

    when others then                                <------------------------- 문제가 되는 부분

      update [table]

      set [col_stat] = 'exception....'

      where current of cur;

      commit;

      insert into [err_table] values ();

      commit;

    end;

  end loop;

  close cur;

end;

 

위와 같은 프로시져를 생성하여 수행하는 중입니다.

그런데 "문제가 되는 부분" 이 무한 루프에 빠집니다.

특정 데이터에 한해 가끔 오류가 발생할 수 있는 상황이 있기 때문에 그러한 특정 데이터를 모아두기 위한 exception 처리 로직을 심어둔건데 동일한 데이터가 계속 누적이 됩니다.

덕분에 야간에 테이블 스페이스가 가득 찰뻔한 중대한 상황이 두어번 있었습니다.

아무리 봐도 별다른 문제점이 있어보이질 않는데 어떠한 부분을 살펴봐야 할까요???

이 글에 대한 댓글이 총 7건 있습니다.

로직을 보면 한 로우를 읽어서 한 로우씩 정상이면 'GOOD'

아니면 'EXCEPTION' 이라고 업데이트 하는 로직입니다.

NO_DATA_FOUND는 구조상 탈 수없는 구조이니 제외시키고

업데이트 실패하면 EXCEPTION을 실행하는데

업데이트 실행에 실패한 것을 다시 업데이트 시키고 있습니다.

WHEN OTHERS THEN 에서

업데이트 로직을 주석처리하면 일단은 작업에 이상없으실 겁니다.

create procedure aaa is

cursor cur is

  select *

  from   [table]

  where [bla_bla_bla]

  for update of [col_stat];

  list cur%rowtype;

begin

  open cur;

  loop

  begin

    fetch cur into list

    exit when cur%notfound;

    [로직 수행... select 만 열심히 합니다]

    update [table]

    set [col_stat] = 'good'

    where current of cur;

    commit;

  exception

    when no_data_found then

      update [table]

      set [col_stat] = 'no data'

      where current of cur;

      commit;

    when others then                              

      --update [table]

      --set [col_stat] = 'exception....'

      --where current of cur;

      --commit;

      --*** 업데이트 실패시 처리로직 작성하세요 ***
     
      insert into [err_table] values ();

      commit;

    end;

  end loop;

  close cur;

end;

 

 

 

 

 

이강실님이 2011-09-05 17:06에 작성한 댓글입니다.
이 댓글은 2011-09-05 17:24에 마지막으로 수정되었습니다. Edit

답변 감사드립니다.

그런데...

1. [로직 수행... select 만 열심히 합니다] 부분에서 NO_DATA_FOUND 가 발생할 수 있습니다.

    로직수행이라는 것이 대상 테이블의 데이터에 대한 검증작업인데

    이 부분은 다른 테이블에서 참조를 하게 됩니다.(해당 데이터가 실제 정상 데이터인지 조회만 합니다)

 

2. OTHERS 가 발생하는 상황이 1. 에서 말씀드린 [로직 수행] 부분에서 2건 이상의 데이터가 나오기도 하기에

    OTHERS 로 처리한것입니다.

최두철(uglyfe)님이 2011-09-06 09:53에 작성한 댓글입니다.

 로직이 좀 애매하네요 ?

 

EXCEPTION 이 UPDATE 에 대한 거 아닌가요 ?

 

EXCEPTION이 FETCH에 걸렸지 싶은데~ ^^:

 

loop

begin

  fetch

  begin

    update

    exception

  end

end

end loop

 

으로 한번 수정해 보세요.

이용운(cloudlyu)님이 2011-09-07 14:16에 작성한 댓글입니다.

exception 으로 처리하는 부분이 단순히 update 에 대한 것 만은 아닙니다.

데이터에 대한 검증을 하는 로직을 수행하는 도중에도(select 가 전부이긴 하지만)

data_not_found 가 발생할 수도 있고,

1건의 data 가 나와야 하는데 2건 이상의 data 가 나오는 경우도 발생할 수 있기에

전체적으로 exception 처리를 한 것입니다.

그래서 loop 전체에 대해 exception 처리 부분이 걸려있도록 구성해 놓은 상황입니다.

최두철(uglyfe)님이 2011-09-08 10:51에 작성한 댓글입니다.

일단 주어진 정보만 봤을때는 문제 없어 보입니다.
보여주지 않은 부분에서 문제가 있지 않을런지요?

에러테이블에 같은 데이터가 계속 쌓인다고 하셨는데요?
혹시 커서부분의 조인조건이 누락되어 카티션 프러덕 발생으로
같은 데이터가 계속 조회되는건 아닐런지요?

마농(manon94)님이 2011-09-08 10:59에 작성한 댓글입니다.

 fetch 되어 오는 컬럼중에 Null  포함 컬럼이 있다면

1405가 발생하겠고...

 

FETCH로 한건씩 오게 될 경우 FOR IN 구문이 아닌 declare Fetch의 경우

"exit when cur%notfound;"

로 충분히 커버 됩니다.

 

이 경우 update에 대한 건이 어덯게 처리되어야 할지에 대한 별도 로직이 필요하겠지요.

FETCH는 FETCH FOR 구문으로 적어주지 않는다면 다건에 대한 검증은 불가능합니다.

 

커서 자체가 단건에 대한 처리를 기본으로 한다면

차라리 select into 구문을 사용해서 예외처리를 해주시는 것이 나을겁니다.

 

동일 테이블에 대한 update 구문에서 1403이 나올 수 있다는건 이해가 안되네요.

구문대로라면 100건을 1건 1건 조회해서 해당 건에 대한 update를 수행하고 문제가 있을 경우 오류 테이블을 insert 하는 구조입니다.

어떤 문제가 발생할 가능성이 있다면 FETCH 구문은 포함 컬럼중에 Null 이 있다면 1405:fetched column value is NULL 를 발생시킬 수 있습니다.

그런 경우라면 오류를 100건 Insert 했을겁니다.

이용운(cloudlyu)님이 2011-09-08 15:42에 작성한 댓글입니다.

제가 댓글로 추가해주신 부분을 제대로 안 읽었군요~ ^^;

 

EXCEPT은 각기 작성해주시는게 좋습니다.

 

마농님 말씀처럼 보여주시지 않은 부분에 오류가 있어 보입니다.

 

그리고, 처리 건수가 많지 않다면  Commit은 최종적으로만 해주시는 것이 커서관련 오류를 피할 수 있더군요.

이용운(cloudlyu)님이 2011-09-08 15:50에 작성한 댓글입니다.
이 댓글은 2011-09-08 15:50에 마지막으로 수정되었습니다.
[Top]
No.
제목
작성자
작성일
조회
38843양수+음수일때 음수값 처리는 어떻게 해야하나요? [4]
성이
2011-09-06
3881
38842SQL로 CarrageReturn 처리하는 방법? [1]
윤석민
2011-09-05
4177
38841쿼리 비효율 ? [2]
김진국
2011-09-05
4093
38840프로시져가 무한 루프를 도는 것 같은데요 [7]
최두철
2011-09-05
7722
38839오라클 시간계산시 익일 시간 [5]
강영호
2011-09-03
5201
38838interpolation SQL 을 어떻게 구현하면 빠를까요?
부족한
2011-09-02
3314
38837단건을 여러건으로 [1]
HJLEE
2011-09-02
3664
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.017초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다