출처 : http://thx4alice.tistory.com/396
Pro-C 간단 매뉴얼
---------------
2000. 5. 23
---------------
+++++++++++
ProC...
+++++++++++
-. 오라클 데이타베이스 내의 테이블에 존재하는 레코드들을 조회,수정 등의 데이타 처리를 하고, C프로그램으로 전환하기 위해 사용함.
-. C와의 차이점
-. 외형상의 차이 : 확장자가 .pc로 끝난다.
-. 기본적으로 C문법을 따르며, C프로그램코드에 DB에 접속하여 레코드들을 처리하는 과정이 추가되어 작성된다.
즉, C로 작성된 프로그램코드에 오라클의 SQL의 DML or DDL명령문이 'EXEC'구문과 결합된 형태가 추가된 것임을 알 수 있다.
-. 변수선언에서 C언어에서는 사용하지 않는, .arr과 .len이라는 변수가 컴파일된 C source코드에 생성되어 있는 것을 확인할 수 있다.
-. 컴파일 과정
-. filename.pc -> filename.c -> filename.o -> filename*(생성된 오브젝트 파일을 링크해서 실행파일을 만드는 과정이다.)
-. 실제 컴파일
-. makefile 위치
$ORACLE_HOME에 proc/에 보면 proc.mk파일이 있다.
이중에서
1) USERID = uinfo/mation
-. 오라클 DB에 접속할때 사용할 사용자 아이디와 비밀번호 지정
2) DEST = /home/elfsun/simple/bin
-. 컴파일후 실행파일을 복사할 디렉토리
3) COMM_OBJ = /home/elfsun/simple/lib/lib1.o\
/home/elfsun/simple/lib/lib2.o\
/home/elfsun/simple/lib/lib3.o\
/home/elfsun/simple/lib/lib4.o
-. 컴파일시 참조로할 오브젝트 파일들.
\(백슬레시)로 구분함.
4) all : $(PROGRAM)
-. 프로그램의 이름을 지정할 수 있다. 이것은 프로그램의 소스 이름이 되며, 컴파일후 생성될 실행 파일의 이름이 되기도 한다.
5) install :
-. 컴파일후 생성된 실행 파일을 복사해주는 작업을 수행
6) clean :
-. 컴파일 과정에서 생성되는 C파일과 오브젝트 파일들을 삭제할때 수행
이들중 수행할 각 명령들은 '@'바로 뒤에 작성해 줄 수 있다.
[실제 컴파일 수행 - makefile이름이 proc.mk인 경우]
1) 실제 컴파일을 하기 위해
$ make -f proc.mk
2) 컴파일한 실행 파일을 ~/bin/ 디렉토리에 복사하기 위해
$ make -f proc.mk install
3) 컴파일 후 생성되는 오브젝트 파일과 c파일을 삭제하기 위해
$ make -f proc.mk clean
-. SQLCA관련 변수들...
-. sqlca.sqlerr[0] : fetch를 사용하여 쿼리된 레코드의 건수를 리컨시켜 주는 역할을 하는 변수이다.
-. sqlca.sqlwarn : 경고에 대한 정보들을 지니고 있는 변수이다.
-. sqlca.sqlerrm.sqlerrmc : sql 명령수행중 에러가 발생했을때, 발생한 에러에 대한 내용과 오류 코드번호에 관한 정보를 출력시켜 준다.
---------------------------------------
-. sqlca.sqlcode값 내 용
---------------------------------------
0 sql문이 정상적으로 수행
1403 유일하게 양수값을 갖는 에러코드임.
조건에 맞는 데이타가 하나도 없을때.
-1405 조회된 값중 null값이 있을때
---------------------------------------
-. host변수 선언
-. 호스트변수는 데이타베이스에서 데이타 처리 결과를 저장하기 위해 사용되며, 응용 프로그램내에서는
변수로서의 역할을 한다. 따라서 호스트 변수를 선언할 때에는 데이타베이스 내에서 사용되는 칼럼의
데이타 타입과 그 크기를 고려하여 선언되어야 하며, 프리컴파일 과정을 통해 응용프로그램내에서도
사용가능한 형태이어야 한다.
ex)
EXEC SQL BEGIN DECLARE SECTION;
varchar username[16], userarea[10];
int usrno, usrage;
EXEC SQL END DECLARE SECTION;
[주의]
1) 호스트 변수 선언시에 오라클 예약어를 사용하지 말것.
2) 호스트 변수에서는 null처리를 해주지 않기 때문에 응용 프로그램에서 반드시 null처리를 해주어야 한다.
단, 호스트 변수가 숫자형인 경우에는 예외이다.
-. DB접속
방법1>
EXEC SQL CONNECT elfsun
INDENTIFIED BY 1234;
방법2>
EXEC SQL BEGIN DECLARE SECTION;
varchar userid[8], passwd[8];
EXEC SQL END DECALRE SECTION;
strncpy(userid.arr,"elfsun",6);
strncpy(passwd.arr,"1234",4);
EXEC SQL CONNECT :userid;
IDENTIFIED BY :passwd;
-. 일반적으로 방법2를 더 선호함.
-. 방법2를 쓸때에 변수명 앞에는 반드시 :를 붙여서 사용하고 있는 변수가 호스트 변수임을 명시해야 한다.
-. CURSOR이용 : 쿼리문으로 조회되는 레코드가 한 건 이상일때 사용함.
형식>
1) EXEC SQL PREPARE statement FROM variable; (쿼리하고자 하는 sql문장 정의)
2) EXEC SQL DECLARE cursor_name CURSOR FOR statement; ( 사용할 커서 선언 )
3) EXEC SQL OPEN cursor_name; ( 선언한 커서 열기 )
4) EXEC SQL FETCH cursor_name INTO :host_variable1, :host_variable2, :host_variable3, ....; ( 열어둔 커서 실행 )
5) EXEC SQL CLOSE cursor_name; ( 열었던 커서 닫음 )
1) EXEC SQL PREPARE statement FROM variable; (쿼리하고자 하는 sql문장 정의)
ex)
char SqlCmd[100]; (변수 SqlCmd를 선언)
memset(SqlCmd,0x00,sizeof(SqlCmd)); ( memset함수를 이용하여 초기화 작업함)
sprintf(SqlCmd,"SELECT usrno, usrname, usrarea FROM forumlist"); (쿼리문을 SqlCmd에 대입함)
EXEC SQL PREPARE st_1 from :SqlCmd; (EXEC..문장을 이용하여 쿼리할 구조를 정의함)
2) EXEC SQL DECLARE cursor_name CURSOR FOR statement; ( 사용할 커서 선언 )
형식1>
EXEC SQL DECLARE cursor_name CURSOR FOR statement;
형식2>
EXEC SQL DECLARE cursor_name CURSOR FOR select 문장;
-. cursor_name : 사용할 커서명
ex)
EXEC SQL DECLARE CUR_1 CURSOR FOR ST_1; (ST_1은 PREPARE에서 정의한것과 동일해야 함)
EXEC SQL DECLARE CUR_1 CURSOR FOR select usrno, username, userarea From forumlist;
3) EXEC SQL OPEN cursor_name; ( 선언한 커서 열기 )
ex)
EXEC SQL OPEN CUR_1;
4) EXEC SQL FETCH cursor_name INTO :host_variable1, :host_variable2, :host_variable3, ....; ( 열어둔 커서 실행 )
ex)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
......
EXEC SQL FETCH CUR_1 INTO :usrno, :usrname, :userarea;
-. 여기서 사용하는 조회된 칼럼들과 1대1로 대응되어야 한다.
또한 사용될 호스트 변수들은 이미 이전에 선언이 되어 있어야만 사용이 가능하다. 칼럼의 데이타 타입과 크기가
일치해야함에도 주의.
5) EXEC SQL CLOSE cursor_name; ( 열었던 커서 닫음 )
ex)
EXEC SQL CLOSE CUR_1;
-. 오류 처리
1) whenever sqlerror 구문
형식)
① EXEC SQL WHENEVER SQLERROR GOTO stop_st;
② EXEC SQL WHENEVER SQLERROR GOTO STOP;
③ EXEC SQL WHENEVER SQLERROR GOTO CONTINUE;
-. 위 문장들은 SQL문장의 수행 결과 리턴되는 sqlca.sqlcode의 값이 음수로서, 에러를 발생시키는 경우, 더이상
프로그램을 진행시키지 않도록 stop_st루틴(①번에 해당)으로 분기하여 프로그램의 에러처리를 하도록 하는 문장임.
stop_st대신 STOP나 CONTINUE를 쓰기도 한다.
-. 또한 실행시켰던 SQL문장들이 레코드의 값 자체의 변경과 관련이 있는 문장들, 즉 INSERT, DELETE, UPDATE와 같은
SQL문장들이었다면, 'EXEC SQL ROLLBACK WORK'명령을 이용하여 그 트렌잭션을 취소시키는 과정을 추가해 주어야 한다.
2) whenever not found 구문
형식)
EXEC SQL WHENEVER NOT FOUND GOTO stop_st;
EXEC SQL WHENEVER NOT FOUND STOP;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
-. 위 문장들은 SQL문장 실행 결과 sqlca.sqlcode값이 1403으로 조건에 맞는 레코드 건수가 하나도 없는 경우이다.
-. ProC내에서의 select 문장
ex1)
-------------------------------------------------------------
EXEC SQL BEGIN DECALRE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT usrno, usrname, usrarea
INTO : usro, :usrname, :usrarea
FROM forumlist
WHERE usrno=5;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n 회원의 고유번호 =%d",usrno);
printf("\n 회원의 이름 =%d",usrname.arr);
printf("\n 회원의 이름(크기) =%d BYTE", usrname.len);
printf("\n 회원의 거주지역 =%s", usrarea.arr);
printf("\n 회원의 거주지역(크기) =%d BYTE", usrarea.len);
stop_st :
printf("\n 에러메시지 =%s", sqlca.sqlerrm.sqlerrmc);
-------------------------------------------------------------
-. into 구문은 쿼리 결과에 만족하는 데이타를 검색해 와서 into구문 뒤의 변수에 각각 할당한다.
-. 호스트 변수명 앞에 (:)을 붙여 줌으로써 조회할 테이블이 칼럼명과 구분을 지어 준다.
ex2)
-------------------------------------------------------------
EXEC SQL BEGIN DECALRE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
char SqlCmdp100];
EXEC SQL END DECLARE SECTION;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(Sqlcmd,"select usrno, usrname, usrarea from forumlist");
EXEC SQL PREPARE ST_1 FROM :SqlCmd;
EXEC SQL DECLARE CUR_1 FOR ST_1;
EXEC SQL OPEN CUR_1;
EXEC SQL FETCH SUR_1 INTO :usrno, :usrname, :usrarea;
if (sqlca.sqlcode < && sqlca.sqlcode != -1405)
{
printf("\n 에러메시지 = %s", sqlca.sqlerrm.sqlerrmc);
printf("\n 레코드 조회시 에러 발생!");
EXEC SQL CLOSE CUR_1;
EXEC SQL ROLLBACK WORK;
exit();
} /* error */
else if(sqlca.sqlcode == 1403)
{
printf("\n 에러메시지 ="%s", sqlca.sqlerrm.sqlerrmc);
printf('\n 조건에 맞는 데이타가 없슴다!");
EXEC SQL CLOSE CUR_1;
EXEC SQL ROLLBACK WORK;
exit();
} /* not exist */
while(sqlca.sqlcode ==0)
{
printf("\n 회원의 고유번호 =%d",usrno);
printf("\n 회원의 이름 =%d",usrname.arr);
printf("\n 회원의 이름(크기) =%d BYTE",usrname.len);
printf("\n 회원의 거주지역 =%s", usrarea.arr);
printf("\n 회원의 거주지역(크기) =%d BYTE", usrarea.len);
EXEC SQL FETCH CUR_1 INTO :usrno, :usrname, :usrarea;
} /* while */
printf("\n 오라클 메시지 = %s",sqlca.sqlerrm.sqlerrmc);
printf("\n 레코드가 성공적으로 조회되었습니다.");
EXEC SQL CLOSE CUR_1;
EXEC SQL COMMIT WORK;
-------------------------------------------------------------
-. PROC속의 UPDATE문장
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIN DECLARE SECTION;
varchar username[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT usrno, username, usrarea
into :usrno, :usrname, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경전 회원[%d]번의 거주지역 =[%s]",usrno,usrarea.arr);
EXEC SQL COMMIT WORK;
strcpy(userarea.arr,"SEOUL");
usrarea.len =5;
EXEC SQL UPDATE FORUMLIST
SET usrarea =:usrarea
WHERE usrno =3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n 오라클 메시지 =%s",sqlca.sqlerrm.sqlerrmc);
EXEC SQL SELECT usrno,usrarea
INTO :usrno, :usrarea
FROM forumlist
WHERE usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경후의 회원 [%d]번의 거주지역 =[%s]", usrno.usrarea.arr);
EXEC SQL COMMIT WORK;
exit();
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 에러발생 =%s",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
EXEC SQL select usrno,username,usrarea
into :usrno, :usrname, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경전의 [%d]번째 회원의 거주지역 =[%s]", usrno, usrarea.arr);
EXEC SQL COMMIT WORK;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"UPDATE FORUMLIST set usrarea=%s \ (한 문장이 끝나지 않았기 때문에 \(역슬래시)를 사용함)
where usrno=3","seoul");
EXEC SQL EXCUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
EXEC SQL select usrno, usrarea
into :usrno, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경후의 [%d]번째 회원의 거주지역 =[%s]", usrno,usrarea.arr);
EXEC SQL COMMIT WORK;
exit();
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 에러 메시지 =%s", sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. 위의 update문을 약간 수정하면
sprintf(SqlCmd,"update forumlist set userarea=%s where usrno=%d","seoul",3);로 해도 됨.
-. ProC속의 Insert문장
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10], usrkindcode[4];
int usrno ;
EXEC SQL END DECLARE SECTION;
int tot;
tot =0;
usrno=10;
strncpy(usrname.arr,"LEE-Y-S",Strlen("LEE-Y-S"));
strncpy(usrarea.arr,"seoul",strlen("seoul"));
strncpy(usrkindcode,"1004",strlen("1004"));
EXEC SQL INSERT INTO FORUMLIST(usrno, usrname, usrarea, usrkindcode)
values(:usrno, :usrname, :usrarea, :usrkindcode);
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n insert success!!");
printf("\n 오라클 메시지 = %s", sqlca.sqlerrm.sqlerrmc);
EXEC SQL SELECT COUNT(*)
INTO :TOT
FROM FORUMLIST
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 =%d", tot);
EXEC SQL COMMIT WORK;
EXEC SQL SELECT usrno, usrarea
INTO :usrno, :usrarea
FROM FORUMLIST
WHERE usrno=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 추가된 회원 [%d]번의 거주지역 =[%s]", usrno, usrarea.arr);
EXEC SQL COMMIT WORK;
stop_st;
EXEC SQL ROLLBACK WORK;
printf("\n 오라클 에러=%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
ex1은 insert문장에 함께 기술해 줄 호스트 변수들을 선언해 주었지만...
ex2에서는 선언하지 않았다.
ex2의 첨에 있는 usrarea는 그 다음에 수행할 select명령에 필요한 선언 문장이다.
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLEARE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
int tot;
tot=0;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"insert into forumlist(usrno, usrname, usrarea, \
usrkindcode) values(%d, %s, %s, %s)", \
10,"lee-k-y","seoul","1004");
EXEC SQL EXECUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n Insert Success!");
EXEC SQL SELECT count(*)
into :tot;
from forumlist
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 = %d",tot);
EXEC SQL COMMIT WORK;
EXEC SQL SELECT usrno, usrarea
into :usrno, :usrarea
from forumlist
where usrno=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\ 추가된 회원 [%d]번의 거주지역 =[%s]",usrarea.arr);
EXEC SQL COMMIT WORK;
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 오라클 에러 = %d", sqlca.sqlerrm,sqlerrmc);
-----------------------------------------------------------------------------
-. Proc내에서의 delete문장.
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIGN DECLRAE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
int tot;
tot=0;
EXEC SQL DELETE FORUMLIST WHERE USRNO=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n Delete 문장 성공!!");
EXEC SQL SELECT count(*)
into :tot;
from forumlist
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 =%d",tot);
EXEC SQL COMMIT WORK;
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n Oracle Error =%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. 어떠한 호스트 변수도 사용하지 않음.
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
int tot;
tot=0;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"Delete forumlist where usrno=%d",10);
EXEC SQL EXCUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
prinf("\n Delete Success!!");
EXEC SQL SELECT COUNT(*)
INTO :TOT;
FROM FORUMLIST
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수=%d",tot);
EXEC SQL COMMIT WORK;
stop_st;
EXEC SQL ROLLBACK WORK;
printf("\n Oracle Error : =%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. where절에서 회원의 고유번호값을 지정해주었다.는 점이 ex1과 다른점이다.
-. delete 부분을 다음과 같이 수정해도 된다.
usrnum=10;
sqlprintf(SqlCmd,"delete forumlist where usrno=%d",usrnum);
이처럼 변수를 먼저 선언해준 후 값을 대입해서 삭제 하는 방법도 있다.
-. 트랜잭션의 제어
-. EXEC SQL COMMIT WORK;
: DML 명령인 INSERT, DELETE ,UPDATE 문장을 수행한 경우에 유용하다.
: DDL 명령은 자동 COMMIT 되므로 사용안해도 됨.
-. EXEC SQL ROLLBACK WORK;
Pro-C 간단 매뉴얼
---------------
2000. 5. 23
---------------
+++++++++++
ProC...
+++++++++++
-. 오라클 데이타베이스 내의 테이블에 존재하는 레코드들을 조회,수정 등의 데이타 처리를 하고, C프로그램으로 전환하기 위해 사용함.
-. C와의 차이점
-. 외형상의 차이 : 확장자가 .pc로 끝난다.
-. 기본적으로 C문법을 따르며, C프로그램코드에 DB에 접속하여 레코드들을 처리하는 과정이 추가되어 작성된다.
즉, C로 작성된 프로그램코드에 오라클의 SQL의 DML or DDL명령문이 'EXEC'구문과 결합된 형태가 추가된 것임을 알 수 있다.
-. 변수선언에서 C언어에서는 사용하지 않는, .arr과 .len이라는 변수가 컴파일된 C source코드에 생성되어 있는 것을 확인할 수 있다.
-. 컴파일 과정
-. filename.pc -> filename.c -> filename.o -> filename*(생성된 오브젝트 파일을 링크해서 실행파일을 만드는 과정이다.)
-. 실제 컴파일
-. makefile 위치
$ORACLE_HOME에 proc/에 보면 proc.mk파일이 있다.
이중에서
1) USERID = uinfo/mation
-. 오라클 DB에 접속할때 사용할 사용자 아이디와 비밀번호 지정
2) DEST = /home/elfsun/simple/bin
-. 컴파일후 실행파일을 복사할 디렉토리
3) COMM_OBJ = /home/elfsun/simple/lib/lib1.o\
/home/elfsun/simple/lib/lib2.o\
/home/elfsun/simple/lib/lib3.o\
/home/elfsun/simple/lib/lib4.o
-. 컴파일시 참조로할 오브젝트 파일들.
\(백슬레시)로 구분함.
4) all : $(PROGRAM)
-. 프로그램의 이름을 지정할 수 있다. 이것은 프로그램의 소스 이름이 되며, 컴파일후 생성될 실행 파일의 이름이 되기도 한다.
5) install :
-. 컴파일후 생성된 실행 파일을 복사해주는 작업을 수행
6) clean :
-. 컴파일 과정에서 생성되는 C파일과 오브젝트 파일들을 삭제할때 수행
이들중 수행할 각 명령들은 '@'바로 뒤에 작성해 줄 수 있다.
[실제 컴파일 수행 - makefile이름이 proc.mk인 경우]
1) 실제 컴파일을 하기 위해
$ make -f proc.mk
2) 컴파일한 실행 파일을 ~/bin/ 디렉토리에 복사하기 위해
$ make -f proc.mk install
3) 컴파일 후 생성되는 오브젝트 파일과 c파일을 삭제하기 위해
$ make -f proc.mk clean
-. SQLCA관련 변수들...
-. sqlca.sqlerr[0] : fetch를 사용하여 쿼리된 레코드의 건수를 리컨시켜 주는 역할을 하는 변수이다.
-. sqlca.sqlwarn : 경고에 대한 정보들을 지니고 있는 변수이다.
-. sqlca.sqlerrm.sqlerrmc : sql 명령수행중 에러가 발생했을때, 발생한 에러에 대한 내용과 오류 코드번호에 관한 정보를 출력시켜 준다.
---------------------------------------
-. sqlca.sqlcode값 내 용
---------------------------------------
0 sql문이 정상적으로 수행
1403 유일하게 양수값을 갖는 에러코드임.
조건에 맞는 데이타가 하나도 없을때.
-1405 조회된 값중 null값이 있을때
---------------------------------------
-. host변수 선언
-. 호스트변수는 데이타베이스에서 데이타 처리 결과를 저장하기 위해 사용되며, 응용 프로그램내에서는
변수로서의 역할을 한다. 따라서 호스트 변수를 선언할 때에는 데이타베이스 내에서 사용되는 칼럼의
데이타 타입과 그 크기를 고려하여 선언되어야 하며, 프리컴파일 과정을 통해 응용프로그램내에서도
사용가능한 형태이어야 한다.
ex)
EXEC SQL BEGIN DECLARE SECTION;
varchar username[16], userarea[10];
int usrno, usrage;
EXEC SQL END DECLARE SECTION;
[주의]
1) 호스트 변수 선언시에 오라클 예약어를 사용하지 말것.
2) 호스트 변수에서는 null처리를 해주지 않기 때문에 응용 프로그램에서 반드시 null처리를 해주어야 한다.
단, 호스트 변수가 숫자형인 경우에는 예외이다.
-. DB접속
방법1>
EXEC SQL CONNECT elfsun
INDENTIFIED BY 1234;
방법2>
EXEC SQL BEGIN DECLARE SECTION;
varchar userid[8], passwd[8];
EXEC SQL END DECALRE SECTION;
strncpy(userid.arr,"elfsun",6);
strncpy(passwd.arr,"1234",4);
EXEC SQL CONNECT :userid;
IDENTIFIED BY :passwd;
-. 일반적으로 방법2를 더 선호함.
-. 방법2를 쓸때에 변수명 앞에는 반드시 :를 붙여서 사용하고 있는 변수가 호스트 변수임을 명시해야 한다.
-. CURSOR이용 : 쿼리문으로 조회되는 레코드가 한 건 이상일때 사용함.
형식>
1) EXEC SQL PREPARE statement FROM variable; (쿼리하고자 하는 sql문장 정의)
2) EXEC SQL DECLARE cursor_name CURSOR FOR statement; ( 사용할 커서 선언 )
3) EXEC SQL OPEN cursor_name; ( 선언한 커서 열기 )
4) EXEC SQL FETCH cursor_name INTO :host_variable1, :host_variable2, :host_variable3, ....; ( 열어둔 커서 실행 )
5) EXEC SQL CLOSE cursor_name; ( 열었던 커서 닫음 )
1) EXEC SQL PREPARE statement FROM variable; (쿼리하고자 하는 sql문장 정의)
ex)
char SqlCmd[100]; (변수 SqlCmd를 선언)
memset(SqlCmd,0x00,sizeof(SqlCmd)); ( memset함수를 이용하여 초기화 작업함)
sprintf(SqlCmd,"SELECT usrno, usrname, usrarea FROM forumlist"); (쿼리문을 SqlCmd에 대입함)
EXEC SQL PREPARE st_1 from :SqlCmd; (EXEC..문장을 이용하여 쿼리할 구조를 정의함)
2) EXEC SQL DECLARE cursor_name CURSOR FOR statement; ( 사용할 커서 선언 )
형식1>
EXEC SQL DECLARE cursor_name CURSOR FOR statement;
형식2>
EXEC SQL DECLARE cursor_name CURSOR FOR select 문장;
-. cursor_name : 사용할 커서명
ex)
EXEC SQL DECLARE CUR_1 CURSOR FOR ST_1; (ST_1은 PREPARE에서 정의한것과 동일해야 함)
EXEC SQL DECLARE CUR_1 CURSOR FOR select usrno, username, userarea From forumlist;
3) EXEC SQL OPEN cursor_name; ( 선언한 커서 열기 )
ex)
EXEC SQL OPEN CUR_1;
4) EXEC SQL FETCH cursor_name INTO :host_variable1, :host_variable2, :host_variable3, ....; ( 열어둔 커서 실행 )
ex)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
......
EXEC SQL FETCH CUR_1 INTO :usrno, :usrname, :userarea;
-. 여기서 사용하는 조회된 칼럼들과 1대1로 대응되어야 한다.
또한 사용될 호스트 변수들은 이미 이전에 선언이 되어 있어야만 사용이 가능하다. 칼럼의 데이타 타입과 크기가
일치해야함에도 주의.
5) EXEC SQL CLOSE cursor_name; ( 열었던 커서 닫음 )
ex)
EXEC SQL CLOSE CUR_1;
-. 오류 처리
1) whenever sqlerror 구문
형식)
① EXEC SQL WHENEVER SQLERROR GOTO stop_st;
② EXEC SQL WHENEVER SQLERROR GOTO STOP;
③ EXEC SQL WHENEVER SQLERROR GOTO CONTINUE;
-. 위 문장들은 SQL문장의 수행 결과 리턴되는 sqlca.sqlcode의 값이 음수로서, 에러를 발생시키는 경우, 더이상
프로그램을 진행시키지 않도록 stop_st루틴(①번에 해당)으로 분기하여 프로그램의 에러처리를 하도록 하는 문장임.
stop_st대신 STOP나 CONTINUE를 쓰기도 한다.
-. 또한 실행시켰던 SQL문장들이 레코드의 값 자체의 변경과 관련이 있는 문장들, 즉 INSERT, DELETE, UPDATE와 같은
SQL문장들이었다면, 'EXEC SQL ROLLBACK WORK'명령을 이용하여 그 트렌잭션을 취소시키는 과정을 추가해 주어야 한다.
2) whenever not found 구문
형식)
EXEC SQL WHENEVER NOT FOUND GOTO stop_st;
EXEC SQL WHENEVER NOT FOUND STOP;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
-. 위 문장들은 SQL문장 실행 결과 sqlca.sqlcode값이 1403으로 조건에 맞는 레코드 건수가 하나도 없는 경우이다.
-. ProC내에서의 select 문장
ex1)
-------------------------------------------------------------
EXEC SQL BEGIN DECALRE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT usrno, usrname, usrarea
INTO : usro, :usrname, :usrarea
FROM forumlist
WHERE usrno=5;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n 회원의 고유번호 =%d",usrno);
printf("\n 회원의 이름 =%d",usrname.arr);
printf("\n 회원의 이름(크기) =%d BYTE", usrname.len);
printf("\n 회원의 거주지역 =%s", usrarea.arr);
printf("\n 회원의 거주지역(크기) =%d BYTE", usrarea.len);
stop_st :
printf("\n 에러메시지 =%s", sqlca.sqlerrm.sqlerrmc);
-------------------------------------------------------------
-. into 구문은 쿼리 결과에 만족하는 데이타를 검색해 와서 into구문 뒤의 변수에 각각 할당한다.
-. 호스트 변수명 앞에 (:)을 붙여 줌으로써 조회할 테이블이 칼럼명과 구분을 지어 준다.
ex2)
-------------------------------------------------------------
EXEC SQL BEGIN DECALRE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
char SqlCmdp100];
EXEC SQL END DECLARE SECTION;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(Sqlcmd,"select usrno, usrname, usrarea from forumlist");
EXEC SQL PREPARE ST_1 FROM :SqlCmd;
EXEC SQL DECLARE CUR_1 FOR ST_1;
EXEC SQL OPEN CUR_1;
EXEC SQL FETCH SUR_1 INTO :usrno, :usrname, :usrarea;
if (sqlca.sqlcode < && sqlca.sqlcode != -1405)
{
printf("\n 에러메시지 = %s", sqlca.sqlerrm.sqlerrmc);
printf("\n 레코드 조회시 에러 발생!");
EXEC SQL CLOSE CUR_1;
EXEC SQL ROLLBACK WORK;
exit();
} /* error */
else if(sqlca.sqlcode == 1403)
{
printf("\n 에러메시지 ="%s", sqlca.sqlerrm.sqlerrmc);
printf('\n 조건에 맞는 데이타가 없슴다!");
EXEC SQL CLOSE CUR_1;
EXEC SQL ROLLBACK WORK;
exit();
} /* not exist */
while(sqlca.sqlcode ==0)
{
printf("\n 회원의 고유번호 =%d",usrno);
printf("\n 회원의 이름 =%d",usrname.arr);
printf("\n 회원의 이름(크기) =%d BYTE",usrname.len);
printf("\n 회원의 거주지역 =%s", usrarea.arr);
printf("\n 회원의 거주지역(크기) =%d BYTE", usrarea.len);
EXEC SQL FETCH CUR_1 INTO :usrno, :usrname, :usrarea;
} /* while */
printf("\n 오라클 메시지 = %s",sqlca.sqlerrm.sqlerrmc);
printf("\n 레코드가 성공적으로 조회되었습니다.");
EXEC SQL CLOSE CUR_1;
EXEC SQL COMMIT WORK;
-------------------------------------------------------------
-. PROC속의 UPDATE문장
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIN DECLARE SECTION;
varchar username[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT usrno, username, usrarea
into :usrno, :usrname, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경전 회원[%d]번의 거주지역 =[%s]",usrno,usrarea.arr);
EXEC SQL COMMIT WORK;
strcpy(userarea.arr,"SEOUL");
usrarea.len =5;
EXEC SQL UPDATE FORUMLIST
SET usrarea =:usrarea
WHERE usrno =3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n 오라클 메시지 =%s",sqlca.sqlerrm.sqlerrmc);
EXEC SQL SELECT usrno,usrarea
INTO :usrno, :usrarea
FROM forumlist
WHERE usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경후의 회원 [%d]번의 거주지역 =[%s]", usrno.usrarea.arr);
EXEC SQL COMMIT WORK;
exit();
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 에러발생 =%s",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
EXEC SQL select usrno,username,usrarea
into :usrno, :usrname, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경전의 [%d]번째 회원의 거주지역 =[%s]", usrno, usrarea.arr);
EXEC SQL COMMIT WORK;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"UPDATE FORUMLIST set usrarea=%s \ (한 문장이 끝나지 않았기 때문에 \(역슬래시)를 사용함)
where usrno=3","seoul");
EXEC SQL EXCUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
EXEC SQL select usrno, usrarea
into :usrno, :usrarea
from forumlist
where usrno=3;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 변경후의 [%d]번째 회원의 거주지역 =[%s]", usrno,usrarea.arr);
EXEC SQL COMMIT WORK;
exit();
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 에러 메시지 =%s", sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. 위의 update문을 약간 수정하면
sprintf(SqlCmd,"update forumlist set userarea=%s where usrno=%d","seoul",3);로 해도 됨.
-. ProC속의 Insert문장
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrname[16], usrarea[10], usrkindcode[4];
int usrno ;
EXEC SQL END DECLARE SECTION;
int tot;
tot =0;
usrno=10;
strncpy(usrname.arr,"LEE-Y-S",Strlen("LEE-Y-S"));
strncpy(usrarea.arr,"seoul",strlen("seoul"));
strncpy(usrkindcode,"1004",strlen("1004"));
EXEC SQL INSERT INTO FORUMLIST(usrno, usrname, usrarea, usrkindcode)
values(:usrno, :usrname, :usrarea, :usrkindcode);
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n insert success!!");
printf("\n 오라클 메시지 = %s", sqlca.sqlerrm.sqlerrmc);
EXEC SQL SELECT COUNT(*)
INTO :TOT
FROM FORUMLIST
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 =%d", tot);
EXEC SQL COMMIT WORK;
EXEC SQL SELECT usrno, usrarea
INTO :usrno, :usrarea
FROM FORUMLIST
WHERE usrno=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n 추가된 회원 [%d]번의 거주지역 =[%s]", usrno, usrarea.arr);
EXEC SQL COMMIT WORK;
stop_st;
EXEC SQL ROLLBACK WORK;
printf("\n 오라클 에러=%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
ex1은 insert문장에 함께 기술해 줄 호스트 변수들을 선언해 주었지만...
ex2에서는 선언하지 않았다.
ex2의 첨에 있는 usrarea는 그 다음에 수행할 select명령에 필요한 선언 문장이다.
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLEARE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
int tot;
tot=0;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"insert into forumlist(usrno, usrname, usrarea, \
usrkindcode) values(%d, %s, %s, %s)", \
10,"lee-k-y","seoul","1004");
EXEC SQL EXECUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n Insert Success!");
EXEC SQL SELECT count(*)
into :tot;
from forumlist
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 = %d",tot);
EXEC SQL COMMIT WORK;
EXEC SQL SELECT usrno, usrarea
into :usrno, :usrarea
from forumlist
where usrno=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\ 추가된 회원 [%d]번의 거주지역 =[%s]",usrarea.arr);
EXEC SQL COMMIT WORK;
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n 오라클 에러 = %d", sqlca.sqlerrm,sqlerrmc);
-----------------------------------------------------------------------------
-. Proc내에서의 delete문장.
-----------------------------------------------------------------------------
ex1)
EXEC SQL BEGIGN DECLRAE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
int tot;
tot=0;
EXEC SQL DELETE FORUMLIST WHERE USRNO=10;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
printf("\n Delete 문장 성공!!");
EXEC SQL SELECT count(*)
into :tot;
from forumlist
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수 =%d",tot);
EXEC SQL COMMIT WORK;
stop_st:
EXEC SQL ROLLBACK WORK;
printf("\n Oracle Error =%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. 어떠한 호스트 변수도 사용하지 않음.
-----------------------------------------------------------------------------
ex2)
EXEC SQL BEGIN DECLARE SECTION;
varchar usrarea[10];
int usrno;
EXEC SQL END DECLARE SECTION;
char SqlCmd[100];
int tot;
tot=0;
memset(SqlCmd,0x00,sizeof(SqlCmd));
sprintf(SqlCmd,"Delete forumlist where usrno=%d",10);
EXEC SQL EXCUTE IMMEDIATE :SqlCmd;
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
EXEC SQL COMMIT WORK;
prinf("\n Delete Success!!");
EXEC SQL SELECT COUNT(*)
INTO :TOT;
FROM FORUMLIST
EXEC SQL WHENEVER SQLERROR GOTO stop_st;
printf("\n forumlist 테이블에 존재하는 총 회원 수=%d",tot);
EXEC SQL COMMIT WORK;
stop_st;
EXEC SQL ROLLBACK WORK;
printf("\n Oracle Error : =%d",sqlca.sqlerrm.sqlerrmc);
-----------------------------------------------------------------------------
-. where절에서 회원의 고유번호값을 지정해주었다.는 점이 ex1과 다른점이다.
-. delete 부분을 다음과 같이 수정해도 된다.
usrnum=10;
sqlprintf(SqlCmd,"delete forumlist where usrno=%d",usrnum);
이처럼 변수를 먼저 선언해준 후 값을 대입해서 삭제 하는 방법도 있다.
-. 트랜잭션의 제어
-. EXEC SQL COMMIT WORK;
: DML 명령인 INSERT, DELETE ,UPDATE 문장을 수행한 경우에 유용하다.
: DDL 명령은 자동 COMMIT 되므로 사용안해도 됨.
-. EXEC SQL ROLLBACK WORK;