在Visual C++下開發Oracle庫介面主要有兩種方法。一種方法是利用Visual C++提供的多種資料庫訪問技術,如開放資料庫連接ODBC、熟據存取對象DAO、對象串連和嵌入資料庫OLE DB和ActiveX資料對象ADO等。另一種方法是在Visual C++中嵌入SQL語句,這就是所指的Pro*C/C++(本文簡稱PROC)。前一種方法由於有MFC 強大的類庫支援,熟悉VC編程時則實現方便,且可移植性強;但是,與PROC 相比,應用程式需要經過兩層才能和資料庫通訊介面建立聯絡,編程相對複雜,執行效率相對較低。PROC支援嵌入式PL/SQL
塊等直接調用Oracle 庫,將過程化語言和非過程化語言相結合,形成一種更強的開發工具,可開發出滿足各種複雜要求的最佳化應用程式,執行效率高。適合熟悉Oracle技術的人員應用。但是用PROC 開發出的應用程式無法向異構資料庫平台移植。
本文詳細描述實際利用PROC在Visual C++環境下開發Oracle資料庫介面程式的方法和具體操作步驟,並給出了編程執行個體。敘述以Visual C++ 6.0版和Oracle8i版為例,其他版本可根據實際情況變更。
幾個特殊檔案
PROC在VC下開發Oracle庫介面時,需要用到幾個特殊檔案。
1、PROC的可執行檔PROCUI. EXE
用Oracle_HOME代表Oracle安裝後的根目錄,當其以預設方式安裝在電腦的D盤時,則Oracle_HOME位置是D: / Oracle。這時PROC的可執行檔在Oracle_HOME / Ora81 / BIN / PROCUI. EXE,對預設安裝即在D: / Oracle / Ora81 / BIN / PROCUI. EXE。
2、Oracle支援SQL在VC環境的庫檔案OraSQL8. LIB
根據以上約定,OraSQL8. LIB檔案在Oracle_HOME / Ora81 / PRECOMP / LIB / MSVC / OraSQL8.LIB,對預設安裝即在D: / Oracle / Ora81 / PRECOMP / LIB / MSVC / OraSQL8.LIB。
3、Oracle支援SQL在VC環境的標頭檔
根據以上約定,標頭檔 *.h在Oracle_HOME / Ora81 / PRECOMP / PUBLIC / *.h,對預設安裝即在D: / Oracle / Ora81 / PRECOMP / PUBLIC / *.h。
*.h 是標頭檔的總稱,通常有十多個,具體內容可在指定路徑下查到。
將PROC整合到VC環境中
為了方便完成用PROC在VC下開發Oracle庫介面,通常將PROC整合到Visual C++ 6.0 環境中,直接在C / C++環境中使用PROC先行編譯器來先行編譯應用程式,然後進行編譯和連結,最終產生可執行程式。將PROC整合到VC環境中應完成如下工作。
1、增加PROC到Tools菜單列表
a) 運行Microsoft Visual C++ 6.0;
b) 從功能表項目Tools中選擇Customize項。為表述簡單起見,書寫成如下格式:菜單Tools/ Customize 項。以下採用類似的表達方法。此時出現Customize對話方塊;
c) 單擊Tools選項卡(或屬性頁面),用滑鼠移動“Menu contents”框捲軸到底部地區;
d) 雙擊點劃線矩形地區,在空白地區上輸入“PROC”,然後按斷行符號鍵;
e) 在“Command”框中,輸入PROC的可執行檔名。根據2.1節的說明,對預設安裝即輸入D: / Oracle / Ora81 / BIN / PROCUI. EXE;
f) 在“Arguments”框中輸入“$(TargetName)”。其作用在從菜單Tools中選擇PROC項時,VC會將當前項目名傳遞給PROC,爾後PROC會直接開啟該專案檔目錄下副檔名為 .pre的同名檔案;
g) 在“Initial directory”框中輸入“$(WkspDir)” / 單擊“Close”按鈕,完成將PROC整合到VC環境中的工作。
2、指定標頭檔路徑
為了確保VC順利完成編譯連結,需要將Oracle提供的標頭檔增加到VC環境中。指定標頭檔路徑的具體步驟如下。
a) 菜單Tools / Options項,出現“Options”對話方塊;
b) 單擊“Directories”選項卡,從“Show directories for:”列表框中選擇“Include files”;
c) 移動“Directories”框的捲軸到底部地區;
d) 雙擊點劃線矩形地區,在空白地區上輸入包含Oracle支援SQL在VC環境標頭檔的子目錄,根據2.3節的說明,對預設安裝即輸入D: / Oracle / Ora81 / PRECOMP / PUBLIC。
VC下開發Oracle介面程式過程
1、建立新工程
下面敘述中,假定建立的工程名為:Exam01。當運行Visual C++ 6.0後,操作步驟如下:
a) 菜單File / New項 / Project卡;
b) 選擇Win32 console Application 項;
c) 由瀏覽選擇或直接輸入工程將位於的路徑 / 填入建立的工程名如Exam01;
d) 單擊OK按鈕 / 依預設值單擊Finish / 單擊OK,完成建立控制台應用工程架構。
2、建立先行編譯源檔案
假定建立的先行編譯源檔案名稱為:Exam01.pc。在Visual C++ 6.0的環境下操作步驟如下:
a) 菜單Project / Add To Project 項 / New項;
b) Files 卡 / SQL script File 項;
c) Files編輯框中輸入Exam01.pc / 單擊OK;
d) 在編輯狀態下輸入Exam01.pc源檔案,或者,從其他檔案中拷貝後再修改形成Exam01. pc源檔案;
e) 選擇恰當路徑,儲存源檔案。例如,路徑為:E: / PROCW / Exam01。
3、先行編譯
通過先行編譯,將先行編譯源檔案如Exam01.pc轉換成為Exam01.c的C程式源檔案。在PROC整合到VC環境下時操作步驟如下:
a) 菜單Tools / PROC 項;
b) 當出現沒有Exam01.pre 的對話方塊時單擊OK,此時彈出PROC先行編譯對話方塊;
c) 利用菜單中的加入項或單擊“+”按鈕,將進行先行編譯的源檔案如Exam01.pc及其路徑添加到先行編譯對話方塊的Input項中,即Input項中出現E: / PROCW / Exam01 / Exam01.pc。此時在Output項中自動顯示輸出檔案如Exam01.c和路徑(必要時可修改檔案名稱和路徑),即Output項中出現E: / PROCW / Exam01 / Exam01.c;
d) 若有需要,雙擊先行編譯對話方塊的Options選項處,對彈出的Options選項對話方塊,選擇需要的先行編譯選項(一般情況下不做該步,即採用預設先行編譯選項);
e) 單擊工具條最右邊的先行編譯表徵圖,進行先行編譯;
f) 先行編譯結束,若出現詢問儲存Exam01.pre 檔案時,應選擇OK進行儲存,完成先行編譯;
g) 如果先行編譯結束,先行編譯對話方塊左邊顯示的狀態表徵圖為黃色(警告)或紅色(先行編譯失敗)時,應雙擊該標識觀察協助或出錯資訊。先行編譯失敗,應當重做4.2節中編輯工作,修改來源程式,再進行先行編譯,直到通過先行編譯。
4、編譯準備
為了使工程能通過編譯,需要將先行編譯輸出的工程源檔案和Oracle支援SQL在VC環境下的運行庫檔案加入到工程中,下面具體介紹增加這兩個檔案的步驟。
1) 將先行編譯的輸出檔案加入工程
a) 菜單Project / Add To Project 項 / Files 項;
b) 在檔案對話方塊中選擇正確路徑(見4.2節和4.3節),選定先行編譯輸出的檔案如Exam01.c,單擊“開啟”按鈕,即將先行編譯輸出的工程源檔案加入工程。
2) 將運行庫檔案加入工程
a) 菜單Project / Add To Project 項 / Files 項;
b) 將檔案對話方塊的檔案類型改為“所有檔案”;
c) 路徑選為Oracle_HOME / Ora81 / PRECOMP / LIB / MSVC;
d) 選擇OraSQL8.LIB檔案,單擊“開啟”鈕,完成將運行庫檔案加入工程。
5、編譯連結
a) 按F7鍵或單擊編譯表徵圖,對工程進行編譯連結。如果沒有出現錯誤,則通過編譯連結,產生可執行檔如Exam01.exe ;
b) 如果編譯連結出現錯誤,返回到4.2節,選擇相應的先行編譯源檔案如Exam01.pc進行修改並儲存;然後按4.3節做先行編譯,先行編譯通過後,單擊OK按鈕用新的 .c檔案代替原來的C源檔案;此時重新按F7鍵進行編譯連結,直到排除所有錯誤,產生可執行檔如Exam01.exe。
6、運行工程
a) 按Ctrl_F5鍵或單擊執行表徵圖運行工程Exam01.exe。按工程中的提示,逐步正確運行;
b) 如果運行中出現錯誤,返回到4.2節修改相應先行編譯源檔案,再按4.3節做先行編譯,按4.5節進行編譯連結,產生新的可執行檔,然後重新運行工程,直到正確實現工程的規定任務。
編程舉例
1、程式內容
一般SQL嵌入式程式主要有說明、包含標頭檔、子程式聲明、主程式和子程式等部分組成,在主程式中調用有關子程式。必備的子程式通常有串連到資料庫子程式、斷開資料庫子程式、錯誤處理子程式和完成某項具體事務(如查詢、插入、修改、刪除等)的工作子程式。
2、程式舉例
下面是一完整的可通過先行編譯、編譯連結和啟動並執行樣本程式。
/* exam01.pc 開發Oracle介面程式舉例 */
/* 說明:本程式介紹用PROC開發Oracle庫介面的編程特點。通過向AUTHS
* 表輸入作家代碼,查詢作家姓名及工資。運行前應建表、插入資料並提交。*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* 包含SQL通訊區,它用於處理錯誤。*/
#include <sqlca.h>
void connect(); /* 串連到Oracle Server */
void disconnect(); /* 斷開到Oracle Server的串連 */
void sql_error(char *); /* 處理錯誤控制代碼 */
void select(); /* 查詢子程式 */
extern sqlglm(char *,int *,int *);
/* 主程式 */
void main()
{
/* 安裝錯誤處理控制代碼 */
EXEC SQL WHENEVER SQLERROR DO sql_error("Oracle錯誤--/n");
/* 串連到資料庫 */
connect();
/* 執行查詢 */
select();
/* 斷開資料庫連接 */
disconnect();
}
/* 子程式 */
/* 串連子程式 connect() */
void connect()
{
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR username[10], password[10], server[10];
EXEC SQL END DECLARE SECTION;
/* 輸入使用者名稱、口令以及伺服器名 */
printf("/n輸入使用者名稱:");
gets(username.arr);
username.len=(unsigned short)strlen((char *)username.arr);
printf("/n輸入口令:");
gets(password.arr);
password.len=(unsigned short)strlen((char *)password.arr);
printf("/n輸入伺服器名:");
gets(server.arr);
server.len=(unsigned short)strlen((char *)server.arr);
/* 串連到Oracle伺服器上 */
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :server;
printf("/n以使用者%s成功地串連到了伺服器%s上!/n", username.arr, server.arr);
}
/* 中斷連線子程式 disconnect() */
void disconnect()
{
char temp;
printf("/n是否在中斷連線前提交所有事務? (Y/N)");
scanf("%c", &temp);
fflush(stdin);
if(temp !='Y' && temp != 'y')
{
/* 回退事務,中斷連線。 */
EXEC SQL ROLLBACK WORK RELEASE;
printf("/n回退事務,中斷連線,退出程式!/n/n");
}
else
{
/* 提交事務,中斷連線。 */
EXEC SQL COMMIT WORK RELEASE;
printf("/n提交事務,中斷連線,退出程式!/n/n");
exit(1);
}
}
/* 查詢子程式 select()
* 首先輸入作家代碼,然後查詢作家姓名和工資。*/
void select()
{
EXEC SQL BEGIN DECLARE SECTION;
char author_code[8], name[10];
float salary;
short salary_ind;
EXEC SQL END DECLARE SECTION;
printf("/n輸入作家代碼: ");
gets(author_code);
/* 查詢作家姓名和工資 */
EXEC SQL SELECT name, salary INTO :name, :salary:salary_ind
FROM auths
WHERE author_code = :author_code;
/* 根據指示變數的值來確定該作家的工資是否為空白。*/
if (salary_ind ==0)
{
printf("/n作家代碼/t作家姓名/t作家工資/n");
printf("--------/t--------/t--------/n");
printf("%8s/t%8s/t%8.2f/n", author_code, name, salary);
}
else
{
printf("作家%s的工資未錄入,為空白值!/n", name);
}
}
/* 錯誤處理子程式 sql_error() */
void sql_error(char *msg)
{
char err_msg[128];
size_t buf_len, msg_len;
/* 出現SQL錯誤,繼續往下執行。 */
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("/n%s/n", msg);
buf_len=sizeof(err_msg);
/* 調用函數sqlglm()獲得錯誤訊息。 */
sqlglm(err_msg, &buf_len, &msg_len);
printf("%.*s/n", msg_len, err_msg);
/* 回退事務,中斷連線,退出程式。 */
EXEC SQL ROLLBACK RELEASE;
exit(EXIT_FAILURE);
}
3、建表和插入資料記錄
上述樣本程式如要正確運行,還需以Oracle庫的合法使用者登入,並建立AUTHS表和插入一些資料記錄。建表檔案、建表命令和插入資料記錄的樣本命令如下所述。這裡敘述的工作完成後,上節產生的可執行檔才能正確運行。
REM 以下為建表檔案auths.SQL
DROP TABLE auths CASCADE CONSTRAINTS
/
CREATE TABLE auths(
AUTHOR_CODE VARCHAR2(8) NOT NULL,
NAME VARCHAR2(10),
BIRTHDATE DATE,
ENTRY_DATE_TIME DATE,
SALARY NUMBER(7,2),
remark VARCHAR2(255))
/
REM 下一行為在PL/SQL環境中運行建表檔案的命令
REM @ E: / PROCW / Exam01 / auths.sql
REM 下一行為在PL/SQL環境中向auths表插入資料的命令,插入後應提交(COMMIT)!
REM INSERT INTO auths(author_code,name,salary) VALUES('A00001','王達琳',1200);