'Language'에 해당되는 글 463건

  1. 2015.05.20 [번역] Embadded SQL - 02
  2. 2015.05.20 [번역] Embedded SQL - 01
  3. 2015.05.20 [번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 04
  4. 2015.05.20 [번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 03
  5. 2015.05.20 [번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 02
  6. 2015.05.20 [번역] 데이터유형과 호스트변수( Datatypes and Host Variables ) - 01
  7. 2015.05.20 [번역] pro*c 데이터베이스 개념(Database Concepts) - 03
  8. 2015.05.20 [번역] pro*c 데이터베이스 개념(Database Concepts) - 02
  9. 2015.05.20 [번역] pro*c 데이터베이스 개념(Database Concepts) - 01
  10. 2015.05.20 [소스] PRO*C의 기본구조와 Indicator의 사용예

[번역] Embadded SQL - 02

Language/Pro*C 2015. 5. 20. 17:10
목 차
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ 기본 SQL 문장 ( The Basic SQL Statements )
▣ The DML Returning Clause
▣ 커서 ( Cursors )
▣ 최적화 힌트 ( Optimizer Hints )
▣ CURRENT OF절 ( The CURRENT OF Clause )
▣ 커서문 ( The Cursor Statements )
▣ Non-Scrollable 커서를 사용하는 예제
▣ Scrollable 커서를 사용하는 예제
3) 기본 SQL 문장 (The Basic SQL Statements )
이장에서는 데이타를 조작하고 쿼리하는 문장에 포커스를 두고 설명한다.
데이터를 조작하는 문장인 INSERT,UPDATE,DELETE문을 실행할때, 문장이 실행을
성공했는지 실패했는지 관심을 가질것이다. 이것을 알기위해서 단순히 SQLCA를
체크하면 된다. 체크하는 방법에는 두가지가 있다.

- WHERNEVER문을 체크하는 방법
- SQLCA 변수를 체크하는 방법

아래의 SQL문장들은 오라클의 데이터를 조작하고 쿼리 할 수 있도록 하는데 사용
된다.






아래의 SQL문장들은 명시적인 커서를 선언하고 조작하는데 사용된다.






3-1) SELECT문
SELECT문의 사용예는 아래와 같다.

EXEC SQL SELECT ename, job, sal + 2000
INTO :emp_name, :job_title, :salary
FROM emp
WHERE empno = :emp_number;

SELECT문에서 사용할 수 있는 SQL절은 아래와 같은것들이 있다.

☞ INTO
☞ FROM
☞ WHERE
☞ CONNECT BY
☞ START WITH
☞ GROUP BY
☞ HAVING
☞ ORDER BY
☞ FOR UPDATE OF

3-2) INSERT문
INSERT문의 사용예는 아래와같으며, 테이블이나 VIEW에 행을 추가할때 사용한다.

EXEC SQL INSERT INTO emp (empno, ename, sal, deptno)
VALUES (:emp_number, :emp_name, :salary, :dept_number);

서브쿼리사용
서브쿼리라고하면 SELECT문이 반복적으로 나오는것을 말하며, 이것은 다음과 같은
경우에 사용된다.
☞ SELECT,UPDATE,DELETE문의 WHERE,HAVING,START WITH절에서 비교를 위한 값을
제공한다.
☞ CREATE TABEL, INSERT문에서 삽입될 행을 설정한다.
☞ UPDATE문의 SET의 값을 정의 한다.

아래의 예제는 다른테이블로 행를 복사해서 삽입하는 예제이다.

EXEC SQL INSERT INTO emp2 (empno, ename, sal, deptno)
SELECT empno, ename, sal, deptno FROM emp
WHERE job= :job_title ;

3-3) UPDATE문
UPDATE문은 테이블에서 특정컬럼의 값을 변경할때 사용하며, 사용예는 아래와같다.

EXEC SQL UPDATE emp
SET sal = :salary, comm = :commission
WHERE empno = :emp_number;

아래의 예제는 UPDATE문을 해서 서브쿼리를 사용한 예이다.

EXEC SQL UPDATE emp
SET sal = (SELECT AVG(sal)*1.1 FROM emp WHERE deptno = 20)
WHERE empno = :emp_number;

3-4) DELETE 문
행을 삭제할 경우 사용하는 문장이다. 예제는 아래와 같다.

EXEC SQL DELETE FROM emp
WHERE deptno = :dept_number ;

4) DML RETURNING절
INSERT, UPDATE, DELETE문의 선택적인 DML RETURNING절을 가질 수 있다.
아래는 DML RETURNING 절의 예제이다.

{RETURNING | RETURN} {expr [,expr]}
INTO {:hv [[INDICATOR]:iv] [, :hv [[INDICATOR]:iv]]}

위의 표현식에서 expr은 컬럼값을 표현식이며, hv는 호스트변수,iv는 호스트 지시자
변수이다. 표현식의 숫자는 호스트 변수의 수와 같아야만 한다.
이절은 INSERT,UPDATE후에 행수를 취득할 필요가 없으며, DELETE전에 프로그램에서
레코드를 할 필요가 없다. RETRURNING 절은 불필요한 네트웍 부하를 줄이고, 서버
메모리를 줄일수 있다.
Oracle Dynamic SQL Method 4는 DML RETURNING 절을 지원하지 않는다.

5) 커서(CURSOR)
아래의 문장들은 커서를 조작하고 선언하는데 사용된다.

☞ DECLARE CURSOR
☞ OPEN
☞ FETCH
☞ CLOSE

우선, DECLARE CURSOR문을 이용해서 커서이름을 선언하는 사용한다.
OPEN문을 이용해서 쿼리를 실행하고 쿼리에 맞는 행을 확인한다. FETCH문은 현재행의
값을 취득하는데 사용한다. 모든행의 값을 취득할때까지 반복적으로 FETCH문을
실행할 수 있다.

데이터를 다 취득한후 CLOSE문을 사용해서 커서를 끝낸다.
아래에 설명 부분은 이들 커서제어문을 어떻게 사용하는지 보여주고 있다.

5-1) DECLARE CURSOR문
DECLARE CURSOR문의 사용예는 아래와 같다.

EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT ename, empno, sal
FROM emp
WHERE deptno = :dept_number;

커서는 전처리기에서 사용되는 인식자이며, 호스트나 프로그램 변수가 아니다.
커서명은 하이픈으로 연결될수 없고, 길이를 가지고 있으면, 31문자 정도로 하는것이
좋으며, ANSI와 호환을 위해서는 18문자 이상되지 말아야한다.

CURSOR와 연관된 SELECT문은 INTO절을 포함할 수 없으며, FETCH절에 사용한다.
DECLARE CURSOR 문은 커서를 참조하는 모든 SQL문장보다 먼저 선언되어야한다.
아래의 예제는 OPEN문이 잘못 사용된 예제이다.

...
EXEC SQL OPEN emp_cursor;
EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT ename, empno, sal
FROM emp
WHERE ename = :emp_name;

커서 제어문들은 같은 전처리 단위내에서 발생해야한다. 예를들어, A 파일내에서
커서를 선언하고 B파일에서 OPEN 할 수는 없다. 호스트 프로그램에서 DELCARE문은
많이 사용될수 있지만 모든 DECLARE문은 유일해야한다. 즉, 하나의 전처리단위에서
같은 이름으로 커서를 사용할 수 없다.
5-2) OPEN문
OPEN문은 쿼리를 실행하고 ACTIVE SET을 확인하기위해서 사용한다.
OPEN시에 SQLCA에서 SQLERRD의 세번째요소인 행진행수를 0으로 맞춘다.
이시점에 프로그램에서 볼수있는 행은 아무것도 없다. 그것을 FETCH문에 의해서
다루어진다.
OPEN시 커서를 ACTIVE SET의 맨처음 행에 위치시킨다.
커서가 한번 오픈되면, 쿼리의 입력호스트 변수는 다시 커서가 열리기전까지 재 검사를
하지 않는다. 그래서 ACTIVE SET은 변경되지 않는다. 만약 ACTIVE SET을 변경하기고자
한다면 커서를 다시 열어야만 한다.

5-3) FETCH문
FETCH문은 ACTIVE SET으로부터 행의 값을 추출하여 결과에 포함된 출력호스트변수를
지정하는데 사용한다. 커서와 연관된 SELECT문은 INTO절이 삽입될수 없다는것을
기억하라.
아래의 예제는 3개의 호스트변수에 값을 입력하는 예제이다.

EXEC SQL FETCH emp_cursor
INTO :emp_name, :emp_number, :salary;

각각 다른 호스트변수에 같은 커서에서 취득한 데이터를 설정하는 예제를 아래에서
보여주고 있다.

EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT ename, sal FROM emp WHERE deptno = 20;
...

EXEC SQL OPEN emp_cursor;
EXEC SQL WHENEVER NOT FOUND GOTO ...
for (;;)
{
EXEC SQL FETCH emp_cursor INTO :emp_name1, :salary1;
EXEC SQL FETCH emp_cursor INTO :emp_name2, :salary2;
EXEC SQL FETCH emp_cursor INTO :emp_name3, :salary3;
...

}

ACTIVE SET이 비었거나 아무 데이터도 포함하고 있지 않다면, FETCH는 "no data found"
에러코드를 SQLCA의 sqlcode에 리턴하던지 혹은 SQLSTATE상태 변수 또는 SQLCODE에 리턴
할 것이다.

아래의 상태에서 FETCH하는 경우 에러가 발생한다.

☞ 커서를 OPEN하기 전 상태
☞ "no data found"후에 FETCH한 상태
☞ 커서를 닫은후 FETCH한 상태

5-4) CLOSE문
아래의 예처럼 커서를 닫는다. 커서를 닫는다고 하는것이 오픈되었던 커서에 의해서
서버에 잡혀져 있던 리소스를 해제하는 것이다.

EXEC SQL CLOSE emp_cursor;



출처 - http://younbok.egloos.com/9342724

:

[번역] Embedded SQL - 01

Language/Pro*C 2015. 5. 20. 17:09

목 차
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ 기본 SQL 문장 ( The Basic SQL Statements )
▣ The DML Returning Clause
▣ 커서 ( Cursors )
▣ 최적화 힌트 ( Optimizer Hints )
▣ CURRENT OF절 ( The CURRENT OF Clause )
▣ 커서문 ( The Cursor Statements )
▣ Non-Scrollable 커서를 사용하는 예제
▣ Scrollable 커서를 사용하는 예제

1) 호스트 변수 ( Host Variables )
오라클은 호스트변수를 프로그램에 데이터와 상태정보를 넘기는데 사용하고,
프로그램은 오라클에 데이터를 넘기는데 사용한다.

1-1) 입출력 호스트 변수
SELECT나 FETCH문의 INTO 절의 호스트 변수를 출력 호스트변수라고 한다.
그이외의 SQL문의 호스트 변수는 오라클에 값을 입력하는데 사용하므로 입력 호스트
변수라고 한다.
Attention : ORDER BY 절에 호스트 변수를 사용할 수 있다. 하지만 이것은 상수나
문자로서 간주되며 아래의 예처럼 쓰 일 수 있다.
EXEC SQL SELECT ename, empno INTO :name,:number
FROM emp ORDER BY :ord;
위의 예처럼 호스트 변수를 포함하고 있지만(:ord)여기서는 이변수를
상수로서 간주하며 설정된 값과는 관계없이 Ordering은 행해지지 않는다.

SQL키워드나 데이터베이스 오브젝트이름를 지원하기위한 입력호스트 변수로는 사용할
수 없다. 그래서 데이터선언문(DDL - ALTER,CREATE,DROP등등)에서 입력호스트변수를
사용할 수 없다. 아래의 예제에서는 DROP TABLE문이 유효하지 않은 예제를 보여주고
있다. :

char table_name[30];

printf("Table name? ");

gets(table_name);

EXEC SQL DROP TABLE :table_name; -- 호스트 변수는 유효하지 않음

데이터베이스 오브젝트 이름을 실행시에 변경할 필요가 있다면 dynamic SQL를
사용하면된다. 이에 대해서는 앞으로 다룰 "Oracle Dynamic SQL"장에서 살펴
보기로 한다.

오라클이 입력호스트변수가 있는 SQL문을 실행하기전에, 프로그램은 그들에게
값을 할당해야만 한다. 아래의 예를 보자 :

int emp_number;

char temp[20];

VARCHAR emp_name[20];
/* 입력호스트 변수를 위한 값을 얻는다 */
printf("Employee number? ");

gets(temp);

emp_number = atoi(temp);

printf("Employee name? ");

gets(emp_name.arr);

emp_name.len = strlen(emp_name.arr);

EXEC SQL INSERT INTO EMP (EMPNO, ENAME)
VALUES (:emp_number, :emp_name);

2) 지시자 변수 ( Indicator Variables )
호스트 변수에대한 결과코드를 지시자변수가 가지게 된다. 그래서 지시자 변수는
호스트 변수를 감시할수 있는것이다.
지시자변수는 입력 호스트 변수에 NULL을 할당하기위해서 사용되며, 출력호스트
변수에 잘려진 값이나 NULL을 감지하기위해서 INTO절에 사용한다.

◐ 입력시 프로그램이 지시자변수에 할당할수 있는 값의 의미






◐ 출력시 오라클이 지시자변수에 할당할수 있는 값의 의미


다음을 꼭 기억하도록 하자.
지시자 변수는 2바이트 정수로 정의 되어야만하고, SQL문장에서 콜른(:)을 앞에
붙이며 호스트변수 바로뒤에 와야한다.

2-1) NULL삽입
INSERT문에서 각컬럼이 null이되기를 원한때, 아래의 예처럼 -1로 지시자 변수를
설정한다.

set ind_comm = -1;
EXEC SQL INSERT INTO emp (empno, comm)
VALUES (:emp_number, :commission:ind_comm);

아래와같이 NULL로 하드코딩할수도 있다.

EXEC SQL INSERT INTO emp (empno, comm)
VALUES (:emp_number, NULL);

통상적으로, 아래의 예처럼 INSERT문에 NULL을 입력할 수 있다.

printf("Enter employee number or 0 if not available: ");

scanf("%d", &emp_number);

if (emp_number == 0)
ind_empnum = -1;
else
ind_empnum = 0;

EXEC SQL INSERT INTO emp (empno, sal)
VALUES (:emp_number:ind_empnum, :salary);

2-2) NULL 반환
아래의 예처럼 NULL반환값을 조작하는데 사용할 수 있다.

EXEC SQL SELECT ename, sal, comm
INTO :emp_name, :salary, :commission:ind_comm
FROM emp
WHERE empno = :emp_number;

if (ind_comm == -1)
pay = salary; /* commission is NULL; ignore it */
else
pay = salary + commission;

2-3) Test for NULLs
NULL값을 검사하기위해서 WHERE절에 지시자 변수를 아래의 예처럼 사용할 수 있다.

EXEC SQL SELECT ename, sal
INTO :emp_name, :salary
FROM emp
WHERE :commission INDICATOR :ind_comm IS NULL ...

그러나, 다른값이나 각각의 값의 NULL을 비교하기위해서 관계연산자를 사용할 수는
없다. 예를들어, 아래의 SELECT문은 COMM컬럼이 한개이상의 NULL을 포함하고 있으면
쿼리를 실패할것이다.

EXEC SQL SELECT ename, sal
INTO :emp_name, :salary
FROM emp
WHERE comm = :commission;

아래의 예제는 동일한 값을 어떻게 비교하는지 보여주고 있다.

EXEC SQL SELECT ename, sal
INTO :emp_name, :salary
FROM emp
WHERE (comm = :commission) OR ((comm IS NULL) AND
(:commission INDICATOR :ind_comm IS NULL));


출처 - http://younbok.egloos.com/9342725

:

[번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 04

Language/Pro*C 2015. 5. 20. 17:08

목 차

▣ 오라클 데이터 유형 (Oracle Datatypes)
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ VARCHAR 변수 ( VARCHAR Variables )
▣ 커서 변수 ( Cursor Variables )
▣ CONTEXT 변수 ( CONTEXT Variables )
▣ Universal ROWIDs
▣ 호스트 구조체 ( Host Structures )
▣ 포인터 변수 ( Pointer Variables )
▣ Globalization Support
▣ NCHAR 변수 ( NCHAR Variables )
6) 포인터 변수 ( Pointer Variables )
C언어는 다른 변수를 지적하는 포인터를 제공한다. 포인터는 그것의 값이 아닌, 변수
의 주소(저장위치)를 가지고 있다.
6-1) 포인터 변수 선언
아래의 예제는 일반 C언어에서처럼 호스트 변수를 포인터를 선언한것이다.
int *int_ptr;
char *char_ptr;
6-2) 포인터 변수 참조
아래의 예제는, 포인터를 쿼리에서 사용한 예이다.
EXEC SQL SELECT intcol INTO :int_ptr FROM ...
문자열 포인터를 제외하고 참조값을 크기는 주여진 형의 크기에 따라 결정된다.
문자열은 NULL terminater가 들어가서 실행시 strlen()함수에 의해서 크기가
결정된다. 자세한 사항은 "Globalization Support" 장에서 보도록 하자.
포인터는 구조체의 맴버를 참조하기위해서 사용할 수 있다.
아래의 예제처럼, 구조체 변수를 선언하여 사용할 수 있으며 구조체 맴버의 데이터형과
포인터변수의 데이터형은 같아야만 한다. 대부분의 컴파일러는 맞지 않을경우
경고를 표시한다.

struct
{
int i;
char c;
} structvar;

int *i_ptr;
char *c_ptr;
...

main()
{
i_ptr = &structvar.i;
c_ptr = &structvar.c;
/* Use i_ptr and c_ptr in SQL statements. */
...

6-3) 구조체 포인터
호스트 변수로서 구조체에대한 포인터를 사용할 수 있다. 아래의 예제에서

◎ 구조체 선언
◎ 구조체에대한 포인터 선언
◎ 구조체을 위한 메모리 할당
◎ 쿼리에서 호스트 변수로서 구조체를 사용
◎ 결과를 출력하기위해서 구조체 요소를 참조 한다.
struct EMP_REC
{
int emp_number;
float salary;
};

char *name = "HINAULT";
...

struct EMP_REC *sal_rec;
sal_rec = (struct EMP_REC *) malloc(sizeof (struct EMP_REC));

...

EXEC SQL SELECT empno, sal INTO :sal_rec
FROM emp
WHERE ename = :name;
printf("Employee number and salary for %s: ", name);
printf("%d, %gn", sal_rec->emp_number, sal_rec->salary);

위의 쿼리에서 호스트 구조체에대한 포인터는 호스트 구조체 사용과 같은 방법으로
참조하면 주소참조기호(&)를 사용하지 않는다.
7) Globalization Support
아시아 언어들과 같은 2바이트 문자들에 대한 처리방법에 대한 설명을 할것이다.
오라클은 Globalization을 지원하기때문에 다른 언어 환경에서도 작동된다.
오라클은 NLS parameters 혹은 다양한 Globalization support를 지정하므로서 언어
독립적으로 작동 시킬 수 있다.
오라클 초기 파일에 이런 내용를 설정 할 수있으며, 테이블 4-6은 지원 파라미터를
보여주고 있다.




주요한 파라미터는 NLS_LANGUAGE 와 NLS_TERRITORY이다. NLS_LANGUAGE는 서버 메세지에
대한 언어, 월/일이름에 대한 언어, sort 순서등을 지정 할 수 있다.
NLS_TERRITORY 파라미터는 날짜형식, Decimal character, 그룹 분리자 (group separator),
Local currency symbol, ISO currency symbol등을 지정 한다.

NLS_LANG = <language>_<territory>.<character set>

위와 같은 형태로 파라미터를 지정하며, language는 사용자 세션에대한 NLS_LANGUAGE의 값을
설정하고, territorysms NLS_TERRITORY의 값을 설정하며 character set은 터미널에서 사용되는
인코딩 구조(문자셋 혹은 code page)를 지정한다. 인코딩 구조는 수치코드의 범위이다.

NLS_LANG는 환경변수로 시스템에 선언한다. 예를 들어서, C쉘에서 NLS_LANG는 아래와 같이
선언한다.

setenv NLS_LANG French_France.WE8ISO8859P1

오라클 데이터베이스 세션내에서 아래와 같은 문장을 이용해서 파라미터를 변경할 수 있다.

ALTER SESSION SET <globalization support_parameter> = <value>

Pro*C/C++에서는 모든 Globalization을 지원한다. 즉 다국어로 저장된 데이터를 처리하기위한
함수들을 오라클은 제공하고 있다.

8) NCHAR 변수
3개의 내부 데이타유형은 전체국가의 문자셋 데이터를 저장할수 있다.
(NCHAR,NCLOB, NVARCHAR2 = NCHAR VARYING)
Pro*C/C++은 초기버젼의 멀티바이트 NCHAR호스트 변수를 지원한다. NLS_LOCAL값이 YES로
설정되어 있을때, 멀티바이트(초기버젼)는 SQLLIB에서 제공될것이다( oracle 7).
NLS_LOCAL값이 NO로 설정되면, Oracle7이후버젼의 새로운 의미의 멀티바이트 스트링을 지원한다.
새로운 어플리케이션을 위해서는 NLS_LOCAL=NO로 설정하고 사용하라.

8-1) CHARACTER SET [IS] NCHAR_CS
전체국가의 문자셋 데이터를 가질수 있는 호스트 변수를 지정하기위해서는 문자변수를
선언할때 "CHARACTER SET [IS] NCHAR_CS"절을 삽입한다. 이렇게 하면 선언한 변수에
다국어를 지원하는 문자셋 데이터를 저장 할 수 있다. IS는 생락가능하며 NCHAR_CS는
다국어 문자셋의 이름이된다.
예를 들면,

char character set is nchar_cs *str = "<Japanese_string>";

<Japanese_string>은 AL16UTF16문자셋인 유니코드 문자로 구성된다.

EXEC SQL
SELECT ENAME INTO :str FROM EMP WHERE DEPT = n’<Japanese_string1>’;

str에 데이타를 취득하기위해서, 위의 쿼리를 사용한다.
혹은 아래와 같이 사용할 수 있다.

EXEC SQL
SELECT DEPT INTO :dept FROM DEPT_TAB WHERE ENAME = :str;

8-2) 환경 변수 - NLS_NCHAR
NLS_LOCAL = NO되어 있을 경우나, NLS_NCHAR 환경변수가 설정되어있을 경우에 데이터
베이스 서버는 NCHAR를 지원한다. NLS_NCHAR는 전처리시나 실행시에 유효한 전체국가의
문자셋분류가 지정되어 있어야만 한다.

8-3) CONVBUFSZ Clause in VAR
EXEC SQL VAR문은 선택할 수 있는 절이다 : CONVBUFSZ (<size>).
<size>는 바이트이며 문자셋을 변환할 수 있는 오라클 런타임 라이브러리의 버퍼
크기를 지정하는데 사용한다.

문법은 다음과 같다. :

EXEC SQL VAR host_variable IS datatype [CONVBUFSZ [IS] (size)] ;
혹은
EXEC SQL VAR host_variable [CONVBUFSZ [IS] (size)];
여기에서 데이타형은 :
type_name [ ( { length | precision, scale } ) ]

8-4) 임베디드 SQL에서의 문자 스트링 (Character Strings in Embedded SQL)
스트링은 통상적으로 따옴표(')를 사용한다.
예를들어 임베디드 SQL은 아래와 같다 :

EXEC SQL SELECT empno INTO :emp_num FROM emp
WHERE ename = N'<Japanese_string>';

8-5) 스트링의 제한
Dynamic SQL method 4는 Pro*C/C++에서 멀티바이트 문자스트링 호스트 변수를 사용할
수 없다.

8-6) 지시자 변수 ( Indicator Variables )
멀티바이트 문자인 호스트 문자 변수는 지시자 변수와 함께 사용 할 수 있다.


출처 - http://younbok.egloos.com/9342726

:

[번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 03

Language/Pro*C 2015. 5. 20. 17:07

목 차

▣ 오라클 데이터 유형 (Oracle Datatypes)
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ VARCHAR 변수 ( VARCHAR Variables )
▣ 커서 변수 ( Cursor Variables )
▣ CONTEXT 변수 ( CONTEXT Variables )
▣ Universal ROWIDs
▣ 호스트 구조체 ( Host Structures )
▣ 포인터 변수 ( Pointer Variables )
▣ Globalization Support
▣ NCHAR 변수 ( NCHAR Variables )
5) 커서 변수 ( Cursor Variables )
커서 변수의 장점은 다음과같다.
▶ 쉬운 유지보수
커서 변수가 열리는 스토어드 프로시져내로 쿼리가 집중된다.
만약 커서가 변경될 필요가 있으면, 한곳의 커서내용만 변경하면되고 각 어플리케이션
을 변경할 필요가 없다.
▶ 편리한 보안성
어플리케이션의 사용자는 Pro*C/C++응용프로그램이 서버에 연결할때 사용한 사용자이름
이 된다. 사용자는 쿼리에서 사용된 테이블의 읽기 권한이 아닌 실행권한을 가져야만
한다. 이러한 것은 테이블의 컬럼에 접근하는 것을 제한 할 수 있다.

5-1) 커서 변수 선언
SQL_CURSOR 유형을 사용해서 커서 변수를 선언할 수 있다. 예를 들면 아래와 같다.

EXEC SQL BEGIN DECLARE SECTION;
sql_cursor emp_cursor; /* a cursor variable */
SQL_CURSOR dept_cursor; /* another cursor variable */
sql_cursor *ecp; /* a pointer to a cursor variable */
...
EXEC SQL END DECLARE SECTION;
ecp = &emp_cursor; /* assign a value to the pointer */

대소문자를 가리지는 않으나 대소문자를 혼용해서 사용해서는 않된다.
커서변수는 함수의 인자로 념겨서 사용할 수 있으며, 함수를 커서변수를 리턴하도록
선언할 수 도 있고 포인터 변수로도 리턴가능하다.

5-2) 커서 변수 할당
커서 변수를 사용하기에 앞서 커서를 할당해야한다. 전처리 명령어인 ALLOCATE명령어
를 사용해서 커서를 할당한다. 예를 들어, 위의 예제에서 선언한 SQL_CURSOR emp_cursor를
할당하기위해서 아래와 같은 문을 작성한다 :

EXEC SQL ALLOCATE :emp_cursor;

커서 변수를 위해서 할당된 메모리는 CLOSE 문이 실행될때나 연결이 닫힐경우 해제된다.
EXEC SQL CLOSE :emp_cursor;
5-3) 커서 변수 열기
오라클 데이터베이스 서버상에서 커서변수는 열어야한다.SQL OPEN 명령어로 커서 변수를
열수는 없다. 예를 들어, 데이터베이스에 저장된 아래의 PL/SQL 패키지를 고려해 보자.

CREATE PACKAGE demo_cur_pkg AS
TYPE EmpName IS RECORD (name VARCHAR2(10));
TYPE cur_type IS REF CURSOR RETURN EmpName;
PROCEDURE open_emp_cur ( curs IN OUT cur_type, dept_num IN NUMBER);
END;

CREATE PACKAGE BODY demo_cur_pkg AS
CREATE PROCEDURE open_emp_cur (
curs IN OUT cur_type,
dept_num IN NUMBER) IS
BEGIN
OPEN curs FOR
SELECT ename FROM emp
WHERE deptno = dept_num
ORDER BY ename ASC;
END;
END;

위의 패키지가 저장된후, Pro*C/C++프로그램에서는 open_emp_cur커서를 사용할 수 있다.
아래의 예제를 보자.
...
sql_cursor emp_cursor;
char emp_name[11];
...
/* 커서변수 할당 */
EXEC SQL ALLOCATE :emp_cursor;
...
/* 서버에서 커서를 OPEN */
EXEC SQL EXECUTE
begin
demo_cur_pkg.open_emp_cur(:emp_cursor, :dept_num);
end;
;

EXEC SQL WHENEVER NOT FOUND DO break;

for (;;)
{
EXEC SQL FETCH :emp_cursor INTO :emp_name;
printf("%sn", emp_name);
}
...
PL/SQL 블록내에서 커서를 OPEN하기위해서, 블록내에 커서를 아래의 예처럼 선언해야
한다.

sql_cursor emp_cursor;
int dept_num = 10;
...

EXEC SQL EXECUTE
BEGIN
OPEN :emp_cursor FOR SELECT ename FROM emp
WHERE deptno = :dept_num;
END;
END-EXEC;
...

아래의 예제는 커서절과 함께 임베디드 SQL문을 사용해서 커서변수를 OPEN하는 경우를
보여주고 있다.

...
sql_cursor emp_cursor;
...
EXEC ORACLE OPTION(select_error=no);
EXEC SQL
SELECT CURSOR(SELECT ename FROM emp WHERE deptno = :dept_num)
INTO :emp_cursor FROM DUAL;
EXEC ORACLE OPTION(select_error=yes);
위의 예제처럼, cursor절이 포함된 쿼리를 사용하기전에,SELECT_ERROR옵션을 NO로 설정
해야만 한다. 이것음 부모 커서의 취소를 막고 프로그램이 에러없이 작동되도록한다.


5-4) 커서 변수 해제와 닫기

커서변수를 닫기위해서 CLOSE명령어를 사용한다. 예제는 아래와같다.

EXEC SQL CLOSE :emp_cursor;

할당된 커서 변수는 재사용이 가능하지만, 서버와 연결이 끊겼다거나, 재연결된경우
커서변수를 재할당 해야만 한다.

EXEC SQL FREE :emp_cursor;

할당된 커서를 할당해제하기위해서는 위와같이 사용하면된다.

5-5) 예제 (cv_demo.sql 과 sample11.pc )

아래의 예제는 PL/SQL 스크립트와 Pro*C/C++프로그램으로 커서변수를 사용하는 방법을
보여주고 있다.

/******************************************************************************
* cv_demo.sql
******************************************************************************/

-- PL/SQL source for a package that declares and
-- opens a ref cursor

CONNECT SCOTT/TIGER;

CREATE OR REPLACE PACKAGE emp_demo_pkg as
TYPE emp_cur_type IS REF CURSOR RETURN emp%ROWTYPE;
PROCEDURE open_cur(curs IN OUT emp_cur_type, dno IN NUMBER);
END emp_demo_pkg;

CREATE OR REPLACE PACKAGE BODY emp_demo_pkg AS
PROCEDURE open_cur(curs IN OUT emp_cur_type, dno IN NUMBER) IS
BEGIN
OPEN curs FOR SELECT *
FROM emp WHERE deptno = dno
ORDER BY ename ASC;
END;
END emp_demo_pkg;
/******************************************************************************
* sample11.pc
*
* 커서변수를 사용해서 EMP 테이블에서 데이터를 취득한다.
* EMP_DEMO_PKG 패키지 내의 open_cur를 PL/SQL 프로시져 에서 연다.
*
******************************************************************************/
#include <stdio.h>
#include <sqlca.h>
#include <stdlib.h>
#include <sqlda.h>
#include <sqlcpr.h>
//////////////////////////////////////////////////////////////////////
// 에러처리 함수
//////////////////////////////////////////////////////////////////////
void sql_error(msg)
char *msg;
{
size_t clen, fc;
char cbuf[128];
clen = sizeof (cbuf);

sqlgls((char *)cbuf, (size_t *)&clen, (size_t *)&fc);

printf("n%sn", msg);
printf("Statement is--n%sn", cbuf);
printf("Function code is %ldnn", fc);

sqlglm((char *)cbuf, (size_t *) &clen, (size_t *) &clen);

printf ("n%.*sn", clen, cbuf);
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK WORK RELEASE;

exit(EXIT_FAILURE);
}
//////////////////////////////////////////////////////////////////////
// 메인 함수
//////////////////////////////////////////////////////////////////////
void main()
{
char temp[32];

EXEC SQL BEGIN DECLARE SECTION;

char *uid = "scott/tiger";
SQL_CURSOR emp_cursor;
int dept_num;
struct
{
int emp_num;
char emp_name[11];
char job[10];
int manager;
char hire_date[10];
float salary;
float commission;
int dept_num;
} emp_info;
struct
{
short emp_num_ind;
short emp_name_ind;
short job_ind;
short manager_ind;
short hire_date_ind;
short salary_ind;
short commission_ind;
short dept_num_ind;
} emp_info_ind;

EXEC SQL END DECLARE SECTION;
EXEC SQL WHENEVER SQLERROR do sql_error("Oracle error");
/* 오라클 연결 */
EXEC SQL CONNECT :uid;
/* 커서변수 할당 */
EXEC SQL ALLOCATE :emp_cursor;
/* 데이터가 없을 경우 반복문 EXIT */
EXEC SQL WHENEVER NOT FOUND DO break;
for (;;)
{
printf("nEnter department number (0 to exit): ");
gets(temp);
dept_num = atoi(temp);
if (dept_num <= 0)
break;
EXEC SQL EXECUTE
begin
emp_demo_pkg.open_cur(:emp_cursor, :dept_num);
end;
END-EXEC;
printf("nFor department %d--n", dept_num);
printf("ENAME SAL COMMn");
printf("----- --- ----n");

/* EMP 테이블의 데이터를 취득, 지시자 구조체 사용 */

for (;;)
{
EXEC SQL FETCH :emp_cursor
INTO :emp_info INDICATOR :emp_info_ind;
printf("%s ", emp_info.emp_name);
printf("%8.2f ", emp_info.salary);

if (emp_info_ind.commission_ind != 0)
printf(" NULLn");
else
printf("%8.2fn", emp_info.commission);
}
}
/* 커서 닫기 */
EXEC SQL WHENEVER SQLERROR CONTINUE;

EXEC SQL CLOSE :emp_cursor;

/* 오라클 연결 종료 */
EXEC SQL ROLLBACK WORK RELEASE;
exit(EXIT_SUCCESS);
}

출처 - http://younbok.egloos.com/9342727

:

[번역] 데이터유형과 호스트 변수 (Datatypes and Host Variables ) - 02

Language/Pro*C 2015. 5. 20. 15:55

목 차

▣ 오라클 데이터 유형 (Oracle Datatypes)
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ VARCHAR 변수 ( VARCHAR Variables )
▣ 커서 변수 ( Cursor Variables )
▣ CONTEXT 변수 ( CONTEXT Variables )
▣ Universal ROWIDs
▣ 호스트 구조체 ( Host Structures )
▣ 포인터 변수 ( Pointer Variables )
▣ Globalization Support
▣ NCHAR 변수 ( NCHAR Variables )
3) 지시자 변수 ( Indicator Variables )
호스트 변수는 임의의 지시자 변수와 연관 시킬 수 있다. 지시자 변수는 2바이트
정수로 정의 되어야만 한다. SQL문에서 colon(:)이 앞에 붙어야하고, 호스트변수
바로뒤에 나와야한다(INDICATOR문을 사용하지 않은 경우). 만약에 Declare Section을
사용한다면, Declare Section문내에 지시자 변수를 선언해야만 한다.
3-1) INDICATOR 키워드
가독성을 높이기 위해서, INDICATOR를 선행해서 사용할 수 있다. 정확한 문법은
아래와 같다.

:host_variable INDICATOR :indicator_variable

같은 표현으로

:host_variable:indicator_variable 와 같이 사용 할 수도 있다.
호스트 프로그램에서는 두가지 형식을 다 사용할 수 있다. 지시자의 값과 그의미를
아래의 표에서 설명하고 있다.







3-2) 지시자 변수 사용의 예제

일반적으로, 지시자 변수는 입력호스트 변수에 NULL을 할당하는데 사용하며 출력
호스트 변수에 잘려진 값이나 NULL값을 감지하기위해서 사용한다. 아래의 예제에서
3개의 호스트 변수를 선언하고 1개의 지시자 변수를 선언한다. 그리고 SELECT문으로
데이터베이스에서 사원번호가 호스트 변수 emp_number와 같은정보를 찾는데 사용한다.
맞는 행이 발견되었을때, 오라클데이터베이스는 출력변수 salary와 commission에
그행의 컬럼 SAL과 COMM의 값을 설정한다. 그리고 지시자변수 ind_comm에 return
code를 저장한다. 그 다음문장에서 ind_comm를 이용해서 어떤행위를 할지를 결정한다.

EXEC SQL BEGIN DECLARE SECTION;

int emp_number;
float salary, commission;
short comm_ind; /* indicator variable */

EXEC SQL END DECLARE SECTION;

char temp[16];
float pay; /* not used in a SQL statement */
...
printf("Employee number? ");

gets(temp);

emp_number = atof(temp);

EXEC SQL SELECT SAL, COMM
INTO :salary, :commission:ind_comm
FROM EMP
WHERE EMPNO = :emp_number;

if(ind_comm == -1) /* commission is null */
pay = salary;
else
pay = salary + commission;

3-3) 지시자 변수 가이드 (INDICATOR Variable Guidelines)
다음의 가이드라인은 지시자변수를 선언하고 참조하는데 적용된다.
지시자변수는
▶ 2바이트 정수로 선언되어야만 한다.
▶ SQL문에 콜론(:)을 앞에 붙인다.
▶ SQL문이나 PL/SQL 블록 바로다음에 위치한다.
4) VARCHAR 변수 ( VARCHAR Variables )
varchar유형은 가변길이 스트링을 선언할때 사용한다. DB에서 varchar2나 혹은 long형 컬럼
에서 입출력하는 string을 다룰때, 표준 C 스트링을 대신해서 VARCHAR호스트 변수를 사용하는
것이 편리한다. VARCHAR라는 이름의 유형은 대소문자 다 사용가능하고 혼용해서는 사용이
불가능한다.

4-1) VARCHAR변수 선언
VARCHAR변수를 확장된 C 유형이나 미리선언된 구조체로 생각하면된다. 예를들어 전처리 컴파일
러는 VARCHAR선언을 아래와 같이 확장한다.

VARCHAR username[20];

위의 선언을 아래와 같이 확장하게 된다.

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

VARCHAR변수 사용의 장점은 SELECT나 FETCH후에 VARCHAR구조체의 길이 member변수를
참조 할 수 있다는 것이다. 길이 member변수는 스트링의 길이가 저장된다. 이길이를
NULL terminator를 추가하는것과 같은 경우에 이 member변수를 사용할 수있다.

username.arr[username.len] = ’’;

strncpy 혹은 printf문에서 길이를 사용하는데 쓰인다.

printf("Username is %.*sn", username.len, username.arr);

VARCHAR변수에 최대길이를 지정하는데 그 범위는 1~65533이며, 아래의 예와 같은 경우
길이가 지정되지 않아 유요하지 않은 경우를 보여주고 있다.

VARCHAR null_string[]; /* invalid */

한 라인에 여러개의 VARCHAR 변수를 선언할 수 있다.

VARCHAR emp_name[ENAME_LEN], dept_loc[DEPT_NAME_LEN];

4-2) VARCHAR변수 참조 (VARCHAR Variable Referencing )

SQL문에서, 아래의 예처럼 VARCHAR 변수를 사용할 수 있다 :
...
int part_number;
VARCHAR part_desc[40];
...
main()
{
...
EXEC SQL SELECT pdesc INTO :part_desc
FROM parts
WHERE pnum = :part_number;
...

쿼리가 실행된후에, part_desc.len에 스트링의 실제길이가 저장되고 스트링은 part_desc.arr에
저장된다. C문장에서, 어떻게 사용되는 아래의 예를 보면 알수 있다:

printf("nnEnter part description: ");
gets(part_desc.arr);
/* You must set the length of the string
before using the VARCHAR in an INSERT or UPDATE */
part_desc.len = strlen(part_desc.arr);

4-3) 함수인자로 VARCHAR을 전달( Pass VARCHAR Variables to a Function )

VARCHARs는 구조체이다.대부분의 C 컴파일러는 값으로 구조체인자를 함수에 넘기는것이
가능하다. Pro*C/C++에서 레퍼런스로 VARCHAR을 함수로 넘겨야 한다. 아래의 예제는
함수에 VARCHAR변수를 인자로 넘기는 정확한 방법을 예시하고 있다.

VARCHAR emp_name[20];
...
emp_name.len = 20;

SELECT ename INTO :emp_name FROM emp
WHERE empno = 7499;
...

print_employee_name(&emp_name); /* pass by pointer */
...

print_employee_name(name)
VARCHAR *name;
{
...
printf("name is %.*sn", name->len, name->arr);
...
}

4-4) VARCHAR Array Component의 길이 얻기

전처리기가 VARCHAR선언을 처리할때, 생성된 구조체의 배열요소의 길이는 선언된것보다
길어질 수 있다. 예를들어, SUN시스템에서는
VARCHAR my_varchar[12];
위와같은 선언이 아래와 같이 전처리기에의해서 확장된다.
struct my_varchar
{
unsigned short len;
unsigned char arr[12];
};
그러나, 전처리기나 C 컴파일러는 이 시스템에서 14바이트로 변경한다.
이것은 구조체 길이를 16바이트로 변경한다(14바이트 : 배열, 2바이트 : 길이).
SQLVarcharGetLength() 함수는 배열의 실제 길이를 리턴한다.
VARCHAR 호스트 변수의 데이터 길이나 혹은 VARCHAR호스트변수 포인터를 인자로 넘기고
SQLVarcharGetLength() 함수는 VARCHAR의 배열요소의 전체 길이를 리턴한다.

SQLVarcharGetLength() 함수는 다음과 같다.

SQLVarcharGetLength (dvoid *context, unsigned long *datlen, unsigned long *totlen);

단일 쓰레드 프로그램에서, sqlvcp()함수를 사용하라. 이함수를 호출하기전에 datlen 인자에
varchar의 길이를 설정하고, 함수가 리턴할때는 totlen인자에 배열의 전체길이가 포함되어
있다. 두개의 인자모두 unsigned long integer형인 포인터이면 반드시 reference로 넘겨야
한다.

4-5) 예제 프로그램 : Using sqlvcp()

아래의 예제 프로그램은 Pro*C/C++ application에서 함수를 어떻게 사용하는지 보여줄
것이다. 예제는 또한 sqlgls()함수를 사용한다. 그예제는 VARCHAR 포인터를 선언하고
VARCHAR버퍼에 요구되는 크기를 결정하기위해서 sqlvcp()함수를 사용한다.
프로그램은 사원이름을 EMP테이블에서 취득해서 출력하는 프로그램이다. 이 예제는
SQL문및 함수의 코딩,길이특성을 출력하기 위해서 sqlgls()함수를 사용한다.

/*************************************************************************************
* sqlvcp.pc 프로그램은 VARCHAR구조체의 실제크기를 결정하는 sqlvcp()함수를 어떻게 사용
* 하는지를 보여주고 있다. 그 크기는 배열의 포인터를 증가시키는 옵셋으로 사용된다.
*
* 이 프로그램은 또난 sqlgls() 함수를 어떻게 사용하는 지 보여주고 있다. 마지막에 실행된 SQL문
* 의 TEXT를 얻기위해 사용되었다. sqlgls()함수는 "Error Handling" 장에서 설명된다.
*************************************************************************************/

#include <stdio.h>
#include <sqlca.h>
#include <sqlcpr.h>

/* VARCHAR 포인터 유형을 선언 */
struct my_vc_ptr
{
unsigned short len;
unsigned char arr[32767];
};

/* VARCHAR 포인터를 위한 유형을 선언*/
typedef struct my_vc_ptr my_vc_ptr;
my_vc_ptr *vc_ptr;

EXEC SQL BEGIN DECLARE SECTION;
VARCHAR *names;
int limit; /* FETCH FOR 절에서 사용하기위해 선언 */
char *username = "scott/tiger";
EXEC SQL END DECLARE SECTION;

void sql_error();
extern void sqlvcp(), sqlgls();

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main 함수
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
unsigned int vcplen, function_code, padlen, buflen;
int i;
char stmt_buf[120];

EXEC SQL WHENEVER SQLERROR DO sql_error();
EXEC SQL CONNECT :username;
printf("nConnected.n");

/* 테이블의 행수를 취득 */
EXEC SQL SELECT COUNT(*) INTO :limit FROM emp;
/* 커서를 선언*/
EXEC SQL DECLARE emp_name_cursor CURSOR FOR
SELECT ename FROM emp;
EXEC SQL FOR :limit OPEN emp_name_cursor;

/* VARCHAR의 바람직한 데이터의 길이 설정 */
vcplen = 10;
/* 메모리를 할당하기위한 길이를 찾는데 SQLVCP 함수를 사용한다. */
sqlvcp(&vcplen, &padlen);
printf("Actual array length of VARCHAR is %ldn", padlen);
/* 이름 버퍼를 할당한다. FOR 을 위한 limit변수를 설정한다. */
names = (VARCHAR *) malloc((sizeof (short) + (int) padlen) * limit);

if (names == 0)
{
printf("Memory allocation error.n");
exit(1);
}

/* FETCH전에 최대길이 값을 설정. 효율적인 VARCHAR * 값을 얻기위한 방법임 */
for (vc_ptr = (my_vc_ptr *) names, i = 0; i < limit; i++)
{
vc_ptr->len = (short) padlen;
vc_ptr = (my_vc_ptr *)((char *) vc_ptr +
padlen + sizeof (short));
}
/* FETCH를 실행한다. */
EXEC SQL FOR :limit FETCH emp_name_cursor INTO :names;
/* 결과 출력 */
printf("Employee names--n");
for (vc_ptr = (my_vc_ptr *) names, i = 0; i < limit; i++)
{
printf("%.*st(%d)n", vc_ptr->len, vc_ptr->arr, vc_ptr->len);
vc_ptr = (my_vc_ptr *)((char *) vc_ptr +
padlen + sizeof (short));
}

/* 가장최근 의 통계를 얻음. SQL statement using SQLGLS. Note that
* the most recent statement in this example
* is not a FETCH, but rather "SELECT ENAME FROM EMP"
* (the cursor).
*/
buflen = (long) sizeof (stmt_buf);
/* 리턴값은 1이어야하며, 이는 에러가 없음을 알려준다. */
sqlgls(stmt_buf, &buflen, &function_code);
if (buflen != 0)
{
/* SQL문을 출력한다. */
printf("The SQL statement was--n%.*sn", buflen, stmt_buf);
/* 리턴된 길이를 출력 */
printf("The statement length is %ldn", buflen);
/* 특성을 출력. */
printf("The function code is %ldn", function_code);
EXEC SQL COMMIT RELEASE;
exit(0);
}
else
{
printf("The SQLGLS function returned an error.n");
EXEC SQL ROLLBACK RELEASE;
exit(1);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // sql_error()함수 - 에러 메시지를 출력한다.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void sql_error()
{
char err_msg[512];
int buf_len, msg_len;

EXEC SQL WHENEVER SQLERROR CONTINUE;
buf_len = sizeof (err_msg);
sqlglm(err_msg, &buf_len, &msg_len);
printf("%.*sn", msg_len, err_msg);
EXEC SQL ROLLBACK RELEASE;
exit(1);
}



출처 - http://younbok.egloos.com/9342728

:

[번역] 데이터유형과 호스트변수( Datatypes and Host Variables ) - 01

Language/Pro*C 2015. 5. 20. 15:54

목 차

▣ 오라클 데이터 유형 (Oracle Datatypes)
▣ 호스트 변수 ( Host Variables )
▣ 지시자 변수 ( Indicator Variables )
▣ VARCHAR 변수 ( VARCHAR Variables )
▣ 커서 변수 ( Cursor Variables )
▣ CONTEXT 변수 ( CONTEXT Variables )
▣ Universal ROWIDs
▣ 호스트 구조체 ( Host Structures )
▣ 포인터 변수 ( Pointer Variables )
▣ Globalization Support
▣ NCHAR 변수 ( NCHAR Variables )
1) 오라클 데이터 유형 (Oracle Datatypes)

1-1) Internal Datatype
데이터베이스 컬럼에 저장된 값들을 위해서 오라클은 Internal Datatype를 사용한다.




NCHAR나 NVARCHAR2는 다중바이트 문자 데이터를 저장하는데 사용된다.
LOB 유형은 구조화되지 않은 데이터((text, graphic images, video clips, or sound waveforms)를
저장하는데 사용되며, BFILE data는 데이터 베이스 밖에 파일을 저장한다.
1-2) External Datatype
External Datatype은 아래의 표를 참조한다.




2) 호스트 변수 ( Host Variables )
호스트 변수는 오라클과 호스트 프로그램사이의 통신을 위한 키이다. precompiler 프로그램은 호스트
변수로부터 오라클로 데이터를 입력하고 오라클은 데이터를 호스트변수로 추출한다.
2-1) 호스트변수 선언
C프로그래밍 언어의 규칙에 따라서 호스트 변수를 선언한다.
MODE=ORACLE로 지정되어 있으면, Declare Section에 변수를 선언할 필요는 없다. 만약 모드가
그렇지 않다면, FIPS flagger는 이것에 대해서 경고를 알릴것이다.
모드가 CODE=CPP 혹은 PARSE=NONE 혹은 PARSE=PARTIAL이면, Declare Section을 사용해야만
한다.
아래의 표는 호스트 변수를 선언할때 사용할 수 있는 데이터 유형이다.




아래의 표는 호환가능한 오라클 내부 데이터 유형을 보여주고 있다.






C유형의 1차배열은 호스트 변수에서 사용 가능하다. char[n] 와 VARCHAR[n]에서 n은 string의
최대길이를 지정한 것이다. 이차원 배열은 char[m][n] 와 VARCHAR[m][n]에 대해서 사용 가능
하며 n은 string의 최대길이를 지정하며 m은 배열에서 string의 수를 지정 하는 것이다.
단순한 C 유형의 포인터를 사용할 수 있으며 char[n] 와 VARCHAR[n]에 대한 포인터는 char 혹은
VARCHAR로 선언되어야만 한다. 포인터 배열은 지원하지 않는다.
Storage-Class Specifiers
Pro*C/C++은 호스트 변수를 선언할때 auto, extern, 그리고 static 과같은 storage-class specifiers
를 사용할 수 있다. register는 사용 할 수 없다. 예제는 아래와 같다.
extern char protocol[15];
extern char msg[]; <-- 255자를 넘어가는 경우 문제가 발생한다.
the const 와 volatile 유형 qualifiers를 사용가능하다.
2-2) 호스트변수 참조
호스트 변수는 colon (:)을 붙여서 표시하여야 한다. 예제는 아래의 코드와 같다.
char buf[15];
int emp_number;
float salary;
...

gets(buf);
emp_number = atoi(buf);
EXEC SQL SELECT sal INTO :salary FROM emp
WHERE empno = :emp_number;
혼란스럽지만, 오라클의 컬럼및 테이블 이름과 같은 이름으로 호스트 변수를 줄 수 있다.
아래에 예제가 있다.
int empno;
char ename[10];
float sal;
...

EXEC SQL SELECT ename, sal INTO :ename, :sal FROM emp
WHERE empno = :empno;
함수 호출이나 수치 표현은 호스트 변수로 사용될 수 없다. 아래의 코드는 유효하지않은 코드이다.
#define MAX_EMP_NUM 9000
...

int get_dept();
...
EXEC SQL INSERT INTO emp (empno, ename, deptno) VALUES
(:MAX_EMP_NUM + 10, ’CHEN’, :get_dept());



출처 - http://younbok.egloos.com/9342729

:

[번역] pro*c 데이터베이스 개념(Database Concepts) - 03

Language/Pro*C 2015. 5. 20. 15:40

목 차

▣ 데이터베이스 연결( Connect to the Database )
▣ 연결옵션( Advanced Connection Options )
▣ Definitions of Transactions Terms
▣ How Transactions Guard Your Database
▣ 트렌잭션 시작하고 끝내는 방법(How to Begin and End Transactions)
▣ Commit문의 사용 ( Using the COMMIT Statement )
▣ SAVEPOINT문의 사용 ( Using the SAVEPOINT Statement )
▣ ROLLBACK문의 사용 ( The ROLLBACK Statement )
▣ RELEASE 옵션 ( The RELEASE Option )
▣ SET TRANSACTION문 (The SET TRANSACTION Statement )
▣ Override Default Locking
▣ Fetch Across COMMITs
▣ Distributed Transactions Handling
7) RELEASE옵션(The RELEASE option)
작성한 프로그램이 Commit혹은 Rollback이 작동하지 않을때 비정상적으로 종료되며, Release옵션
을 사용해서 오라클 연결을 끊는다. 아래의 두가지 예를 사용해서 프로그램을 종료한다.
EXEC SQL COMMIT WORK RELEASE;
혹은
EXEC SQL ROLLBACK WORK RELEASE;
8) SET TRANSACTION문 (The SET TRANSACTION Statement )
SET TRANSACTION문은 아래의 예처럼 사용가능한다. SET TRANSACTION문은 Read-only transation에서 처음에 사용되어야만 하며 단지 한번만 사용가능하다. 다른 트랙젝션에는 영향을 미
치지 않는다.
EXEC SQL SET TRANSACTION READ ONLY;
select , commit, rollback문만이가능하다. insert,delete,select for update문이 오면 에러를 발생한다.
아래의 예제는, 가게운용자가 보고서를 출력하기위해서 read-only transaction을 사용해서 과거의 달,주, 일별 판매현황을 체크하는 예제이다. 트랜젝션하는동안 데이터베이스를 update하는 사용자에게는
영향을 주지 않는다.
EXEC SQL SET TRANSACTION READ ONLY;
EXEC SQL SELECT sum(saleamt) INTO :daily FROM sales
WHERE saledate = SYSDATE;
EXEC SQL SELECT sum(saleamt) INTO :weekly FROM sales
WHERE saledate > SYSDATE - 7;
EXEC SQL SELECT sum(saleamt) INTO :monthly FROM sales
WHERE saledate > SYSDATE - 30;
EXEC SQL COMMIT WORK;
/* simply ends the transaction since there are no changes
to make permanent */
/* format and print report */
9) Override Default Locking
오라클은 자동적으로 update 혹은 delete 하는 시점에 Row-level lock을 얻는다. 그래서, update나
delete 전에 row에대한 lock을 원한다면 FOR UPDATE OF 절을 사용해라.
전체 테이블에 대한 lock을 걸기위해서는 LOCK TABLE문을 사용할 수 있다.
Using FOR UPDATE OF
아래의 예와같이 FOR UPDATE OF절을 사용한다.
EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT ename, job, sal FROM emp WHERE deptno = 20
FOR UPDATE OF sal;
FOR UPDATE OF절을 사용하면 여러 테이블을 참조 할 수 없다. 모든행은 FETCH될때 Lock이
걸리는 것이 아니고, OPEN될때 Lock이 걸리게 된다. ROW Lock은 Commit나 RollbacK했을때
해제가되며, commit후에 FOR UPDATE커서로 부터 Fetch 할 수 가 없다.
Using LOCK TABLE
LOCK TABLE문은 지정된 LOCK 모드로 한개이상의 테이블에 Lock을 걸 수 있다.
아래에 예제를 보여주고 있다.
EXEC SQL LOCK TABLE EMP IN ROW SHARE MODE NOWAIT;
10) Fetch Across COMMITs
COMMIT와 FETCH를 혼용하기를 원한다면, CURRENT OF절을 사용해서는 않된다.
ROWID를 사용해서 update난 delete할 현재행을 확인 할 수 있다. 예제는 아래와 같다.
...

EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT ename, sal, ROWID FROM emp WHERE job = ’CLERK’;
...

EXEC SQL OPEN emp_cursor;
EXEC SQL WHENEVER NOT FOUND GOTO ...

for (;;)
{
EXEC SQL FETCH emp_cursor INTO :emp_name, :salary, :row_id;
...
EXEC SQL UPDATE emp SET sal = :new_salary
WHERE ROWID = :row_id;
EXEC SQL COMMIT;
...
}

11) Distributed Transactions Handling
Distributed Database는 다른 Node의 여러개의 물리적 데이터베이스로 구성된 한개의 논리 데이터
베이스를 말한다. Distributed문은 데이터베이스 링크를 사용한 원격 컴퓨터를 접근 하는 SQL문이다.
Commit이 발생했을때, 원격에 있는 데이터 베이스들이 변경되게 된다. 만약에 ROLLBACK이
발생했을 경우, 모든 변화는 적용되지 않게 된다. 네트웍이나 시스템의 에러로 인해서 문제가 발생
하게되면 FORCE TRANSACTION 시스템 권한을 가진 사람이 수동으로 아래와 같이 적용을 해야한다.
EXEC SQL COMMIT FORCE ’22.31.83’;

EXEC SQL ROLLBACK FORCE ’25.33.86’;
’25.33.86’은 오라클의 데이터 사전 View인 DBA_2PC_PENDING테이블에서 확인 할수 있고 이를
이용하여 수동으로 적용 할 수 있다.



출처 - http://younbok.egloos.com/9342730

:

[번역] pro*c 데이터베이스 개념(Database Concepts) - 02

Language/Pro*C 2015. 5. 20. 15:40

목 차

▣ 데이터베이스 연결( Connect to the Database )
▣ 연결옵션( Advanced Connection Options )
▣ Definitions of Transactions Terms
▣ How Transactions Guard Your Database
▣ 트렌잭션 시작하고 끝내는 방법(How to Begin and End Transactions)
▣ Commit문의 사용 ( Using the COMMIT Statement )
▣ SAVEPOINT문의 사용 ( Using the SAVEPOINT Statement )
▣ ROLLBACK문의 사용 ( The ROLLBACK Statement )
▣ RELEASE 옵션 ( The RELEASE Option )
▣ SET TRANSACTION문 (The SET TRANSACTION Statement )
▣ Override Default Locking
▣ Fetch Across COMMITs
▣ Distributed Transactions Handling
3) Definitions of Transactions Terms
Transactions이란 주제를 이해하기위해서는 몇가지 용어의 개념을 알고 넘어가야 한다.
오라클은 동시성(concurrency)을 제어 해야만 하는데 이를 제어하지 못한다면, 데이터이 손실이 발생
할 수도 있기때문이다.
데이터를 동시에 접근하는것을 제어하기위해서 Locks를 사용한다. Lock은 사용자에게 임시적으로
데이터 베이스 리소스에 임시적으로 권한을 부여한다. 그래서, 데이터는 사용자가 작업을 끝낼때가지
변경될수 없도록 한다.
같은 데이터베이스 객체에 둘 이상의 사용자가 접근할때 Deadlock이 발생할 수 있다.
한사용자가 테이블을 쿼리하고 다른 사용자가 동시에 테이터를 update했을때 쿼리에의해 읽힌 데이터
는 변경되지 않는다. 오라클은 테이블 데이터의 스넵샷(snapshot)을 만들고, 레코드는 rollback segment에서 변경된다.
4) How Transactions Guard Your Database
트렌젝션 중간에 프로그램이 실패하면, 데이터 베이스는 자동적으로 이전상태로 복원하게된다.
다음장에서는 트랜젝션을 정의 하고 제어하는 방법에 대해서 배울것이다.
5) Transactions을 시작하고 끝내는 방법
트렌잭션은 처음 sql문이 실행되면 시작되고 다음 SQL문이 실행되면 다른 트랜잭션이 자동적으로
실행된다. 그래서 모든 실행가능한 문장은 트랜젝션의 부분이된다.
트랜젝션을 끝내는 방법은 아래와 같다.
● COMMIT 혹은 ROLL BACK문을 실행한 경우
● ALTER,CREATE,GRANT와 같은 DDL문을 실행한경우
소프트웨어적인 문제나 하드웨어적인 문제와같은 기대하지 않은 문제가 발생한 경우 트랜젝션이
끝나며 오라클은 트랜젝션을 ROLL BACK 시킨다.
5) Commit문의 사용 ( Using the COMMIT Statement )
COMMIT명령은
● 트랜젝션동안에 변경된 내용을 영원히 바꾼다.
● 다른 사용자에게 변경된 내용을 볼 수 있도록 한다.
● 테이블이나 행에 걸려있는 모든 LOCK를 해제한다.
● CURRENT OF절이 참조하고있는 커서를 닫는다.
● 트랜젝션을 끝낸다.
EXEC SQL COMMIT WORK RELEASE;
위의 문장은 트랜젝션을 COMMIT하고 오라클 연결을 끊는다. WORK는 ANSI호환성을 제공하고,
RELEASE 옵션은 프로그램이 잡고있는 모든 오라클 리소스를 해제하고, 데이터 베이스를 로그오프
한다. DDL명령은 COMMIT을 할 필요가 없다. 이문장들은 자동으로 COMMIT을 실행한다.
6) SAVEPOINT문의 사용 ( Using the SAVEPOINT Statement )
트랜젝션의 현재 지점을 표시하는데 SAVEPOINT는 사용된다. 예를 들어, 아래의 문장은
start_delete라는 이름으로 SAVEPOINT를 지정한것이다. :
EXEC SQL SAVEPOINT start_delete;

Savepoints는 긴 트랜젝션을 나눌수 있도록 해준다. 아래의 예제는 MAIL_LIST 테이블에 접근하여
새로운 리스트를 추가하고, 예전의 리스트를 UPDATE 하거나, 삭제하는 예제이다. 삭제후에 sqlerrd의
3번째 요소를 체크해서 그수가 기대치보다 크다면 savepoint인 start_delete까지 rollback을 처리해서 삭제 되지 않도록 처리하는 예제이다....

for (;;)
{
printf("Customer number? ");
gets(temp);
cust_number = atoi(temp);
printf("Customer name? ");
gets(cust_name);
EXEC SQL INSERT INTO mail_list (custno, cname, stat)
VALUES (:cust_number, :cust_name, ’ACTIVE’);
...
}

for (;;)
{
printf("Customer number? ");
gets(temp);
cust_number = atoi(temp);
printf("New status? ");
gets(new_status);
EXEC SQL UPDATE mail_list
SET stat = :new_status
WHERE custno = :cust_number;
}

/* mark savepoint */
The ROLLBACK Statement
3-20 Pro*C/C++ Precompiler Programmer’s Guide
EXEC SQL SAVEPOINT start_delete;
EXEC SQL DELETE FROM mail_list
WHERE stat = ’INACTIVE’;
if (sqlca.sqlerrd[2] < 25) /* check number of rows deleted */
printf("Number of rows deleted is %dn", sqlca.sqlerrd[2]);
else
{
printf("Undoing deletion of %d rowsn", sqlca.sqlerrd[2]);
EXEC SQL WHENEVER SQLERROR GOTO sql_error;
EXEC SQL ROLLBACK TO SAVEPOINT start_delete;
}

EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL COMMIT WORK RELEASE;
exit(0);
sql_error:
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK WORK RELEASE;
printf("Processing errorn");
exit(1);

하나의 savepoint로 rollback을 하면 그후에 지정된 savepoint는 삭제된다, 그러나 rollback이
일어난 지점의 savepoint는 삭제되지 않으며, 같은 이름의 savepoint가 있다면, 먼저 지정한 것은
지워진다. COMMIT 혹은 ROLLBACK 문은 모든 savepoint를 지운다.
7) Rollback문의 사용 ( Using the ROLLBACK Statement )
Rollback문은 데이터베이스의 변경된 내용을 되돌리려고 할때 사용한다.
Rollback이 일어나면 아래와 같은 일이 발생하게 된다.
● 현재 트랜젝션이 일어난 동아 발생한 데이터베이스의 변경을 되돌린다.
● 모든 savepoint를 삭제한다.
● 트랜젝션을 끝낸다.
● parse lock을 제외하고 모든 행과 테이블에 걸린 lock을 해제한다.
● CURRENT OF 절에서 참조된 모든 커서를 닫는다.


출처 - http://younbok.egloos.com/9342731

:

[번역] pro*c 데이터베이스 개념(Database Concepts) - 01

Language/Pro*C 2015. 5. 20. 15:38

목 차

▣ 데이터베이스 연결( Connect to the Database )
▣ 연결옵션( Advanced Connection Options )
▣ Definitions of Transactions Terms
▣ How Transactions Guard Your Database
▣ 트렌잭션 시작하고 끝내는 방법(How to Begin and End Transactions)
▣ Commit문의 사용 ( Using the COMMIT Statement )
▣ SAVEPOINT문의 사용 ( Using the SAVEPOINT Statement )
▣ ROLLBACK문의 사용 ( The ROLLBACK Statement )
▣ RELEASE 옵션 ( The RELEASE Option )
▣ SET TRANSACTION문 (The SET TRANSACTION Statement )
▣ Override Default Locking
▣ Fetch Across COMMITs
▣ Distributed Transactions Handling
1) 데이터베이스 연결( Connect to the Database )
Connect문의 사용문법은 다음과 같다.
EXEC SQL CONNECT { :user IDENTIFIED BY :oldpswd | :usr_psw }
[[ AT { dbname | :host_variable }] USING :connect_string ]
[ {ALTER AUTHORIZATION :newpswd | IN { SYSDBA | SYSOPER } MODE} ] ;

Pro*C/C++ 프로그램은 데이타를 취득 및 조작하기전에 데이터베이스와 연결 해야만 한다. 로그온
하기위해서 간단히 아래의 문장 처럼 사용한다.
EXEC SQL CONNECT :username IDENTIFIED BY :password ;
위의 문장에서 username 와 password는 char 변수나 VARCHAR의 호스트 변수를 사용한다.
혹은, 아래의 문장처럼 연결하기도 한다.
EXEC SQL CONNECT :usr_pwd;
위의 문장에서 usr_pwd는 / (slash 문자)로 구분된 사용자명과 비밀번호로 이루어 졌다.
CONNECT문은 프로그램에 의해서 실행되는 처음의 SQL문장이어야만 하며, 아래의 예제처럼
두개의 변수를 사용하여 CONNECT문을 실행할 수 있다. 사용자명과 비밀번호를 사용자 입력으로 받을
수도 있고, 아래의 코딩처럼 하드코딩하여 사용 할 수도 있다.
char *username = "SCOTT";
char *password = "TIGER";
...
EXEC SQL WHENEVER SQLERROR ...
EXEC SQL CONNECT :username IDENTIFIED BY :password;
그렇지만 ,아래의 예제처럼 CONNECT문안에 사용자명과 비밀번호를 하드코딩 할 수는 없다.
EXEC SQL CONNECT SCOTT IDENTIFIED BY TIGER;
EXEC SQL CONNECT ’SCOTT’ IDENTIFIED BY ’TIGER’;
1-1) 비밀번호 변경을 위한 ALTER AUTHORIZATION 절의 사용
Pro*C/C++는 EXEC SQL CONNECT문을 확장해서 실행시 사용자의 비밀번호를 변경할 수 있는
편리한 방법을 제공한다.
일반적인 로그온 방법으로 사용자가 로그인을 했을 경우, 사용자의 기간이 만료되었거나 비밀번호가
틀릴경우가 발생할 수 있다.이런한 경우,
EXEC SQL CONNECT .. ALTER AUTHORIZATION :newpswd;
위의 문장을 사용해서 사용자가 newpswd 로 비밀번호를 변경 할 것을 나타낸다.
2) 연결옵션( Advanced Connection Options )
아래의 그림은 Oracle Net을 이용하여 한개의 로컬 데이터베이스와 3개의 원격 데이터베이스와
통신하는 모습을 도식화 한 것이다.




이번장에서는 다음에 대해서 배울것이다.
◎ 프로그램이 직/간접적으로 다른 데이터베이스를 엑세스하는 방법
◎ 동시적으로 로컬과 리모드의 데이터베이스를 엑세스하는 방법
◎ 같은 데이터베이스에 다중연결을 하는 방법
각각의 노드(node - Network에서 이야기하는 Node의 개념)에는 디폴트 데이터베이스(Default
Database)를 가지고 있다. 이름을 지정하지 않고 Connect문을 사용하면 디폴트 데이터베이스에
연결한다. 기본적인 연결은 AT절 없이 연결을 한다. 기본적으로 설정되지 않은 데이터베이스에
연결을 하고자 할경우, AT절을 이용해서 연결하며 모든 데이터베이스의 이름은 유일해야하면
연결시 같은 이름으로 여러번 설정하여 연결 할 수 있다. 이것이 바로 데이터 베이스의 다중연결을
설정하는 것이다.
2-1) Explicit Connections
▶ Single Explicit Connection
아래의 예제는 원격의 서버에 데이터베이스에 연결하는 것이다.
/*** 필요한 호스트 변수 선언 ***/
char username[10] = "scott";
char password[10] = "tiger";
char db_string[20] = "NYNON";

/*** 유일한 데이터베이스명을 준다. ***/
EXEC SQL DECLARE DB_NAME DATABASE;

/*** 데이터베이스를 연결한다. ***/
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT DB_NAME USING :db_string;
혹은 아래의 예제처럼 , 호스트 변수를 AT절에 사용 할 수 도 있다.
아래의 예제에서는 DECLARE DATABASE 문장이 필요하지 않다.
/*** 필요한 호스트 변수 선언 ***/
char username[10] = "scott";
char password[10] = "tiger";
char db_name[10] = "oracle1";
char db_string[20] = "NYNON";
/* db_name 을 사용해서 데이터베이스 연결하기 */
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT :db_name USING :db_string;
...
권한을 부여하는 SQL문을 실행할 경우 아래와 같이 사용할 수 있다.
EXEC SQL AT DB_NAME SELECT ...
EXEC SQL AT DB_NAME INSERT ...
EXEC SQL AT DB_NAME UPDATE ...
PL/SQL문을 작성해서 사용할 경우 아래와 같은 형태로 사용 가능하다.
EXEC SQL AT :db_name EXECUTE
begin

/* PL/SQL block here */
end;
END-EXEC;
▶ Cursor 제어
OPEN, FETCH, 그리고 CLOSE와 같은 커서제어 문은 예외이다. 이것은 AT절을 사용할 수
없으며, 커서를 사용하려면, DECLARE CURSOR 절에 AT절을 사용해야 한다.
사용예는 아래와 같다.
EXEC SQL AT :db_name DECLARE emp_cursor CURSOR FOR ...
EXEC SQL OPEN emp_cursor ...
EXEC SQL FETCH emp_cursor ...
EXEC SQL CLOSE emp_cursor;
아래의 예에서 처럼 커서가 열렸을때, 관계를 변경 할 수 없다.
EXEC SQL AT :db_name DECLARE emp_cursor CURSOR FOR ...
strcpy(db_name, "oracle1");
EXEC SQL OPEN emp_cursor;
EXEC SQL FETCH emp_cursor INTO ...
strcpy(db_name, "oracle2");
EXEC SQL OPEN emp_cursor; /* illegal, cursor still open */
EXEC SQL FETCH emp_cursor INTO ...
위의 경우가 잘못된것은 커서가 열려있는 상태에서 다른 커서를 열려고 하기때문에 생기는
문제이다. 이를 해결하고자 한다면, 열려있는 커서를 닫고 다시 커서를 열어서 사용하는
방법으로 해결 할 수 있다.
...

EXEC SQL CLOSE emp_cursor; -- close cursor first
strcpy(db_name, "oracle2");
EXEC SQL OPEN emp_cursor;
EXEC SQL FETCH emp_cursor INTO ...
▶ Dynamic SQL
Dynamic SQL은 커서제어와 비슷하게 AT절을 사용하여 데이터베이스와 연결을 시도한다.
3가지 방법으로 연결하여 사용하는 방법을 예제코드를 살펴보도록 하자.
<Method 1>
EXEC SQL AT :db_name EXECUTE IMMEDIATE :sql_stmt;
<Method 2>
EXEC SQL AT :db_name DECLARE sql_stmt STATEMENT;
EXEC SQL PREPARE sql_stmt FROM :sql_string;
EXEC SQL EXECUTE sql_stmt;
<Method 3>
EXEC SQL AT :db_name DECLARE sql_stmt STATEMENT;
EXEC SQL PREPARE sql_stmt FROM :sql_string;
EXEC SQL DECLARE emp_cursor CURSOR FOR sql_stmt;
EXEC SQL OPEN emp_cursor ...
EXEC SQL FETCH emp_cursor INTO ...
EXEC SQL CLOSE emp_cursor;
▶ Multiple Explicit Connections
아래의 예제처럼 2개의 다른 데이터베이스에 AT절을 이용하여 연결할 수 있다.
/* declare needed host variables */
char username[10] = "scott";
char password[10] = "tiger";
char db_string1[20] = "NYNON1";
char db_string2[20] = "CHINON";
...

/* give each database connection a unique name */
EXEC SQL DECLARE DB_NAME1 DATABASE;
EXEC SQL DECLARE DB_NAME2 DATABASE;
/* connect to the two nondefault databases */
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT DB_NAME1 USING :db_string1;
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT DB_NAME2 USING :db_string2;
아래의 예제는 DB Name과 Db_String을 입력받아 다중으로 데이터베이스에 연결하는
예제 코딩을 보여주고 있다.
/* declare needed host variables */
char username[10] = "scott";
char password[10] = "tiger";
char db_name[20];
char db_string[20];
int n_defs = 3; /* number of connections to make */
...

for (i = 0; i < n_defs; i++)
{
/* get next database name and OracleNet string */
printf("Database name: ");
gets(db_name);
printf("OracleNet) string: ");
gets(db_string);
/* do the connect */
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT :db_name USING :db_string;
}
같은 데이터베이스 이름으로 여러번 연결하기 예제

strcpy(db_string, "NYNON");
for (i = 0; i < ndefs; i++)
{
/* connect to the nondefault database */
printf("Database name: ");
gets(db_name);
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT :db_name USING :db_string;
}
...
2-2) Implicit Connections
Implicit 연결법은 쿼리에서 데이터베이스 link를 이용하여 원하는 데이터 베이스에 연결하여
데이터를 취득해오는 방법을 이야기 한다.
▶ Single Implicit Connections
아래와 같이 데이터베이스 링크를 생성해서 , 생성된 링크를 이용하여 SQL을 작성하고
취득하고자하는 데이터를 취득하는 것이다.
EXEC SQL CREATE DATABASE LINK db_link
CONNECT TO username IDENTIFIED BY password
USING ’NYNON’;
아래의 예제는 데이터베이스 링크를 이용하여 원격의 데이터베이스 서버의 EMP테이블에서 데이터
를취득하는 예제이다.
EXEC SQL SELECT ENAME, JOB INTO :emp_name, :job_title
FROM emp@db_link
WHERE DEPTNO = :dept_number;
데이터베이스 링크를 쉽게 참조하기 위해서, 아래와 같이 SYNONYM을 생성할 수 있다.
EXEC SQL CREATE SYNONYM emp FOR emp@db_link;

SYNONYM을 생성하고 아래와 같은 쿼리를 이용하여 원격에 있는 데이터베이스의 EMP 테이블
에서 데이터를 취득한다.
EXEC SQL SELECT ENAME, JOB INTO :emp_name, :job_title
FROM emp
WHERE DEPTNO = :dept_number;

이것은 위치 EMP테이블에 대한 위치 투명성을 제공한다.
▶ Multiple Implicit Connections
아래의 예제는 동시에 원격 데이터베이스 서버에 접속하는 예제이다.
우선, 두개의 데이터베이스 링크를 생성하고 SYNONYM을 생성한다.
EXEC SQL CREATE DATABASE LINK db_link1
CONNECT TO username1 IDENTIFIED BY password1
USING ’NYNON’;
EXEC SQL CREATE DATABASE LINK db_link2
CONNECT TO username2 IDENTIFIED BY password2
USING ’CHINON’;
EXEC SQL CREATE SYNONYM emp FOR emp@db_link1;
EXEC SQL CREATE SYNONYM dept FOR dept@db_link2;
그다음, 원격의 데이터베이스 서버의 EMP와 DEPT테이블에서 쿼리를 할 수 있다.
EXEC SQL SELECT ENAME, JOB, SAL, LOC
FROM emp, dept
WHERE emp.DEPTNO = dept.DEPTNO AND DEPTNO = :dept_number;



출처 - http://younbok.egloos.com/9342732

:

[소스] PRO*C의 기본구조와 Indicator의 사용예

Language/Pro*C 2015. 5. 20. 15:37

Pro*c/c++에서 사용되는 기본적인 구조와 Indicator의 사용예를 예제를 통해서 간단히 이해

할 수 있을것으로 본다. 이 예제에서 Indicator는 임무(comm)컬럼의 NULL여부를 판단하기위한
지시자로서 사용되었다. 소스에서는 간단한 주석을 첨부했으므로 이해하는데 그리 어렵지는
않을 것으로 생각된다.
/******************************************************************************
* sample1.pc
*
* 사원번호를 입력받아 사원이 이름, 봉급,임무를 취득
* 임무가 NULL인지를 판단하기위해서 indicator 변수를 사용한다.
******************************************************************************
*
* 선 생성 되어야할 Table 구조
* CREATE TABLE DEPT
* (
* DEPTNO NUMBER(2) NOT NULL,
* DNAME VARCHAR2(14),
* LOC VARCHAR2(13));
*
* CREATE TABLE EMP
* (
* EMPNO NUMBER(4) NOT NULL,
* ENAME VARCHAR2(10),
* JOB VARCHAR2(9),
* MGR NUMBER(4),
* HIREDATE DATE,
* SAL NUMBER(7,2),
* COMM NUMBER(7,2),
* DEPTNO NUMBER(2));
*
*****************************************************************************/
#include <stdio.h>
#include <string.h>
//////////////////////////////////////////////////////////////////////
// VARCHAR 길이 설정
#define UNAME_LEN 20
#define PWD_LEN 40
//////////////////////////////////////////////////////////////////////
// MODE=ORACLE인경우 Declare Section이 필요하지 않다.
// 변수선언
VARCHAR username[UNAME_LEN];
//////////////////////////////////////////////////////////////////////
// varchar가 소문자도 가능하다.
varchar password[PWD_LEN];
//////////////////////////////////////////////////////////////////////
// SELECT문의 결과를 위한 구조체 선언
//////////////////////////////////////////////////////////////////////
struct {
VARCHAR emp_name[UNAME_LEN];
float salary;
float commission;
} emprec;
//////////////////////////////////////////////////////////////////////
// indicator 선언
struct
{
short emp_name_ind;
short sal_ind;
short comm_ind;
} emprec_ind;
//////////////////////////////////////////////////////////////////////
// 입력 호스트 변수 선언
int emp_number;
int total_queried;
//////////////////////////////////////////////////////////////////////
// SQL Communications Area을 포함한다.
// EXEC SQL INCLUDE SQLCA를 사용가능하다.
#include <sqlca.h>
//////////////////////////////////////////////////////////////////////
// 에러처리 함수
void sql_error();
void main()
{
char temp_char[32];
//////////////////////////////////////////////////////////////////////
// 오라클 연결
//////////////////////////////////////////////////////////////////////
// VARCHAR에 사용자이름 복사처리
strncpy((char *) username.arr, "SCOTT", UNAME_LEN);
//////////////////////////////////////////////////////////////////////
// VARCHAR의 길이 설정
username.len = strlen((char *) username.arr);
//////////////////////////////////////////////////////////////////////
// 비밀번호 복사처리
strncpy((char *) password.arr, "TIGER", PWD_LEN);
password.len = strlen((char *) password.arr);
//////////////////////////////////////////////////////////////////////
// 에러핸들러로 sql_error()을 등록
EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--n");
//////////////////////////////////////////////////////////////////////
// 오라클에 연결시 에러가 발생하면 sql_error()을 호출한다.
EXEC SQL CONNECT :username IDENTIFIED BY :password;

printf("nConnected to ORACLE as user: %sn", username.arr);

//////////////////////////////////////////////////////////////////////
// 반복하면서 Employee의 결과를 취득
total_queried = 0;
for (;;)
{
//////////////////////////////////////////////////////////////////////
// 결과가 1403(No data found)이 발생하면 Loop를 멈춘다.
EXEC SQL WHENEVER NOT FOUND DO break;
for (;;)
{
emp_number = 0;
printf("n 사번입력 (0 to quit): ");

//////////////////////////////////////////////////////////////////////
// 사번입력을 얻는다.
gets(temp_char);

emp_number = atoi(temp_char);

if (emp_number == 0)
break;

//////////////////////////////////////////////////////////////////////
// 입력한 사번으로 취득 DATA를 얻는다.
EXEC SQL SELECT ename, sal, NVL(comm, 0)
INTO :emprec INDICATOR :emprec_ind
FROM EMP
WHERE EMPNO = :emp_number;

//////////////////////////////////////////////////////////////////////
// 결과를 출력한다.
printf("nnEmployeetSalaryttCommissionn");
printf("--------t------tt----------n");
//////////////////////////////////////////////////////////////////////
// 출력 String Data의 마지막에 NULL-terminate를 추가한다.
emprec.emp_name.arr[emprec.emp_name.len] = '';
printf("%-8st%6.2ftt", emprec.emp_name.arr, emprec.salary);
if (emprec_ind.comm_ind == -1)
printf("NULLn");
else
printf("%6.2fn", emprec.commission);

total_queried++;
}

if (emp_number == 0) break;
printf("nNot a valid employee number - try again.n");
}

printf("nnTotal rows returned was %d.n", total_queried);

printf("nG'day.nnn");

//////////////////////////////////////////////////////////////////////
// 오라클 연결을 끊는다.
EXEC SQL COMMIT WORK RELEASE;
exit(0);
}
//////////////////////////////////////////////////////////////////////
// 에러처리 함수
//////////////////////////////////////////////////////////////////////
void sql_error(msg)
char *msg;
{
char err_msg[128];
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("n%sn", msg);

buf_len = sizeof (err_msg);

sqlglm(err_msg, &buf_len, &msg_len);

printf("%.*sn", msg_len, err_msg);

EXEC SQL ROLLBACK RELEASE;

exit(1);
}



출처 - http://younbok.egloos.com/9342733

: