C언어03_Pro*C의 이해
이 글은
https://kikook.tistory.com/499
글을 공부하며 정리한 글 입니다.
1. Pro*C란
- SQL문을 포함한 C프로그램에서 DB에 접근 및 조작할 수 있는 프로그램으로 변환하기 위한 언어.
- 프리 컴파일러이다.
- 입력파일 내에 있는 EXEC SQL문을 이용하여 출력파일을 작성하고, 이 파일을 컴파일하고 링크해서 실행모듈 작성한다.
- C 프로그램을 작성한다.
- 프로그램을 컴파일하여 오브젝트 파일을 작성한다.
- 오브젝트 파일을 링크해서 실행 가능한 파일을 작성한다.
- 프로그램을 실행한다.
-
C프로그램 어디에든 배치해도 좋다.
- EXEC SQL
- SQL문을 호스트언어에 포함
- 발생할 수 있는 언어상의 장애 최소화.
- 모든 SQL문에는 EXEC SQL의 접두사를 붙인다.
- 실행문 선언문에 관계없이 붙는 접두사이다.
- EXEC ORACLE
- SQL과는 호환성이 없다.
- ORACLE 프리컴파일러 특유의 것이다.
실행문
- DB에 대한 콜을 생성하는 SQL문
- DML, DDL, DCL등이 있다.
- 실행 후 SQLCA에는 일련의 리턴코드가 저장된다.
- CONNECT, COMMIT, ROLLBACK 문의 다음에 첫 번째로 나타나는 SQL실행문 부터 논리적인 작업 단위가 새롭게 시작됨
선언문
- 코드생성 X
- 논리적 작업단위에 영향 없음.
2. Pro*C의 구성
어플리케이션 프롤로그
- 변수를 정의하고 Pro*C 프로그램을 위한 일반적 준비 수행
- 선언절, INCLUDE SQLCA문, CONNECT문
01) 선언절
- C프로그램 내에서 사용된 모든 호스트 변수 선언.
호스트 변수?
- 호스트 변수의 데이터 타입은 선언절에서 호스트 언어를 사용하여 선언한다.
- 데이터 타입은 테이블 정의시 사용되는 컬럼데이터 타입과 일치할 필요는 없다.
- 선언절에서 명시적으로 선언
- 영어 대/소문자 포맷 사용
- SQL문 앞에서는 (:)콜론 붙이기
- C문에서는 앞에 콜론을 붙이지 않음
- SQL 예약어를 사용하지않는다.
- 상수를 사용할 수 있는 곳에서만 사용한다.
- 표지 변수가 붙어 있어도 상관 없다.
EXEC SQL BEGIN DECLARE SECTION; -- 시작
int pempno; /* 사번 */
char pname[11]; /* 성명 */
int pdeptno; /* 부서 */
EXEC SQL END DECLARE SECTION; -- 종료
EXEC SQL SELECT deptno, ename
INTO :pdeptno, :pname
FROM emp
WHERE empno = :pempno;
표지변수
?- 선언절에서 선언된 호스트변수에 1:1로 대응되는 임의 선택 변수
- NULL 값을 취급하는데 유효하다.
- 영어 대/소문자의 포맷 사용
- 2byte 정수로 선언
- SQL문 앞에서는 (:)콜론 붙이기
- C문에서는 앞에 콜론을 붙이지 않음
- SQL예약어를 사용하지 않는다.
- SQL문 내에서는 대응하는 입력 호스트 변수를 앞에 붙여 사용
- 호스트 변수로서의 포인터 선언
- 포인터 변수는 C에서 통상적으로 행하는 방법으로 선언하여 선언절 내에서 사용할 수 있다.
EXEC SQL BEGIN DECLARE SECTION; -- 시작
int i, j * intptr;
char * cp;
EXEC SQL END DECLARE SECTION; -- 종료
EXEC SQL SELECT intfield
INTO :intptr
FROM DUAL;
- VARCHAR의사타입의 선언
- Pro*C에서는 VARCHAR타입을 사용할 수 있다.
- 가변길이의 문자열을 처리할 수 있다.
- 선언절에서 참조할 뿐이며, 확장된 c타입 또는 사전에 선언된 구조이다.
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR jobDesc[40];
EXEC SQL END DECLARE SECTION;
//아래의 구조체로 확장할 수 있다.
struct{
unsigned short int len;
unsigned char arr[40];
}jobDesc
02) SQL통신영역의 선언
- SQL 통신영역(SQLCA)에 대한 참조를 포함시켜 각 Pro*C 프로그램에서 발생하는 상황처리를 가능하게 함.
EXEC SQL INCLUDE SQLCA;
- 프리 컴파일시 SQLCA파일의 위치를 알아야 한다.
- “INCLUDE = “ 커맨드 라인 옵션 사용
- Pro*C가 파일을 SYS$ORACLE:SQLCA 처럼 공동의 OS영역에서 발견할 수 있도록 파일의 정식 명칭을 지정한다.
- PCC를 호출할 디렉토리 또는 디스크에 SQLCA를 카피한다.
- SQLCA가 포함하고 있는 정보
- 경고 플래그와 처리상황에 관한 정보
- 에러코드
- 진단정보
03) ORACA(SQLCA에 대한 확장)
- EXEC SQL INCLUDE를 사용하여 ORACA의 정의 참조
- 커냉드라인 옵션 또는 EXEC ORACLE OPTION에서 ORACA = YES 옵션 선택
- 정보
- orastxt : SQL문의 텍스트 ( oracle이 해석한 sql문의 내용 조사 가능. COMMIT, FETCH, CONNECT제외 )
- orasfnm : 에러가 있는 파일 이름
- orastxtf : SQL문 보존 플래그 ( 어느조건으로 보존할 지 선택 )
- 디폴트값은 SQL문을 보존하지 않음
- SQLERROR가 있는 SQL만을 보존한다.
- SQLERROR및 SQLWARN이 있는 SQL보존
- SQL문 전부 보존
- DEBUG처리 사용 허가 플래그
- 0또는 1을 설정할 수 있으며, 1을 설정한 경우 모든 DEBUG처리를 사용할 수 있다.
- orahchf : 커서 캐쉬검사
04) ORACLE 접속
EXEC SQL CONNECT :oracleid IDENTIFIED BY :oraclepwd;
- CONNECT문은 프로그램 내에서 최초의 SQL문
- 선언문과 C코드만을 CONNECT문 앞에 놓을 수 있다.
- 비밀번호를 따로 지정할 경우 유저명과 패스워드 양쪽에 대해 호스트 변수를 사용해야 한다.(고정 또는 가변길이 문자열중 하나로 선언)
- CONNECT문을 수행하기 전, 양쪽 호스트 변수를 초기화 시켜야 한다.
- CONNECT는 프로그램의 최초 실행문이지만, 논리적 작업단위의 시작이다.
어플리케이션 본체
- 데이터를 조작하기 위한 INSERT, UPDATE 등의 SQL문을 포함
- 데이터 정의문이 포함되며, 테이블, 뷰, 인덱스 등의 데이터 구조를 작성하거나 정의하기 위해 사용됨
- 처리 시 필요로 하는 코드의 전후에 어떠한 C코드를 지정해도 상관없다.
- DECLARE STATEMENT 문
- DECLARE DATABASE 문
- EXEC ORACLE 옵션
01) 행 삽입
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20]
VARCHAR pwd[20];
int empno;
VARCHAR ename[15];
VARCHAR job[10];
float sal;
int deptno;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;
void main(void)
{
int sret; // scanf로 리턴받는 코드
// Oracle 로그
strcpy(uid.arr, "SCOTT");
uid.len = strlen(uid.arr);
strcpy(pwd.arr , "TIGER");
pwd.len = strlen(pwd.arr);
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
printf("Connected to ORACLE user : %s\n\n\n", uid.arr);
while(1)
{
printf("Enter employee number(or 0 to end) : ");
sret = scanf("%d", &empno);
if(sret == EOF || sret == 0 || empno == 0 )
break;
printf("Enter employee name : ");
scanf("%s", ename.arr);
ename.len = strlen(ename.arr);
printf("Enter employee's job : ");
scanf("%s", job.arr);
job.len = strlen(job.arr);
printf("Enter employee salary : ");
scanf("%f", &sal);
printf("Enter employee deptno : ");
scanf("%d", &deptno);
EXEC SQL INSERT INTO EMP
( empno
, ename
, job
, sal
, deptno )
VALUES
( :empno
, :ename
, :job
, :sal
, :deptno );
EXEC SQL COMMIT WORK;
printf("Employee %s added. \n\n", ename.arr);
}
EXEC SQL COMMIT WORK RELEASE;
exit(0);
}