| Table of Contents |
|---|
개요
...
여러 개의 레코드를 반환하는 select 문 처리를 위해 커서를 사용하여 레코드 fetch 과정 중 발생하는 오류에 관해 설명한다.
버전
...
Altibase 4.3.9
현상
...
여러 개의 레코드를 반환하는 질의문 처리를 위해서는 아래와 같은 과정으로 커서(CURSOR)를 이용해야 한다.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
$ ./cursor1 <CURSOR 1> [Success declare cursor] [Success open cursor] [Fetch Cursor] ------------------------------------------------------------------ DNO DNAME DEP_LOCATION MGR_NO ------------------------------------------------------------------ 1 BUSINESS DEPT Seoul 100 2 BUSINESS DEPT Seoul 100 ...중략... 908 BUSINESS DEPT Seoul 100 909 BUSINESS DEPT Seoul 100 Error : [-266300] Request of fetching data to an unprepared SQL statement. /* fetch 수행 중 에러 발생 */ ------------------------------------------------------------------ [Close Cursor] ------------------------------------------------------------------ Success close cursor |
원인
...
커서(CURSOR) OPEN 상태에서 COMMIT/ROLLBACK 수행한 경우
...
Altibase는 ANSI 표준을 준수하여 fetch across commit 방식을 지원하지 않는다. 따라서 커서 OPEN 후 COMMIT 또는 ROLLBACK을 수행하면 ANSI 표준에 따라 커서를 강제로 닫는다.
...
| Code Block | ||
|---|---|---|
| ||
non-autocommit mode
커서(CURSOR) 선언
커서(CURSOR) OPEN
while(1)
{
커서(CURSOR) FETCH ;
if (sqlca.sqlcode == SQL_SUCCESS) {
/* 변경 DML 수행 */
/* COMMIT 또는 ROLLBACK 수행 */
}
else if (sqlca.sqlcode == SQL_NO_DATA) {
...
}
else {
/* 처음 통신 버퍼에 담긴 레코드를 모두 처리한 후 두 번째 통신 버퍼에 담길 때 이 단계에서 에러가 발생한다. */
...
}
} |
조치
...
커서(CURSOR) OPEN 상태에서 COMMIT/ROLLBACK 수행한 경우
...
이 에러를 조치하기 위한 2가지 방법을 안내한다.
...
위 방법은 모두 애플리케이션 변경이 필요하다.
1. fetch 세션과 변경 DML 세션 분리
하나의 애플리케이션 내에 다중 연결을 사용하여 COMMIT 또는 ROLLBACK 수행이 커서에 영향이 없도록 한다.
...
Code Block language cpp /* FETCH를 위한 세션 */ EXEC SQL AT conn1 CONNECT; /* 변경DML 수행을 위한 세션 */ EXEC SQL AT conn2 CONNECT; EXEC SQL AT conn2 AUTOCOMMIT OFF; /* CONN1에서 커서 선언, OPEN, FETCH 수행 */ EXEC SQL AT conn1 DECLARE cursor; EXEC SQL AT conn1 OPEN cursor; while (1) { /* conn1에서 FETCH 수행. */ EXEC SQL AT conn1 FETCH cursor if (sqlca.sqlcode == SQL_SUCCESS) { /* conn2에서 변경DML 및 COMMIT 또는 ROLLBACK 수행 */ EXEC SQL AT conn2 INSERT or UPDATE or DELETE ; /* check sqlca.sqlcode */ if (sqlca.sqlcode == SQL_SUCCESS) { ... } else { ... } /* conn2에서 수행한 commit 또는 rollback은 conn1의 커서 사용에 영향을 주지 않는다. */ EXEC SQL AT conn2 commit or rollback; /* check sqlca.sqlcode */ if (sqlca.sqlcode == SQL_SUCCESS) { ... } else { ... } } else if (sqlca.sqlcode == SQL_NO_DATA) { ... } else { ... } }
2. 통신 버퍼에 담길 만큼만 커서 선언 후 반복적 커서 오픈
한 번의 FETCH 로 통신 버퍼에 담길 만큼의 레코드 수를 산정한 후 LIMIT 절을 사용해 커서를 선언한다.
...
Code Block language cpp /* LIMIT 절을 사용하여 커서를 선언한다. n은 LIMIT절에서 반환할 마지막 레코드 값으로 운영 환경에 맞게 정의해야 한다. 통신 버퍼에 담기는 레코드 수는 레코드 크기에 따라 다르다. */ DECLARE 커서 SELECT ~ FROM ~ WHERE ~ LIMIT :s_start, n; /* LIMIT 절에 사용한 시작 값을 선언한다. */ s_start = 1; while(1) { /* 조건에 맞는 레코드를 모두 FETCH할 때까지 커서 오픈을 반복한다. */ OPEN 커서 while(1) { 커서(CURSOR) FETCH ; if (sqlca.sqlcode == SQL_SUCCESS) { /* 변경 DML 수행 */ } else if (sqlca.sqlcode == SQL_NO_DATA) { ... } else { ... } } /* COMMIT 또는 ROLLBACK 수행 */ /* LIMIT 절의 시작 값을 지정한다. n은 예시이다. */ s_start = s_start + n ; } CLOSE 커서 또는 CLOSE RELEASE 커서
참고
...
버전 별 차이
...
Altibase 버전에 따라 같은 상황에서 발생하는 에러 메시지는 다를 수 있다.
...