ProCプログラムのOracleプリコンパイル
Oracleプリコンパイラとは、高水準ソース・プログラムで埋込みSQL文を使用可能にするプログラミング・ツールです。図1-1のように、プリコンパイラはソース・プログラムを入力として受け入れ、埋込みSQL文を標準Oracleランタイム・ライブラリ・コールに変換して、通常の方法でコンパイル、リンクおよび実行できる変更済ソース・プログラムを生成します。

Oracleデータベースからempテーブルのデータをフェッチするサンプル例
test_p1.pc
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/* SQLアクセス用定数(テスト用のためハードコーディング)*/
#define ORAUSER "hr"
#define ORAPASSWD "hr"
#define ORASYSID_T "atp_low"
/* SQLアクセス用変数(いわゆるホスト変数)宣言部 */
/* "h_"始まりの変数はselectに利用 */
EXEC SQL BEGIN DECLARE SECTION;
varchar username[20];
varchar password[20];
varchar systemid[20];
int deptno; /* 部署番号 */
int empno; /* 従業員番号 */
char ename[50]; /* 従業員名 */
float sal; /* 給与 */
EXEC SQL END DECLARE SECTION;
/* ProCプリコンパイラ用ヘッダファイル宣言 */
EXEC SQL INCLUDE sqlca.h;
/******************************/
/* ここからメイン関数 */
/* メイン関数内での流れ */
/* 1.変数定義(ホスト変数についてはグローバル定義) */
/* 2.値の初期化 */
/* 3.DBコネクト */
/* 4.select文の発行 */
/* 5.カーソルオープン */
/* 6.フェッチ実行 */
/* 7.カーソルクローズ */
/* 8.DB切断(コミット) */
/******************************/
int main(int argc, char *argv[])
{
/* フェッチ時のカーソルループ用変数 */
int i;
/* ホスト変数初期化 */
memset(&username, 0x00, sizeof(username));
memset(&password, 0x00, sizeof(password));
memset(&systemid, 0x00, sizeof(systemid));
deptno = 0;
empno = 0;
sal = 0.0;
memset(&ename, 0x00, sizeof(ename));
/* oracleへの接続(SQLアクセス用変数に定数をセット) */
strcpy(username.arr, ORAUSER);
username.len = strlen(username.arr);
strcpy(password.arr, ORAPASSWD);
password.len = strlen(password.arr);
strcpy(systemid.arr, ORASYSID_T);
systemid.len = strlen(systemid.arr);
/* 例外宣言→errorptへ飛ぶ */
EXEC SQL WHENEVER SQLERROR GOTO errorpt;
printf("user: %s, password: %s 接続開始します\n",
username.arr,password.arr);
/* 接続 */
EXEC SQL CONNECT :username
IDENTIFIED BY :password
AT :systemid;
if (sqlca.sqlcode != 0) {
printf("接続エラー: %s\n", sqlca.sqlerrm.sqlerrmc);
return 1;
}
printf("データベースに接続しました。\n");
/* カーソルを宣言 */
EXEC SQL AT :systemid DECLARE emp_cursor CURSOR FOR
SELECT empno, ename, sal FROM EMP WHERE deptno = 60;
/* ユーザー入力: 部署番号
printf("部署番号を入力してください: ");
scanf("%d", &deptno);*/
/* カーソルをオープン */
EXEC SQL OPEN emp_cursor;
if (sqlca.sqlcode != 0) {
printf("カーソルのオープンに失敗しました: %s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
return 1;
}
/* カーソルからデータをFETCH */
while (1) {
EXEC SQL FETCH emp_cursor INTO :empno, :ename, :sal;
if (sqlca.sqlcode == 100) {
/* データがもう存在しない場合 */
printf("すべてのデータを取得しました。\n");
break;
} else if (sqlca.sqlcode != 0) {
printf("FETCHエラー: %s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL CLOSE emp_cursor;
// EXEC SQL ROLLBACK WORK RELEASE;
return 1;
}
/* データの表示 */
printf("従業員番号: %d, 名前: %s, 給与: %.2f\n", empno, ename, sal);
}
/* カーソルをクローズ */
EXEC SQL CLOSE emp_cursor;
/* トランザクションをコミット */
//EXEC SQL COMMIT WORK RELEASE;
printf("処理が完了しました。\n");
return 0;
/* error時の処理 */
errorpt:
printf("\n\n%-79s \n",sqlca.sqlerrm.sqlerrmc);
EXEC SQL WHENEVER SQLERROR CONTINUE;
}
ハンドでコンパイル
1)プリコンパイル(pcファイルをcファイルにする)
proc iname=test_p1.pc oname=test_p1.c sqlcheck=full
2)オブジェクトファイルを生成する
gcc -c test_p1.c -I $ORACLE_HOME/precomp/public
3)実行ファイル作成
gcc -o test_p1 test_p1.o -L$ORACLE_HOME/lib -lclntsh
4)実行
./test_p1
makeファイルでコンパイル
MakeTestP1.mk
# Oracle環境の設定
#ORACLE_HOME = /u01/app/oracle/product/19.3/db1 # Oracleのインストールパス
PROC = $(ORACLE_HOME)/bin/proc # Pro*Cプリコンパイラ
CC = gcc # Cコンパイラ
CFLAGS = -I$(ORACLE_HOME)/rdbms/public -L$(ORACLE_HOME)/lib -lclntsh
#LDLIBS = -loracle # Oracleライブラリリンクオプション
# ターゲットプログラム名
TARGET = test_p1
# ソースファイル
PC_SRC = $(TARGET).pc # Pro*Cソース
C_SRC = $(TARGET).c # Pro*Cから生成されるCソース
# 生成物
OBJ = $(TARGET).o
all: $(TARGET)
# Pro*Cプリコンパイル
$(C_SRC): $(PC_SRC)
$(PROC) iname=$(PC_SRC) oname=$(C_SRC)
# Cコンパイルとリンク
$(TARGET): $(C_SRC) $(OBJ)
$(CC) $(C_SRC) -o $(TARGET) $(CFLAGS)
# クリーンアップ
clean:
rm -f $(TARGET) $(C_SRC) $(OBJ) test_p1.c *.lis

