본문 바로가기

별걸다하는 IT/데이터베이스 Database

[Pro*C/C++] C/C++언어에서 오라클 DBMS 연동하기 (proc 접속/연결하기)

반응형

DBMS 포스팅 목차 바로가기

안녕하세요

오늘은 proc 기초에 대해 포스팅을 해보려고 해요.

proc는 C/C++소스에서 오라클 SQL문을 사용할 수 있게 해주는 프리컴파일러인데요.

자세한 내용은 proc 소개 포스팅을 참고하도록 합시다.

 

오라클 DBMS 연동하는 법

일단 소스에서 SQL문을 활용해서 뭔가 데이터를 갖고오던 넣던 비교하던 뭔가하려면

어떤 DBMS계정과 연결할건지 사전에 계정과 비번을 입력해서 로그인을 먼저 해야겠죠!!

 

오라클에 접속하려면 아래 세 가지가 필요합니다. 

1. 계정

2. 비밀번호

3. tnsname명

 

계정(id)과 비밀번호(password)로 접속하기

첫 번째는 아이디랑 비번을 하나의 문자열로 한 번에 입력하는거

두 번째는 ID랑 비번을 각각 입력하는 거 사실 뭐로 하든 상관 없습니다.

 

[CONNECT 계정/비번 구문]

/*변수선언*/
EXEC SQL BEGIN DECLARE SECTION;
varchar id_pwd[50]; 
EXEC SQL END DECLARE SECTION;

memset(&id_pwd, 0x00, sizeof(id_pwd));
strcpy((char*)id_pwd.arr, "hr/hr");
id_pwd.len = strlen((char*)id_pwd.arr);

EXEC SQL CONNECT :id_password;

참고로 SQL문에서 사용할 변수는 그냥 C언어처럼 선언하는게 아니라 DECLARE구문 사이에 선언함으로써 SQL에 쓰일거라는걸 구분해줘요.

 

저의 경우에는 로컬에서 그냥 테스트용으로 만든거라 비번까먹을까봐 계정도 hr, 비번도 hr로 맞춰놓았어요 ㅋㅋ

그래서 비번이랑 아이디가 같음!

순서는 "ID/Password"입니다. 

만약에 ID가 scott이고 비번이 tiger이면 id_password 변수 값은 "scott/tiger"이 되겠죠?

간단하게 sql plus에서 계정비번을 이용한 심플 connect 명령어 테스트를 진행해봤어요.

 

[IDENTIFIED BY 구문]

/*변수선언*/
EXEC SQL BEGIN DECLARE SECTION;
varchar id[50]; 
varchar password[50]; 
EXEC SQL END DECLARE SECTION;

memset(&id, 0x00, sizeof(id));
memset(&password, 0x00, sizeof(password));

/*계정과 비번 세팅*/
strcpy((char*)id.arr, "scott");
strcpy((char*)password.arr, "tiger");

id.len = strlen((char*)id.arr);
password.len = strlen((char*)password.arr);

EXEC SQL CONNECT :id IDENTIFIED BY :password;

identified by 구문을 이용해서 id와 비번을 각각 입력해줬습니다.

 

원격DB접속시 - 계정(id), 비번(password), tnsname

로컬(디폴트) DBMS라면 위 예시처럼 계정과 비번만으로 접속이 되는데요.

디폴트 커넥션이 아닌, 리모트 서버에 접속하려면 접속하려는 서버의 tnsname이 필요합니다.

그래야 어디에 연결할지 오라클이 알 수 있겠죠~

즉, 리모트서버 접속시 오라클이 구분할 수 있도록 tnsname 값이 추가로 필요하다!

(보통 서버명이랑 같은 경우가 많지만 항상 그런건 아니랍니다.)

클라이언트에서 원격지 오라클 서버에 접속을 시도하겠죠?

그래서 접속할 수 있는 원격지 서버에 대한 정보를 tnsnames.ora이라는 파일에 클라이언트가 관리하고 있습니다

쉽게 tnsname은 tnsnames.ora에 등록된 서버명(?)이라고 생각하면 돼요.

오라클의 경우 tnsnames.ora파일은 ${ORACLE_HOME}/network/admin 위치에 관리하고 있어요.

 

요런형식이 보통 반복되어 등록되어있는데 

가장 상단의 =앞에 있는 요 이름 있죠? 이게 tns명입니다.

 

const char* id = "hr";
const char* password = "hr";
const char* tns = "XE";
/*(소스가 너무 길어지니까 호스트변수 선언법은 생략하고 일단 위처럼 적을게요.
작성법은 여태까지 했던 것과 동일합니다!)*/

EXEC SQL CONNECT :id IDENTIFIED BY :password using :tns;

요렇게 작성하면 되겠죠?

참고로 proc구문 말고 sql plus에서는 connect id/password@tns 이 문법으로 동일하게 체크해볼 수 있습니다.

 

(실습)DB_CONNECT 함수 만들기

지금까지 한 걸 토대로 db_connect하는 함수를 작성해봅시다.

 

int db_connect(char* oracle_user, char* oracle_password, char* db_name)
{
    EXEC SQL BEGIN DECLARE SECTION;
    varchar id[64];
    varchar password[64];
    varchar tns[128];
    EXEC SQL END DECLARE SECTION;
	
    memset(&id, 0x00, sizeof(id));
    memset(&password, 0x00, sizeof(password));
    memset(&tns, 0x00, sizeof(tns));
    
    strcpy((char*)id.arr, oracle_user);
    strcpy((char*)password.arr, oracle_password);
    strcpy((char*)tns.arr, db_name);

    id.len = strlen((char*)id.arr);
    password.len = strlen((char*)password.arr);
    tns.len = strlen((char*)tns.arr);

    EXEC SQL CONNECT :id IDENTIFIED BY :password USING :tns;

    if (!SQL_SUCCESS)
    {
        return sqlca.sqlcode;
    }
    return 1;
}

참고로 EXEC SQL BEGIN DECLARE SECTION 는 호스트 변수를 선언하는 구문이예요.

함수 인자로 아이디와 비번, tns를 받아서 DB접속하는 함수로 작성해봤습니다.

 

두개 이상 커넥션 - 멀티커넥션 연결이 필요할 때

두개 이상의 DBMS에 연결이 필요할 때, 각 커넥션을 구분하기 위해 AT구문을 함께 사용할 수 있습니다.

 

스토리지가 두 개가 있는대 

01스토리지에도 employees 테이블이 있고, 02 스토리지에도 employees 테이블이 있어요

어차피 저장공간이 다르니까 테이블이름은 같아도 데이터는 다르겠죠?

 

그런데 소스상에 연봉이 1000인 직원번호를 갖고 오는 쿼리가 있다고 칩시다.

SELECT EMPLOYEE_ID FROM EMPLOYEES WHERE SALARY = 1000;

이 EMPLOYEES테이블이 01 스토리지에 있는 employees인지, 02 스토리지에 있는 employees인지 구분이 필요해요!

 

한개의 커넥션이면 어차피 겹치지 않으니까 상관 없는데 멀티커넥션이라면 구분이 필요하겠죠.

내가 접근요청한 커넥션이 어떤 DB인지 지정을 AT절로 할 수 있습니다. 

(물론 두개의 커넥션이 같은 tns를 가리킬 수도 있죠 이때도 각 커넥션을 AT으로 구분합니다) 

 

const char* id = "hr";
const char* password = "hr";
const char* tns1 = "XE";
const char* tns2 = "ORCL";

EXEC SQL DECLARE DB1 DATABASE; 
EXEC SQL DECLARE DB2 DATABASE; 

EXEC SQL CONNECT :id IDENTIFIED BY :password AT DB1 using :tns1;
EXEC SQL CONNECT :id IDENTIFIED BY :password AT DB2 using :tns2;

 

오늘은 간단하게 proc에서 DB 연결하는 법에 대해 알아봤습니다.

도움이 되었다면 공감은 큰 힘이 됩니다~~ 그럼 다음 포스팅에서 만나요~!

반응형