[오라클 서버에 연결하기]

Net8 Configuration Assistant에서

로컬 네트 서비스 이름 구성 - 추가 - 데이터베이스 /서비스 버전 지정

- 서비스이름(보통 전역데이타베이스명) - 네트워크 프로토콜 (TCP)

- 호스트이름 (오라클 서버의 IP 포트는 그냥 1521)

- 테스트 수행 - 네트서비스이름 (서비스이름과 동일해도 되고, 변경해도 된다.)

- 완료

[xx.pc파일 만들기]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//선언부
EXEC sql BEGIN DECLARE SECTION;
VARCHAR uid[20];
VARCHAR pwd[20];
VARCHAR ser[20];
long m_empno;
VARCHAR m_ename[20];
double m_sal;
VARCHAR m_hire[20];
EXEC SQL END DECLARE SECTION;

//포함부
EXEC SQL INCLUDE SQLCA;

void main()
{

dasi:
printf("Login Name?");
scanf("%s", uid.arr);
uid.len=strlen(uid.arr);
printf("Password?");
scanf("%s", pwd.arr);
pwd.len=strlen(pwd.arr);
printf("Server Alias?");
scanf("%s", ser.arr);
ser.len=strlen(ser.arr);
//접속부
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd USING :ser;
if(sqlca.sqlcode ==0)
{
printf(" Login Name: %s Success...\n",uid.arr);
}
else
{
printf(" Login Name: %s Failed...\n",uid.arr);

goto dasi;
}

//실행부
printf("EmpNo?");
scanf("%ld", &m_empno);
EXEC SQL SELECT EMPNO,ENAME,SAL,HIREDATE INTO :m_empno,:m_ename,:m_sal,:m_hire
FROM emp WHERE empno=:m_empno;
if(sqlca.sqlcode==0)
{
printf("===================================================\n");
printf(" %ld %s %lf %s\n", m_empno,m_ename.arr,m_sal,m_hire.arr);
printf("====================================================\n");
}
else
{

if(sqlca.sqlcode==1403)
printf(" Not found...\n");

else

printf(" 시스템장애...\n");
}

EXEC SQL COMMIT WORK RELEASE;
fflush(stdin);
getchar();
exit(0);
}

[선행컴파일 : Pro*C/C++]

환경설정 : CPP (또는 C로 선택)

+ : 선행컴파일할 xx.pc 선택

옵션 : cpp로 (c로 선택인 경우 ANSI C로 선택)

선행 컴파일 : xx.cpp로 만들어짐

( SQL문장을 CPP가 실행할 수 있는 코드로 변환시켜줌)

[컴파일]

1. 만들어진 xx.cpp를 Open

2. 컴파일하면 default workspace를 만들거냐고 물어본다. (예)

3. 그리고 Oracle\Ora81\precomp\lib\msvc\oraSQL8.LIB추가한다.

4. 그러면 실행파일이 만들어진다.

[sqlca]

오라클의 SQLCA구조체는 SQL문 실행 후 그 결과값을 위해 만들어진 구조체이다.

· sqlca.sqlcode:4바이트 2진 정수이고, SQL 문의 실행결과를 나타낸다.

0 실행이 정상 종료

1403 NOT FOUND

음수 프로그램 또는 시스템 장애

[주의]

uid.len=strlen(uid.arr);

strlen 함수를 사용하려면 unsigned char는 않되므로 char로 변경시켜주면

에러 않난다.

struct { unsigned short len; unsigned char arr[20]; } uid;

struct { unsigned short len;char arr[20]; } uid;

· 호스트 변수

SQL 문 및 프로그램 문의 양쪽으로부터 참조되는 모든 값에 대해서 선언해야 한다. 호스트 변수의 데이터타입은 선언절에서 호스트 언어를 사용해서 선언해야 하며, 이 때 이 데이터타입은 테이블을 정의할 때에 사용되는 ORACLE 데이터타입과 일치할 필요는 없다.

EXEC sql BEGIN DECLARE SECTION;
VARCHAR uid[20];
VARCHAR pwd[20];
VARCHAR ser[20];
long m_empno;
VARCHAR m_ename[20];
double m_sal;
VARCHAR m_hire[20];
EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT EMPNO,ENAME,SAL,HIREDATE INTO :m_empno,:m_ename,:m_sal,:m_hire

FROM emp WHERE empno=:m_empno;

printf("Login Name?");
scanf("%s", uid.arr);
uid.len=strlen(uid.arr);

printf("EmpNo?");
scanf("%ld", &m_empno);

표지 변수

emp_sal_indicator =-1;

EXEC SQL INSERT INTO emp(empno,sal)

VALUES(:emp_number,:emp_salary :emp_sal_indicator);

↖ 표지변수

EXEC SQL SELECT sal INTO :emp_salary :emp_salary_indicator FROM emp

WHERE empno=:emp_no;

if(emp_salary_indicator== -1) // -1 은 NULL을 의미

printf("Employee No %d Salary 0.00\n",emp_no);

else

printf("Employee No %d Salary %f\n", emp_no,emp_salary);

· 호스트 변수로서의 배열

선언 예)

EXEC SQL BEGIN DECLARE SECTION;

int emp_number[10];

float emp_salary[10];

char emp_name[10][20];

EXEC SQL END DECLARE SECTION;

주의사항)

.호스트 배열은 배열 포인터를 선언할 수 없다. (int *p[10];)

. 문자형 변수 이외에는 일차원 배열만 선언할 수 있다.

EXEC SQL SELECT sabun,saname,sajob,sapay,sahire

INTO :sawon_sabun,

sawon_saname,:sawon_sajob,:sawon_sapay,:sawon_sahire

FROM sawon where sajob=:job;

printf("count=%d \n",sqlca.sqlerrd[2]); /* 처리한 행수 */

for(a=0;a<sqlca.sqlerrd[2];a++)

{

printf("%2d %-10s %-10s %8.2f %-16s\n",

sawon_sabun[a],sawon_saname[a], sawon_sajob[a]

,sawon_sapay[a],sawon_sahire[a]);

}

· sqlca.sqlerrd: 4바이트 2진 정수 배열 ORACLE RDBMS의 내부상황

을 파악하기 위해 사용. sqlca.sqlerrd[2]는 INSERT 나

UPDATE 처럼 DML 처리에 대해서 몇 개의 행이 처리 됐는

지를 나타냄

Connected to ORACLE user : CHANG
Job is?부장
count=3
2 한국남 부장 3000.00 88/11/01
13 무궁화 부장 3000.00 96/11/01
17 이성계 부장 2803.00 84/05/01
처리상태 SQLCode=1403 메세지: ORA-01403: 데이터가 없습니다

(단점) 배열갯수가 맞지 않으면 에러남.

[커서]

쿼리가 복수의 행을 리턴하는 경우 그 리턴된 행에 대한 결과를 보관하고 있는 작업 영역을 말한다.

1.커서의 사용순서

DECLARE : 커서를 선언한다.

OPEN : 커서를 활성화 시킨다.

FETCH : 커서에서 데이터 행을 가져온다.

CLOSE : 커서 사용을 종료한다.

(sql서버에서는 반드시 deallocate해야한다.)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***************************************************************
This is is a sample Pro*C program which uses the FOR option
by inserting records into the EMP table.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20];
VARCHAR pwd[20];
VARCHAR ser[20];
int sawon_sabun;
float sawon_sapay;
char sawon_saname[10];
char sawon_sajob[10];
char sawon_sahire[20];
char sawon_sasex[10];
char job[10];
EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE SQLCA;

void main(void)
{
/* log into ORACLE */
strcpy(uid.arr, "CHANG"); /* copy the user name */
uid.len = strlen(uid.arr);
strcpy(pwd.arr, "CHANG"); /* copy the password */
pwd.len = strlen(pwd.arr);
strcpy(ser.arr, "ths");
ser.len = strlen(ser.arr);

//****

EXEC SQL WHENEVERSQLERROR DO return;

//****

EXEC SQL CONNECT :uid IDENTIFIED BY :pwd USING :ser;

printf("Connected to ORACLE user : %s\n", uid.arr);
printf(" JOB is?");
scanf("%s", job);
EXEC SQL DECLARE sawcur CURSOR FOR SELECT sabun,saname,sajob,sapay,sahire,sasex FROM sawon WHERE sajob=:job;
// EXEC SQL WHENEVERSQLERROR DO return;

EXEC SQL OPEN sawcur;


EXEC SQL WHENEVER NOT FOUND DO break;
while(1)
{
EXEC SQL FETCH sawcur INTO
:sawon_sabun,:sawon_saname,:sawon_sajob,:sawon_sapay,:sawon_sahire,:sawon_sasex;
printf(" %3d %-10s %-10s %10.2f %-15s %10s\n",
sawon_sabun,sawon_saname,sawon_sajob, sawon_sapay ,sawon_sahire,sawon_sasex);
}
EXEC SQL CLOSE sawcur;
EXEC SQL COMMIT WORK RELEASE;
fflush(stdin);
getchar();
exit(0);
}

===

u SQLCA의 사용

방법1) EXEC SQL INCLUDE SQLCA;

방법2) EXEC SQL INCLUDE sqlca.h;

Pro*C/C++소스 파일에 삽입하면 된다.

방법3) #include <sqlca.h>

Pro*C/C++소스 파일이나 생성된 Cpp파일에 삽입하면 된다.

그리고 sqlca.h화일을 VC++의 include Directory에 복사하거나

찾아갈 Directory를 설정해야 한다.

에러가 검출될 때 어떤 처리를 취해야 할 지를 지정해 주는 문장이다.

EXEC SQL WHENEVER [SQLERROR | SQLWARNING | NOT FOUND]

[STOP | CONTINUE | GOTO stmt-label];

· SQLERROR : sqlca.sqlcode가 -1인 경우에 설정

· SQLWARNING :sqlca.sqlwarn[0]에 "W"가 설정되어 있는 경우에 설정

· NOT FOUND : sqlca.sqlcode가 1403인 경우에 설정

· STOP : 프로그램을 종료시키고 논리적인 작업단위는 ROLLBACK 된다.

· CONTINUE : sqlca의 상태를 무시하고 프로그램을 계속 진행한다.

· GOTO :지정한 라벨이 붙은 문으로 제어를 옮긴다.

· DO :DO문장 다음에 지정된 함수를 수행한 다음 수행했던 SQL문 다음

문장을 계속하여 실행한다.

ã WHENEVER문장의 범위

WHENEVER문장은 하나의 선언문이기 때문에 이문장의 유효는 물리적인 위치에 의해 정해진다. 일단 WHENEVER문장이 선언되면 그 아래에 위치하는 모든 SQL문들은 WHENEVER문장의 영향을 받는다. 만약 기존의 WHENEVER문장 아래에 새로운 WHENEVER문장이 선언되면 아래 선언된 문장 다음에 나오는 SQL문장들은 새로 선언된 WHENEVER문장의 영향을 받게 된다.

[Pro*C/C++에서 PL/SQL의 블록 사용]

선행컴파일시 옵션 sql검사를 semantics로 해야함

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

/****************************************************************/

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR uid[20];

VARCHAR pwd[20];

VARCHAR ser[20];

int sawon_sabun;

float sawon_sapay;

char sawon_saname[10];

char sawon_sajob[10];

char sawon_sahire[20];

char sawon_sasex[10];

char name[10];

EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE SQLCA;

void main(void)

{

/* log into ORACLE */

strcpy(uid.arr, "CHANG"); /* copy the user name */

uid.len = strlen(uid.arr);

strcpy(pwd.arr, "CHANG"); /* copy the password */

pwd.len = strlen(pwd.arr);

strcpy(ser.arr, "CHANGS");

ser.len = strlen(ser.arr);

EXEC SQL CONNECT :uid IDENTIFIED BY :pwd USING :ser;

printf("Connected to ORACLE user : %s\n", uid.arr);

printf(" Name is?");

scanf("%s", name);

/* SQL문을 PL/SQL의 블럭으로 처리하는 경우 */

EXEC SQL EXECUTE

DECLARE

n NUMBER(3);

BEGIN

n:=0;

if n>0 then

SELECT sabun,saname,sajob,sapay,sahire,sasex INTO

:sawon_sabun,:sawon_saname,:sawon_sajob,:sawon_sapay,:sawon_sahire,:sawon_sasex

FROM sawon WHERE saname=:name;

else

SELECT sabun,saname,sajob,sapay,sahire,sasex INTO

:sawon_sabun,:sawon_saname,:sawon_sajob,:sawon_sapay,:sawon_sahire,:sawon_sasex

FROM sawon WHERE saname='홍길동';

end if;

END;

END-EXEC;

/* 블럭끝*/

printf(" %3d %-10s %-10s %10.2f %-15s %10s",

sawon_sabun,sawon_saname,sawon_sajob,sawon_sapay,sawon_sahire,sawon_sasex);

EXEC SQL COMMIT WORK RELEASE;

fflush(stdin);

getchar();

exit(0);

}

[동적]

실습예문) EXECUTE IMMEDIATE 의 사용

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

/****************************************************************/

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR uid[20];

VARCHAR pwd[20];

VARCHAR ser[20];

char select[132];

EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE SQLCA;

void main(void)

{

char where[80];

int scode;

/* log into ORACLE */

strcpy(uid.arr, "CHANG"); /* copy the user name */

uid.len = strlen(uid.arr);

strcpy(pwd.arr, "CHANG"); /* copy the password */

pwd.len = strlen(pwd.arr);

strcpy(ser.arr, "CHANGS");

ser.len = strlen(ser.arr);

EXEC SQL WHENEVER SQLERROR STOP;

EXEC SQL CONNECT :uid IDENTIFIED BY :pwd USING :ser;

printf("Connected to ORACLE user : %s\n", uid.arr);

strcpy(select, "UPDATE sawon SET sapay = 2000 WHERE ");

printf("Please enter where clause for the following : \n");

printf("%s", select);

scode = scanf("%s", where);

fflush(stdin);

if(scode == EOF || scode == 0)

{

printf("Invalid entry. \n");

exit(1);

}

strcat(select, where);

printf("%s\n", select);

EXEC SQL EXECUTE IMMEDIATE :select;

printf("%d records updated. \n", sqlca.sqlerrd[2]);

getchar();

EXEC SQL COMMIT WORK RELEASE;

exit(0);

}

원본 http://blog.naver.com/alice8790/60001523069

, .