論Solaris下PRO*C和OCI程序設計分析

時間:2022-03-20 02:17:00

導語:論Solaris下PRO*C和OCI程序設計分析一文來源于網友上傳,不代表本站觀點,若需要原創文章可咨詢客服老師,歡迎參考。

論Solaris下PRO*C和OCI程序設計分析

1引言

數據庫在軟件開發中的應用越來越廣泛,其中,Oracle可說是性能最強大、最穩定的數據庫之一,大量的軟件開發選擇了Oracle。在開發語言的選擇上,C語言以其靈活、高效吸引了大批的軟件開發人員論文。這兩者的強強聯合也必具有較高的性能,在實際中有廣泛的應用。這就是PRO*C和OCI程序設計。

Oracle常常應用在服務器中,solaris又是服務器的首選平臺,因此,本文主要介紹pro*C和oci程序設計在Solaris平臺上的應用和實現,對在Windows平臺和Linux平臺上的應用和實現也可作為。本文所采用的開發環境為Solaris2.8、Oracle8.1.7。

2PRO*C程序設計

PRO*C是Oracle提供的應用程序專用開發工具,它以C語言為宿主語言,能在C程序中嵌入SQL語句,進行數據庫操作。這種嵌入式的SQL語句容易掌握,適合初學者。

2.1設置開發環境

(1)C編譯器

Solaris系統中常用的C語言編譯器是GCC,是GNU組織的免費C編譯器,一般Linux版本中缺省都安裝有GCC,UNIX系統中有的并不自帶,因此需要手動安裝,本文所采用的GCC版本為3.2。

(2)PRO*C預編譯器

PRO*C使用預編譯技術,預編譯器將源程序中的SQL語句轉換為標準的Oracle庫函數調用,從而生成C源程序,再經C編譯器編譯、鏈接后生成可執行文件。這個預編譯器是Oracle自帶的。

(3)C語言頭文件和函數庫。

Oracle安裝程序將這些文件安裝在$ORACLE_HOME/precomp目錄下。

2.2開發PRO*C程序

(1)說明SQL通訊區

SQL通訊區用來記錄執行每一個嵌入SQL語句的狀態信息,通過在函數體外使用下列語句實現:

#include<sqlca.h>或者EXECSQLINCLUDEsqlca;

(2)聲明宿主變量,即C變量

這些變量是應用程序與Oracle通信的橋梁,應用程序的輸入數據通過C變量傳遞給Oracle,反之,Oracle的輸出數據又通過C變量傳遞給應用程序。舉例如下:

EXECSQLBEGINDECLARESECTION;

charszUsername[16];

VARCHARvarPassword[16];

char*szStmt1="CREATETABLEUSERS(USERNAMEVARCHAR2(15)NOTNULL,PASSWORD

VARCHAR2(15)NOTNULL)";

char*szStmt2="SELECTPASSWORDFROMUSERSWHEREUSERNAME=''''chen''''";

EXECSQLENDDECLARESECTION;

值得注意的是:在SQL語句中使用C變量時,前面需加冒號,例如上面的變量應表示為:szUsername。其中,VARCHAR為C擴展數據類型,預編譯時,PRO*C預編譯器將它擴展為一個C結構類型struct{

unsignedshortlen;

unsignedchararr[16];

}varNo;

在SQL語句中使用VARCHAR類型變量時,只需指出結構名稱varPassword就可,但在C語句中使用VARCHAR類型變量時,必須具體說明所操作變量的結構元素名稱是varPassword.len還是varPassword.arr。另外,如果用VARCHAR類型變量做函數參數的話,只能用指針形式。

(3)連接數據庫

EXECSQLCONNECT:username/password@DBname;

通過sqlca.sqlcode的值來判斷連接數據庫成是否功。

(4)執行SQL語句(分為靜態SQL語句和動態SQL語句)

靜態SQL語句是在開發應用程序時就已經明確了的數據庫操作,如:

EXECSQLSELECTpasswordINTO:szPasswordFROMUSERSWHEREusername=:szUsername;

動態SQL語句是在運行時由外部數據提供的,不能直接在C程序中嵌入SQL語句,但可以調用放在一個字符串變量里的SQL語句,最簡單的方法是:EXECSQLEXECUTEIMMEDIATE:szStmt1;但這樣執行的SQL語句不能實現查詢,實現查詢可用下列方法:

EXECSQLPREPAREselect_stmtFROM:szStmt2;

EXECSQLEXECUTEselect_stmtINTO:szPassword;

如果不再需要已準備好的語句,應釋放:EXECSQLDEALLOCATEPREPAREselect_stmt;

(5)提交或回滾所做的數據庫處理,并退出數據庫

回滾:EXECSQLROLLBACKWORKRELEASE;

提交:EXECSQLCOMMITWORKRELEASE;

注意語句中的RELEASE選項,它要求關閉所有打開的游標,之后斷開與數據庫服務器的連接。

2.3生成可執行文件

在Solaris平臺下可通過命令方式對PRO*C源程序進行預編譯,下列命令只列出了最常用的預編譯選項:#prociname=example.cINCLUDE=pathCODE=ANSI_CMODE=ANSICPP_SUFFIX=cc

SQLCHECK=SEMANTICSUSERID=username/password@DBname

預編譯后的example.cc文件就可以當作普通的C源文件來進行處理了。

#gcc-oexampled–I.-I/oracle/product/8.1.7/precomp/publicexample.cc

最終生成的exampled文件就是我們的可執行文件。

3OCI程序設計

OCI(OracleCallInterface)是由頭文件和庫函數等組成的一套Oracle數據庫應用程序編程接口工具,OCI程序實質上就是用高級語言寫的程序,其特點是內部含有對OCI子函數庫的調用。

OCI程序對開發環境的要求相對較低,只要有C語言的OCI開發工具包和C編譯器就可以,程序設計相比PRO*C復雜了點。

3.1創建和初始化OCI環境

首先要在源程序中包含OCI頭文件:#include<oci.h>

OCI環境即OCI函數的工作環境,在調用其他函數之前必須先調用OCIInitialize()和OCIEnvInit()函數創建和初始化OCI環境,其他OCI函數要在這個環境中才能執行。

先定義變量:OCIEnv**m_envhp;

OCIError*m_errhp;

OCIServer*m_srvhp;

OCISvcCtx*m_svchp;

OCIStmt*m_stmthp;

OCIInitialize((ub4)OCI_DEFAULT,(dvoid*)0,(dvoid*(*)(dvoid*,size_t))0,

(dvoid*(*)(dvoid*,dvoid*,size_t))0,(void(*)(dvoid*,dvoid*))0);

OCIEnvInit((OCIEnv**)&m_envhp,OCI_DEFAULT,(size_t)0,(dvoid**)0);

其中m_envhp為輸出參數,是一個指向OCI環境句柄的指針,OCI_DEFAULT是OCI環境的初始化模式。OCIEnvInit()函數中的size_t類型變量為分配給用戶的內存數量,dvoid**類型變量指向用戶的內存區域,該區域的大小等于size_t類型變量。

OCI函數中,大量使用OCI定義的數據類型和宏,其定義可$ORACLE_HOME/rdbms/demo目錄下的oci.h頭文件。

3.2申請句柄

句柄是指向OCI庫所分配的內存區域的指針,該內存區域中的數據由OCI庫維護,程序可通過句柄訪問其中的數據。下面是應用程序中最常用的幾個句柄:

OCIHandleAlloc((dvoid*)m_envhp,(dvoid**)&m_errhp,OCI_HTYPE_ERROR,

(size_t)0,(dvoid**)0);

OCIHandleAlloc((dvoid*)m_envhp,(dvoid**)&m_srvhp,OCI_HTYPE_SERVER,

(size_t)0,(dvoid**)0);

OCIHandleAlloc((dvoid*)m_envhp,(dvoid**)&m_svchp,OCI_HTYPE_SVCCTX,

(size_t)0,(dvoid**)0);

OCIHandleAlloc((dvoid*)m_envhp,(dvoid**)&m_stmthp,OCI_HTYPE_STMT,

(size_t)0,(dvoid**)0);

其中m_errhp為新申請的句柄,m_envhp為它的父環境句柄,OCI_HTYPE_ERROR為句柄類型,表示這是一個錯誤報告句柄,OCI_HTYPE_SERVER表示服務器句柄,OCI_HTYPE_SVCCTX表示服務環境句柄,OCI_HTYPE_STMT表示語句句柄。

存儲在句柄中的數據稱為句柄屬性,所有OCI句柄都具有屬性,可以調用OCIAttrGet()和OCIAttrSet()函數來讀取、設置句柄屬性。

3.3連接服務器建立會話

首先調用OCIServerAttach(m_srvhp,m_errhp,(text*)"",strlen(""),OCI_DEFAULT);函數建立與指定服務器的連接,text*類型變量為空,表示連接默認數據庫服務,OCI_DEFAULT表示應用程序的操作模式為阻塞模式,在這種方式下,只有當OCI調用完成后才將控制權返回給客戶端應用程序。

然后調用OCILogon(m_envhp,m_errhp,&m_svchp,(text*)m_szUser,strlen(m_szUser),

(text*)m_szPassword,strlen(m_szPassword),(text*)m_szDbName,strlen(m_szDbName));建立數據庫會話。此函數隱含申請服務器句柄和用戶會話句柄,登錄后,句柄是只讀的,不能再設置句柄屬性。

3.4執行SQL語句并處理數據

將要執行的SQL語句copy到szSqlStr字符串中,snprintf(szSqlStr,sizeof(szSqlStr),"selectPASSWORDfromUSERSwhereUSERNAME=’chen’");

執行下列語句:

OCIStmtPrepare(m_stmthp,m_errhp,(text*)szSqlStr,(ub4)strlen(szSqlStr),

(ub4)OCI_NTV_SYNTAX,(ub4)OCI_DEFAULT);//準備SQL語句

OCIDefine*defnp0=(OCIDefine*)0;//定義輸出變量

OCIDefineByPos(m_stmthp,&defnp0,m_errhp,1,(dvoid*)szUSERNAME,100,SQLT_STR,

(dvoid*)0,(ub2*)0,(ub2*)0,OCI_DEFAULT);//綁定變量

OCIStmtExecute(m_svchp,m_stmthp,m_errhp,(ub4)1,(ub4)0,(OCISnapshot*)NULL,

(OCISnapshot*)NULL,(ub4)OCI_DEFAULT);//執行SQL語句

3.5結束會話斷開數據庫連接

OCILogoff(m_svchp,m_errhp);

3.6斷開與數據源的連接,釋放句柄

OCIServerDetach(m_srvhp,m_errhp,OCI_DEFAULT);//斷開與數據源的連接

OCIHandleFree((dvoid*)m_stmthp,OCI_HTYPE_STMT);//釋放句柄

OCIHandleFree((dvoid*)m_svchp,OCI_HTYPE_SVCCTX);

OCIHandleFree((dvoid*)m_srvhp,OCI_HTYPE_SERVER);

OCIHandleFree((dvoid*)m_errhp,OCI_HTYPE_ERROR)

3.7生成可執行文件(兩種)

(1)同普通的C程序:

#gcc-oexampled–I.–I$(ORACLE_HOME)/precomp/publicexample.c

(2)利用Oracle自帶的Make文件:

首先將$ORACLE_HOME/rdbms/demo/demo_rdbms.mk文件copy到OCI源程序所在的目錄,將源文件編譯為目標文件:#gcc–cexample.o-I$(ORACLE_HOME)/rdbms/demo

-I$(ORACLE_HOME)/network/public-I$(ORACLE_HOME)/rdbms/public/example.c

然后用命令:#make-fdemo_rdbms.mkbuildOBJS=example.oEXE=exampled,exampled就為生成的可執行文件。

4二者的比較

PRO*C程序的最大優點是簡單易學,另外,因為PRO*C程序是把SQL語句翻譯成相應的Oracle庫函數調用,因此大大提高了應用程序的執行速度。

OCI程序使開發人員能使用已熟悉的C語言編程技術,通過Oracle的OCI函數調用快速開發應用程序,能充分發揮C語言的特點,使開發人員對程序設計和運行控制更加靈活,開發的應用程序具有更強的數據處理能力和更大的靈活性。

5結束語

文章從開發環境、開發流程、編譯三個方面分別詳細了PRO*C和OCI程序設計的方法,并對兩者的性能進行了比較。希望能為廣大的機技術工作者提供參考。由于OCI程序設計相對復雜,以上所述僅是用來實現基本的數據庫操作,若要實現更復雜的應用,需要做大量的實踐操作,積累經驗。文中舉例的程序,都是在實際中編譯通過了的,更有說服力。