在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。
編程舉例
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); |