Gentle Breeze
[Oracle] ORA-01002: fetch out of sequence 본문
이 상황에서 자주 발생하는 Oracle Error Code
원문 - http://scruz.tistory.com/18
ORA-01002: fetch out of sequence
ORACLE에서 제공하는 문서상의 원인과 해결방법은 아래와 같다.
Cause: This error means that a fetch has been attempted from a cursor
which is no longer vaild. Note that a PL/SQL cursor loop
implicitly does fetches, and thus may also cause this error.
There are a number of possible causes for this error, including:
1) Fetching from a cursor after the last row has been retrieved
and the ORA-01403 error returned.
2) If the cursor has been opened with the FOR UPDATE clause,
fetching after a COMMIT has been issued will return the error.
3) Rebinding any placeholders in the SQL statement, then issuing
a fetch before reexecuting the statement.
Action: 1) Do not issue a fetch statement after the last row has been
retrieved - there are no more rows to fetch.
2) Do not issue a COMMIT inside a fetch loop for a cursor
that has been opened FOR UPDATE.
3) Reexecute the statement after rebinding, the attempt to
fetch again.
1) CURSOR를 이용해 어느 테이블의 데이터를 FETCH를 할 때, 그 해당 결과값들이 모두
FETCH되어 더 이상 FETCH될 데이터가 없을 때 ORACLE은 ORA-01403에러를 발생시켜
더 이상 FETCH될 데이터가 없다는 걸 알린다.
하지만 프로그래머의 실수로 FETCH받는 부분의 LOOP제어가 잘 못되어 ORA-01403이
발생했는데도 FETCH를 시도하게 되면 ORA-01002를 발생시킨다.
while(1) {
EXEC SQL FETCH _CURSOR
INTO :data_basket;
pFetch += nFetch;
nFetch = sqlca.sqlerrd[2] - pFetch;
if(sqlca.sqlcode == 0)
(void)put_in_file(data_basket, nFetch);
if(sqlca.sqlcode == 1403) {
if(nFetch > 0)
(void)put_in_file(data_basket, nFetch);
break; <-- 이 부분이 없으면 ORA-01403이 발생했는데도 FETCH를 시도하기
때문에 ORA-01002가 발생된다.
}
if(sqlca.sqlcode != 0 && sqlca.sqlcode != 1403) {
printf("%s\n", sqlca.sqlerrm.sqlerrmc);
exit(1);
}
}
2) SAMPLE_TABLE이란 이름의 테이블이 있다.
a세션은 SAMPLE_TABLE에서 UPDATE를 하고 COMMIT or ROLLBACK을 하지 않은 상태이다.
이때 b세션에서
SELECT * FROM SAMPLE_TABLE;
위의 쿼리를 조회하게 되면 a세션의 UPDATE 쿼리가 반영되지 않은 결과값이 리턴된다.
SELECT * FROM SAMPLE_TABLE FOR UPDATE;
위의 쿼리를 조회하게 되면 a세션의 UPDATE 쿼리에 대한 COMMIT or ROLLBACK이 될 때까지
대기하게 된다.
SELECT * FROM SAMPLE_TABLE FOR UPDATE WAIT 10;
위의 쿼리를 조회하게 되면 a세션의 UPDATE 쿼리에 대한 COMMIT or ROLLBACK이 되지 않은
상태이기 때문에 10초 동안 COMMIT or ROLLBACK 여부를 확인한 뒤 COMMIT or ROLLBACK되지
않았으면 ORA-01002에러를 발생시킨다.
SELECT * FROM SAMPLE_TABLE FOR UPDATE NOWAIT;
위의 쿼리를 조회하게 되면 a세션의 UPDATE 쿼리에 대한 COMMIT or ROLLBACK이 되지 않은
상태이기 때문에 대기하지 않고 ORA-01002에러를 발생시킨다.
3) CURSOR로 선언된 SELECT문의 GROUP BY절이 잘 못되어서 발생하는 경우이다.
Sample_Table)
+-----+---------+------------+---------+
| SEQ | PROD_NO | PROD_NAME | PRICE |
+-----+---------+------------+---------+
| 1 | 1001 | Nikon F6 | 3000000 |
| 2 | 1002 | Nikon F5 | 2500000 |
| 3 | 1003 | Nikon F4s | 2000000 |
| 4 | 1004 | Nikon F4h | 2000000 |
| 5 | 1005 | Nikon F3Ti | 1500000 |
| 6 | 1006 | Nikon F3hp | 1500000 |
| 7 | 1007 | Nikon F3AF | 1500000 |
| 8 | 1008 | Nikon F3 | 1500000 |
+-----+---------+------------+---------+
Query)
SELECT
SEQ,
PROD_NO,
PROD_NAME,
PRICE
FROM
SAMPLE_TABLE
GROUP BY -+
SEQ, | GROUP BY절이 잘 못되어 있다.
PROD_NAME, | 이 경우 ORA-01002에러가 발생한다.
PRICE; -+
4) 실제로 겪어본 케이스는 아니지만
DB Link를 통해 Remote Database에서 Fetch를 받는 중에
Remote Database가 Shutdown되면 ORA-01002에러가 발생된다고 한다.
'⑨ 직무역량강화 > Oracle' 카테고리의 다른 글
[Oracle] Oracle SQLCODE (0) | 2011.08.10 |
---|---|
[PL/SQL] 특정 기간동안 휴일(토/일) 여부 체크해서 TABLE에 INSERT (0) | 2011.01.24 |
[Oracle] Table Index 조회 (0) | 2011.01.24 |
[Oracle 9i] SQL Statement <1> SELECT (0) | 2008.09.08 |
[Oracle 9i] PL/SQL (0) | 2008.09.08 |