반응형
Pro-C 간단 매뉴얼 --------------- 2000. 5. 23 --------------- +++++++++++ ProC... +++++++++++ -. 오라클 데이타베이스 테이블에 존재하는 레코드 조회,수정 등 데이타 처리를 하고, C 프로그램으로 전환/연동함. -. C 언어와 차이점 -. 외형 차이 : 확장자가 *.pc -. 기본 C 문법을 따르며, C 프로그램 코드에 DB 접속 레코드 처리 과정 등이 추가 작성 즉, C 프로그램 코드에 오라클 SQL의 DML or DDL 명령문이 'EXEC' 구문과 결합된 형태로 추가 -. 변수 선언에 C 언어에 없는 .arr과 .len이라는 변수가 컴파일된 C 소스 코드에 생성됨 -. 컴파일 과정 -. 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; |
출처: https://blocked.tistory.com/396 [...낭만코딩 ^^]
반응형
'DBMS, 데이터베이스' 카테고리의 다른 글
레디스, Redis 이야기 (0) | 2022.05.14 |
---|---|
Pro*C 가이드 (pdf) (0) | 2022.05.10 |
Pro*C, gcc/cc로 *.pc 파일 컴파일 (0) | 2022.05.10 |
Pro*C, 오라클 DBMS 연동 (0) | 2022.05.10 |
Docker 설치하고 MariaDB 실행하기 (0) | 2022.04.24 |