드디어 오라클 마지막 질문 ㅜ.ㅜ
글쓴이: cjy1126 / 작성시간: 수, 2003/04/02 - 9:20오후
답변해주신분들 정말 감사합니다.
sample 파일과 책... 가장 중요한 답변 덕에 스터디 프로젝트 임무인 select를 해냈습니다. ^^
그런데 또 문제가 생겼습니다.
제가 전해줄 파일은 db.pc proc로 컴파일한 파일인 db.c db.h 2개이고
테스트용으로 main.c 파일을 만들었습니다.
이건 db.h 입니다.
#include <stdio.h> #include <string.h> #include <sqlca.h> #include <stdlib.h> #include <sqlda.h> #include <sqlcpr.h> void oracle_connect(); void cursor_define(); void select_addr(char *addr[]); void oracle_close();
이건 proc로 컴파일한 db.c 입니다.
#include "db.h" char *username="mini"; char *password="mini"; char saddr[16]; void oracle_connect() { EXEC SQL CONNECT :username IDENTIFIED BY :password; printf("\nConnected to ORACLE as user: %s\n", username); } void cursor_define() { EXEC SQL DECLARE select CURSOR FOR SELECT SADDR FROM SERVER; } void select_addr(char *addr[]) { int i; for(i=0; i<10; i++) memset(addr[i], '\0', (sizeof(char)*16)); EXEC SQL OPEN select; EXEC SQL WHENEVER NOT FOUND DO break; i=0; for( ; ; ) { EXEC SQL FETCH select INTO :saddr; strcpy(addr[i], saddr); i++; } EXEC SQL CLOSE select; } void oracle_close() { EXEC SQL COMMIT WORK RELEASE; exit(0); }
test용 main.c 입니다.
#include "db.h" main() { char *addr[10]; int i; for(i=0; i<10; i++) addr[i] = (char *)malloc(sizeof(char)*16); oracle_connect(); cursor_define(); select_addr(addr); for(i=0; addr[i]!=NULL; i++) printf("%s\n", addr[i]); oracle_close(); }
출력이 이렇게 되네요.
[root@CP36 mini]# ./db Connected to ORACLE as user: mini 192.168.2.37 211.218.217.1 192.168.3.73 200.123.245.0 ]惶홼 ? U?R? ? 횾?> Segmentation fault [root@CP36 mini]#
포인터 배열 10개를 미리 만들어서 select를 받았는데, 실제 데이타는 4개가 있었습니다.
오라클과 C가 NULL 개념이 달라서 그런거 같은데, 해결 방법을 모르겠습니다.
그렇다고 i<10까지 찍으면 빈줄이 6줄 생기고... 난감하네요 ㅜ.ㅜ
도움 부탁드립니다.
Forums:
패치한 후에..
패치한 후에... sqlca.sqlcode 값을 확인해서
제대로 패치 했는지 확인해봐야 겠죠
아래는 예입니다.,
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
ㅜ.ㅜ
답변 감사합니다.
그런데... 이해가 안돼요 :cry:
^^;
exec로 sql문을 실행하면
sqlca.sqlcode에 상태코드가 들어가게 됩니다.
그래서 select해서 아무것도 없거나 fetch가 안되거나 하면
알아 챌수가 있는거죠.
1403이 record not found 입니다.
pro*c 책 중에 이부분을 안다루는 게 없을텐데.. ^^
책 색인에서 한번 찾아보세요...
그리고 pro*c로 돌리고 나면 c파일이 생기는데,
pro*c가 만들어낸 c파일을 한번 열어서 분석해보세요
그럼 오라클이 뭘 어떻게 원하는지 pc파일을 어케 만들어야 하는지
계념을 잡는데 도움이 됩니다.
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
네 pro*c 책을 찾아보겠습니다.
지금 oracle bible 영진책을 보고 있어서요.
pro*c가 엄청 조금 나왔네요.
설명도 거의 없고 -_-;
설명대로 sqlca.sqlcode == 1403 해도 여전히 쓰레기가 나오네요.
지금 sqlca 와 sqlcode로 맹서치중입니다 ^^
답변 감사합니다.
오늘 너무 많은걸 배워서 기쁘네요 ^^
sqlcode 값이 0 이면 성공입니다.
sqlcode가 -1403 이면 더이상 데이터가 없는것으로 간주합니다. 그런데 일단 0이 아니면 에러니까 루프를 벗어나야 합니다.
그리고 fetch 할때 한개씩 할때(실제로는 보통 몇십개씩 fetch하는게 더 좋고, 더 자세하게 할려면 descriptor를 사용하는게 좋죠)는 배열이 아니라 한개의 구조체를 계속 재사용합니다.
========================================
* The truth will set you free.
ㅡ.ㅡ
보통 오라클에서 커서를 사용해서 하나의 row씩 처리하는 문의 구조는 다음과 같습니다.
1403은 DB 모드에 따라서 틀려질 수 있는 값이니까 define 문을 사용하셔도 되겠구요. SQLCODE는 sqlca.sqlcode를 의미하고요.
아마 님의 경우에는 WHENEVER NOT FOUND DO break;
문을 주셨으니까 SQLCODE를 검사 안해도 오라클에서 알아서 빠져나오도록
했을꺼 같습니다. 근데 다른 오류는 검사를 하지 않으셨네요. 실제로 쓰실 때에는 다른 오류도 검사하도록 하셔야 할꺼구요.
문제는 데이터를 가져온 후 출력할 때 출력조건 (NULL) 때문에 그렇습니다.
프로그램 초기에 10개의 포인터 배열을 만들고, 그 다음 문장에서 배열의 포인터들에 malloc()을 통해서 값을 할당해 주잖아요.
그러면 addr[i] 값을은 NULL이 아니라 할당된 주소를 가리키고 있습니다.
select_addr에 들어가서 해 주는 일은 각 배열의 포인터가 가리키고 있는 주소공간을 '\0' 들로 채워주고요.
for 루프를 돌면서 fetch를 통해서 DB에 들어있는 데이터를 addr[0]부터 쭈욱 채워주고요.
그리고는 select_addr()을 빠져나와서 main()에서 for loop를 이용해서 받아온 데이터를 출력하죠.
만일 4개의 데이터가 있었으면, 님께서는 addr[4] 가 NULL 이 되기를 기대하셔서 addr[4] != NULL 조건을 만족하지 않아서 for loop가 끝나기를 바랄텐데요,,
addr[4] 는 분명 '\0' 이 16개 들어있는 것은 맞지만 addr[4] 자체는 NULL 이 아닙니다. addr[4] 는 '\0'이 16개 들어있는 공간을 가리키는 주소값이 들어있습니다.
for 문을 다음과 같이 수정하시면 될 것입니다.
아니면 select_addr에서 몇개의 데이터를 fetch했는지 counter를 명시적으로 파라메터로 주고 받든지요.
다른 얘기 하나.
cursor 이름으로 select를 사용한 건 혼란을 일으킬만하니까 다른 것으로 바꾸시는 게 좋을 듯 합니다. ^^
select 한 건수는 sqlca.sqlerrd[2]
select 한 건수는 sqlca.sqlerrd[2] 입니다.
즉, sqlca 구조체의 멤버중에 sqlerrd 라는 이름의 int 형 배열이 있는데 이들중 3번째 ([2] 니까) 값에 실행한 횟수가 들어있습니다.
또 sqlca.sqlerrd[2]는 fetch뿐 아니라 insert, update. delete 건수도 들어간다고 하더군요.
(그럼 sqlca.sqlerrd[0], sqlca.sqlerrd[1] , sqlca.sqlerrd[3] 등은 뭐죠?)
내 자식들도 나처럼 !!
...흠..
malloc.... 초기화 안되는....... NULL 이 아니라서...
댓글 달기