대표사진
tobewiseys
  1. 데이터베이스

이미지

도서명 표기
Oracle Pro*C 실무 프로젝트 활용서
글쓴이
주경호 저
비팬북스(러닝스페이스)
평균
별점6.5 (4)
tobewiseys

호스트 변수(Host Variable)가 무엇인지, SQLCA(SQL Communication Area)가 무엇인지, ORACA(Oracle Communication Area)를 왜 써야 하는지, Host Array를 언제 써야 하는지 잘 모르는 상태에서, 프로젝트에 투입되어 Pro*C 프로그램을 작성했었던 적이 있다.


 


이러한 내용들은 이미 경험 많은 선배 프로그래머들에게는 너무나 당연한 내용이기 때문에, 초보자에게 간단히 설명하고 자신들의 일에 몰두하는 경우가 많았다. 질문을 하면 구박당하기 쉬웠고, 친절한 선배의 경우에는 예제를 던져주고는 "공부 좀 해라"는 정도였다.


 


따라서, 예제 프로그램, 인터넷, 오라클의 영문자료 등을 읽고 실습하면서 하나 하나 이해해 가야했는데, (그때 그때의 이슈에 따라 관심사가 달라서 그런지) 전체가 체계적으로 정리되기까지 많은 시간이 소요되었다. 실무에서 많이 사용되고 있었음에도 불구하고, 그동안 참고할 만한 한글책이 없었던 것이 항상 아쉬웠었는데, 주경호님이 초보 개발자에게 도움이 되는 책을 출판하였다.


 


다음은 책의 내용을 요약한 것이다.


1장에서 Pro*C를 소개하고 있다. SQL은 원하는 결과만 DBMS에게 요청하는 비절차적인 언어이기 때문에, 개발자가 원하는 형태로 데이터를 가공하는데는 많은 제약이 있다. 따라서, 개발자가 데이터를 마음대로(?) 제어할 수 있는 PL/SQL가 제공되었으나, DBMS 내부에서 수행되기 때문에 오류 발생시 DBMS 종료되거나 DBMS의 부하가 증가하는 문제가 있었다. 이러한 문제를 해결하기 위하여, DBMS 밖에서 데이터를 정밀하게 제어할 수 있도록 C 언어에 SQL문장을 내장시킨(Embedded SQL) Pro*C가 탄생하게 되었다. 


 


프로그램을 작성하는 방식은 내장 SQL을 사용하는 방식과 OCI(Oracle Call Interface)를 이용하는 방법이 있는데, 실무에서는 주로 내장 SQL방식을 사용한다고 이해하면 되겠다. 현재 엔터프라이즈 급 애플리케이션에서 Java가 강세이지만, 배치 프로그램이나, 성능을 요구하는 경우에는, Pro*C 프로그램이 많이 활용되고 있다고 생각하면 되겠다. 


 


1장의 마지막부분은 Pro*C의 데이터 형에 대해서 설명하고 있다. Pro*C의 데이터 형이 Oracle의 데이터형과 어떻게 호환되는지 매핑표를 제시하고 있다. 여기에서 특히 VARCHAR 형에 대해서 주의하자. VARCHAR uid[20]; 이렇게 선언하면, 내부적으로 아래와 같은 구조체와 동일하다고 이해하는 것이 중요하다.


struct {


  unsigned short int len;


 unsigned char arr[20];


} uid;


 


참고로 char형이나 VARCHAR형이나, DB에 있는 데이터를 가져올 때 문자열의 끝이 null로 끝나지 않으면 C프로그램에서 core dump 등의 문제가 발생할 수 있다. https://forums.oracle.com/forums/thread.jspa?threadID=466684


따라서 일반적으로 DB의 데이터 길이보다 1바이트 더 크게 잡는다. 위의 URL에서 보면 emp 테이블의 길이가 10바이트이면 char emp_name[11];로 잡는 것이 바람직하다고 나와 있는데, 11로 적으면 원래 11바이트인지 null문자까지 고려한 것인지 DB를 보고 확인해야 하므로, char emp_name[10+1]; 과 같이 표현하는 방식을 이용하는 것이 바람직하다.


 


VARCHAR형은 input 방향은 문자열이 null로 끝나지 않아도 문제가 없지만, output 방향으로 데이터를 받아올 때는 기본적으로 null이 붙어서 오지 않기 때문에 문자열끝에 null을 붙이는 작업을 해야 한다. 따라서 DB의 데이터 길이 +1로 선언해서 처리하는 것이 필요하다.


 


Pro*C 프로그램에서 core dump가 떨어지면서 프로그램이 종료하는 이유중 가장 큰 비율은  잘못된 문자열처리 때문이 아닌가 싶다. 따라서, 문자열의 null처리를 위한 공간확보에 주의를 해야 할 것이다.


 


2장에서는 오류를 진단하기 위하여 사용되는 SQLCA(SQL Communication Area) 구조체와 ORACA(Oracle Communication Area)에 대한 설명을 하고 있다. 특히, SQLCA 구조체의 멤버들에 대해서는 잘 알아야 한다. sqlca.sqlcode에 대해서는 당연히 알아야 하고, sqlca.sqlerrm, sqlca.sqlerrd나 sqlca.sqlwarn 을 주의해서 살펴보기 바란다.


 


실제로 Pro*C를 이용하여 프로그램을 작성할 때 SQLCA만 보고도 대부분 문제가 없이 처리되지만, 복잡한 프로그램의 경우에는 Pro*C 프로그램에 대한 좀더 상세한 정보가 필요하다. 이 때 사용되는 것이 ORACA 구조체인데 특히, 에러가 발생한 SQL문장, 파일이름, 행번호를 알 수 있다는데 주의해서 살펴보자.


 


3장에서는 프로그램의 구성을 어플리케이션 프롤로그(변수 선언, include, connect, 트랜잭션 제어 등)과 어플리케이션 본체로 구분하여 설명하고 있다.


 


선언절에서는 EXEC SQL BEGIN DECLARE SECTION ... END DECLARE SECTION을 이용하여 호스트변수를 선언하는 방법을 설명하고 있다. SQL문장과 C 프로그램 모두에서 사용할 수 있는 호스트변수(Host Variable)와, 호스트변수 값이 NULL값인지 여부를 나타내는 표지변수(Indicator Variable)에 대해서 설명하고 있다.


 


inlcude 절에서는 함수, #define문, Alias가 선언되어 있으며, connect 절에서는 DB가 같은 서버에 설치된 것처럼 인식하도록하는 로컬 DB 접속 방법, 원격 DB 접속 방법, 여러 DB에 접속하는 방법에 대해서 설명하고 있다. 여러 DB에 접속하는 경우에는 세션별로 별개의 트랜잭션으로 처리되므로, 하나의 트랜잭션으로 처리하려면 별도의 접속보다는 DBLink를 사용하라고 설명하고 있다. 마지막으로 트랜잭션 제어를 위하여 commit, rollback, release의 의미, savepoint에 대해서 설명하고 있다.


 


4장에서는  컴파일 환경에 대해서 설명하고 있다.


프리컴파일은  .pc파일을 C 컴파일러가 인식할 수 있는 .c 파일로 만들며, pro*c 컴파일러의 옵션을 지정하는 방법, 옵션의 종류와 의미에 대해서 설명하고 있다.


 


C 컴파일: cc -c  는 c 소스프로그램을 *.o 오브젝트파일로 변환하며, pro*c의 경우에는 sqlca.h가 필수로 포함되어야 한다.  (-I/$ORACLE_HOME/precomp/public ).  cc -o 는 오브젝트 파일과 시스템/사용자 정의 라이브러리 파일을 결함하여 실행파일을 생성한다.  DB 접속 및 핸들링에 필요한 오라클 라이브러리 참조가 필요하다. 라이브러리 참조를 지정하는 방법은 라이브러리 파일  이름이 lib로 시작하면 lib를 -ㅣ로 바꾸고 확장자를 제거하고 기술해야 한다. 예를 들면, libclntsh.so는 -lclntsh 로 지정해야 한다(이것도 실수를 자주하는 부분이다)


 


make 파일을 만들어 사용하기가 쉽지 않은 이유는 OS/버전/CPU가 다르고, 64비트/32비트 등 단계별 옵션이 다양하기 때문이라고 한다. 따라서, demo_proc.mk 파일을 자신의 상황에 맞게 최적화가 하는 것이 바람직하며, 이를 위하여 make -nf 를 활용하는 방법을 설명하고 있다.


 


참고로 make 파일을 만들 때 명령어 앞에 TAB을 사용하지 않으면 제대로 작동하지 않는다.  자주 발생하는 문제임에도 찾기가 쉽지 않으니 주의하자. 아래의 URL을 참조.


http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/minzkn_make


http://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-2.html


 


5장에서는 단일 행 추출을 위한 간단한 예제가 있고, 6장에서는 다중 행을 추출하기 위하여 커서를 DECLARE, OPEN, FETCH, CLOSE하는 방법에 대한 설명이 있다. 


 


7장에서는  DBMS call을 줄이기 위한 방법으로 Host Array를 이용하는 방법에 대해서 설명하고 있다. 여기서 주의할 점은 108페이지에서 설명된 바와 같이 sqlca.sqlerrd[2]에 대한 해석인데, 아래의 URL에서 좀더 자세히 설명되어 있다.


 


http://docs.oracle.com/cd/B19306_01/appdev.102/b14407/pc_08arr.htm#i5620


For INSERT, UPDATE, DELETE, and SELECT INTO statements, sqlca.sqlerrd[2] records the number of rows processed. For FETCH statements, it records the cumulative sum of rows processed.


When using host arrays with FETCH, to find the number of rows returned by the most recent iteration, subtract the current value of sqlca.sqlerrd[2] from its previous value (stored in another variable). (INSERT, UPDATE, DELETE, SELECT INTO 문장에 대한 sqlca.sqlerrd[2]는 처리된 행의 수를 기록하고 있다. FETCH문장에 대해서는 처리된 행의 누적치를 기록한다. FETCH를 수행할 때 Host Array가 사용되었다면, 가장 최신의 반복에서 반환된 행의수는 현재의 sqlca.sqlerrd[2]의 값에서 이전의 sqlca.sqlerrd[2]의 값을 빼야 한다. )


 


그런데 191,193페이지의 소스를 보면 선택한 행의 총수를 세기 위해서는 SelectRow=SelectRow + sqlca.sqlerrd[2]; 와 같은 방식으로 계산하고 있다.  이 부분의 소스는 수정되어야 할 것이다.


 


8장에서는 여러 개의 Host 변수를 사용하는 것이 불편하므로 Host Structure를 이용하는 방법에 대해서 설명하고 있고, 9장에서는 프로그램 오류를 처리하는 방법에 대해서 설명하고 있다. 특히, 프로그램의 오류중 DB에서 조회한 컬럼의 값이 NULL일 때의 ORA-1405 오류에 대하여 처리하는 방법 두 가지를 설명하고 있다. 첫번째는 NVL 함수를 이용하여 프로그램을 수정하는 방법이고, 두번째는 성능을 고려하여 컴파일러 옵션(unsafe_null=yes dbms=v8) 을 변경하는 방법이다. 또한, 변수의 초기화(memset)가 중요하다고 설명하고 있다.


 


10장에서는 오라클 8i, 9i, 10g의 Pro*C 컴파일러는 Analytic Function을 인식하지 못하므로, Dynamic SQL을 사용해야하며, Dynamic SQL을 이용하면 Analytic Function 뿐만 아니라, Scalar Sub query, 테이블 명의 조건별 변경도 가능하다고 설명하고 있다. 특히,  바인드 변수의 사용를 사용하면,  Library Cache 메모리 낭비하지 않을 수 있고 성능을 향상시킬 수 있다고 설명하고 있다. 


 


11장에서는 Stored Procedure와 Package가 이미 컴파일되어 있고, 최초 실행 시만 파싱되며, 재수행 시 메모리에 저장된 파싱결과를 수행하므로, 재사용, 절차형 프로그램, 성능개선 용이점에서 장점을 가지고 있다고 설명하고 있다. SP 호출 Pro*C를 컴파일하기 위해서는 sqlcheck=full 컴파일 옵션이 지정되어야 한다고 설명하고 있다. 


 


12징에서는 실무적 관점에서 프로그램을 어떻게 정형화할 것인지 설명하고 있다. 


1) 헤더 파일 정의 - 포함해야 할 헤더 파일들을 정리하고, 필요한 별명(Alias)정의해야 한다. (예, SQLCODE, SQLMSG, SQLCOUNT ...)


 


2) DB 접속 부 정의 - 접속암호변경으로 인하여 관련 프로그램을 수정하지 않도록, 데이터베이스 접속 관리 부분은 모듈화되어야 하며, 개발자는 해당 모듈을 자신의 프로그램에 결합하여 사용해야 한다고 설명하고 있다. 접속모듈이 연결정보를 암호화된 파일등을 읽어 처리하면, 암호변경이 용이하고 애플리케이션 재 컴파일이 불필요한 장점을 가진다.


 


3) 에러 및 작업 기록(LOG) 정의 - 운영에 필요한 정보를 기록하는 위치 정의하고, 정상일 때 기록하는 정보, 에러 발생 시 기록하는 정보를 사전에 정의해야 한다. 정상작업 시 데이터 추출 건수 및 갱신 건수를 기록하고, 에러 발생 시 에러 내용을 인자값으로 받아 기록하는 것이 필요하다.


 


4) 에러 처리부 정의 - SQL 오류 발생 시 발생 내역을 파일에 기록하면, 발생 시점의 SQL문장, 에러 내역, 에러 발생 라인을 알 수 있으므로 오류해결이 용이하다. 즉, ORACA를 이용하여 에러가 발생한 프로그램의 라인과 SQL문장을 출력해야 한다.


 


마지막으로 UNIX에서 object 파일(*.o)들을  묶어서 archive 파일을 만드는 방법에 대해서 설명하고, ar -r libUsrLib.a Err.o Write.o Dbcon.o  이 라이브러리를 이용하여 실행 파일을 만드는 방법을 설명하고 있다. cc +DA2.0W -Ae +DD64 -o PMultiRow PMulti.o -L/$ORACLE_HOME/lib -lclntsh -L/$USRHOME/lib -lUsrLib


 


13장에서는 실무프로그램의 성능향상 방법에 대해서 3가지 방법을 알려주고 있다.


1) Select INTO를 자주 호출하여 DBMS Call이나 DISK I/O를 증가시키지 말고 한번의 SQL을 이용하는 방법 (반복되고 있는 SELECT INTO 문장대신 한번의 SQL문장을 사용하여 DBMS Call을 최소화시키는 방법)


 


2) 무조건 update한 후, 데이터가 없으면 insert하는 방식을 사용하지 않는 방법 (OUTER JOIN과 rowid를 이용하여 UPDATE 대상과 INSERT 대상을 구분하는 방법을 설명하고, 성능을 향상시키기 위하여 인덱스를 거치지 않고 rowid를 이용하여 바로 UPDATE하는 예를 보여주고 있다)


그런데...  Oracle 9i 이후에는 이러한 문제점을 해결하기 위하여 Merge 문장을 제공하고 있으니 이를 활용하기 바란다. Static SQL문장을 사용하면 pro*c 컴파일러가 지원하지 않으니 Dynamic SQL을 이용하면 되겠다.


https://kr.forums.oracle.com/forums/thread.jspa?threadID=408011



 


3) INSERT/UPDATE/DELETE에서도 배열을 이용하여 한번에 여러 행을 처리하는 방법(EXEC SQL FOR :호스트변수  SQL문장들;)


 


 


실무에서 필요한 핵심들이 잘 정리되어 있기 때문에 (내 자신의 쓰라린 경험이 반복되지 않기를 바라는 마음에서) 신입사원들에게 강제로 읽게 하고 있다. 도움이 되기를...

좋아요
댓글
0
작성일
2023.04.26

댓글 0

빈 데이터 이미지

댓글이 없습니다.

첫 번째 댓글을 남겨보세요.

tobewiseys님의 최신글

  1. 작성일
    2013.1.11

    좋아요
    댓글
    0
    작성일
    2013.1.11
    첨부된 사진
    20
  2. 작성일
    2012.12.24

    좋아요
    댓글
    0
    작성일
    2012.12.24
  3. 작성일
    2012.12.23

    좋아요
    댓글
    0
    작성일
    2012.12.23

사락 인기글

  1. 별명
    리뷰어클럽공식계정
    작성일
    2025.4.30
    좋아요
    댓글
    64
    작성일
    2025.4.30
    첨부된 사진
    첨부된 사진
    20
  2. 별명
    리뷰어클럽공식계정
    작성일
    2025.5.2
    좋아요
    댓글
    84
    작성일
    2025.5.2
    첨부된 사진
    첨부된 사진
    20
  3. 별명
    리뷰어클럽공식계정
    작성일
    2025.5.2
    좋아요
    댓글
    106
    작성일
    2025.5.2
    첨부된 사진
    첨부된 사진
    20
예스이십사 ㈜
사업자 정보