學習《實戰OpenGL》之OCI介面串連Oracle資料庫初探

來源:互聯網
上載者:User

    在安裝好Oracle之後,開始用OCI編程。VS2008作為開發平台

    首先在安裝目錄下搜到 oci.dll oci.h oci.lib等檔案。同OpenGL一樣*.lib放到VS2008的安裝目錄下vc\lib *.h放到vc\include下,*.dll放到C:\WINDOWS/SYSTEM32下。

    照《實戰OpenGL》建立一個MFC基於對話方塊的工程。

    在stdafx.h中加上oci.h的引用:#include <oci.h> 其他標頭檔會由oci.h進行調用。

添加變數包括OCI串連資料庫的各種控制代碼

public:OCIEnv*envhp ; //環境控制代碼OCIServer*srvhp ; //伺服器控制代碼OCISvcCtx*svchp ; //服務環壟控制代碼OCIError*errhp ; //錯誤控制代碼OCISession*authp ; //交談控制代碼OCIStmt *stmthp ; //語句控制代碼OCIDescribe  *dschp ; //描述控制代碼

添加錯誤處理函數:

void COCIExampleDlg::ErrorProc(dvoid *err, sword status){sb4 errcode ; //儲存錯誤碼CString str ;  //顯示錯誤資訊text errbuf [512] ; //儲存錯誤資訊if (status==OCI_ERROR)//如果出錯{//調用OCI的錯誤擷取函數OCIErrorGet ((dvoid*)errhp , (ub4 )1 , NULL , &errcode , errbuf , (ub4) sizeof (errbuf) , OCI_HTYPE_ERROR ) ; str.Format ("錯誤號碼:%d\n錯誤資訊:%s\n" , errcode , errbuf ) ; AfxMessageBox (str  ) ;  //彈出訊息框 , 顯示錯誤資訊}}

對話方塊中添加兩個button,一個list control 進行資料的顯示。

為了關聯對話方塊的list control在OCIExampleDlg.h中定義

// 對話方塊資料enum { IDD = IDD_OCIEXAMPLE_DIALOG };         CListCtrl    m_grid ;

在OCIExampleDlg.cpp中定義

void COCIExampleDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);DDX_Control(pDX, IDC_LIST1, m_grid);}

串連資料庫的button中寫上串連及執行資料庫的核心代碼

void COCIExampleDlg::OnBnClickedButton1(){//初始化OCI環境OCIEnvInit (& envhp , OCI_DEFAULT , 0 , 0 ) ; // ☆程式第Ⅰ部分☆《分配控制代碼與資料結構》 //分配錯誤控制代碼OCIHandleAlloc (envhp , (dvoid**)&errhp , OCI_HTYPE_ERROR , 0 , 0 ) ; //分配伺服器控制代碼ErrorProc (errhp , OCIHandleAlloc (envhp , ( dvoid** )&srvhp , OCI_HTYPE_SERVER , 0 , 0) ) ;  //分配服務環境控制代碼ErrorProc (errhp , OCIHandleAlloc (envhp, (dvoid**)&svchp ,OCI_HTYPE_SVCCTX ,0 , 0)) ;  //分配交談控制代碼ErrorProc (errhp  , OCIHandleAlloc (envhp , (dvoid**)&authp , OCI_HTYPE_SESSION , 0 , 0) ) ; //分配描述控制代碼ErrorProc (errhp  , OCIHandleAlloc ((dvoid*)envhp , (dvoid**)&dschp , OCI_HTYPE_DESCRIBE , 0 , 0) ) ;  //分配語句控制代碼ErrorProc (errhp , OCIHandleAlloc ((dvoid*)envhp , (dvoid**)&stmthp , OCI_HTYPE_STMT , 0 , 0) ) ; /* 說明:常量"OC_ HTYPE _STMT"等等是OCI控制代碼的宏定義,標明我們所分配的控制代碼的類型。 控制代碼的宏定義具體可以參考oci. h檔案中的"Handle Types"部分。 */// ☆程式第Ⅱ部分☆《串連Oracle資料庫,開始會話》 // 串連資料庫ErrorProc (errhp , OCIServerAttach (srvhp , errhp , (unsigned char*) (LPCTSTR)"ORCL" , (sb4)strlen ("ORCL") , OCI_DEFAULT) ) ; //設定服務環境的伺服器屬性ErrorProc (errhp , OCIAttrSet ((dvoid*)svchp , (ub4) OCI_HTYPE_SVCCTX , (dvoid*)srvhp , (ub4) 0 , OCI_ATTR_SERVER , errhp) ) ; // 認證使用者並且開始會話//認證使用者名稱稱ErrorProc (errhp , OCIAttrSet (authp , OCI_HTYPE_SESSION , (dvoid*) (LPCTSTR) "system" , (ub4)strlen ("system") , OCI_ATTR_USERNAME , errhp) ) ; //認證使用者密碼ErrorProc (errhp , OCIAttrSet (authp , OCI_HTYPE_SESSION , (dvoid*) (LPCTSTR) "123" , (ub4)strlen ("123") , OCI_ATTR_PASSWORD , errhp) ) ; //建立並開始一個使用者會話 , 應用程式必須在串連伺服器之後才能調用該函數ErrorProc (errhp , OCISessionBegin (svchp , errhp , authp , OCI_CRED_RDBMS , OCI_DEFAULT) ) ; //設定伺服器環境的會話屬性ErrorProc (errhp , OCIAttrSet (svchp , OCI_HTYPE_SVCCTX , (dvoid*)authp , 0 , OCI_ATTR_SESSION , errhp) ) ; /*☆程式第Ⅲ部分☆《執行SQL》 這一部分比較如複雜。在OCI環境中執行SQL的過程在第一部分的3.7.4中已經分析過了。這裡我們只示範最簡單的一個沒有條件的SELECT類型的SQL語句中OCI中的執行過程,並通過表格控制項顯示資料。首先,要在本過程的類OCIExampleDlg中加入一些public類型的變數與OCI控制代碼。*/OCIDefine*defhp[20] ; //定義控制代碼OCIBind*bidhp [20] ; //綁定控制代碼OCIParam*colhp ; //列控制代碼ub2collen[30] ; //列長度ub2coltype [30] ; //列類型text*colbuf[30] ; //存放SELECT語句選中的列資料sb2ind[30] ; //指示符變數//儲存表的欄位名稱CString ColName [50] ; //儲存表的欄位名稱CString CoIType [50] ; //儲存欄位的的資料類型text*textSQL  ;  //儲存SQL語句字串  ub4col_num ;   //存放SELECT語句選中的列數sword status;//處理SQL的第一步,準備SQL//swprintf((char*)textSQL ,"SELECT * FROM Score" ) ; textSQL=(text*)(LPCTSTR)"SELECT * FROM Score";if (status=OCIStmtPrepare (stmthp , errhp , textSQL , strlen ((char*)textSQL) , OCI_NTV_SYNTAX , OCI_DEFAULT)){ErrorProc (errhp , status) ;  //捕捉錯誤資訊return ; }//處理SOL的第三步, 執行if (status=OCIStmtExecute (svchp , stmthp , errhp , (ub4)0 , 0 , NULL , NULL , OCI_DEFAULT)){ErrorProc (errhp , status) ;  //捕捉錯誤資訊return ; }//由於我們所要處理的這個SELECT語句沒有選擇條件,即SQL語句中沒有輸入資料。因此我們就不需要處理SQL的第二步"綁定"。//處理SOL的第四步, 描述//讀取挑選清單中的項數ErrorProc (errhp , OCIAttrGet (stmthp , OCI_HTYPE_STMT , &col_num , 0 , OCI_ATTR_PARAM_COUNT , errhp ) ) ; text*namep ; //欄位名稱ub4 sizep ; //欄位名稱的字串長度texttempText[100] ; //擷取表的欄位的屬性資訊for (int i=0 ; i< (int)col_num ;  i++){//為選擇項分配參數描述符ErrorProc (errhp , OCIParamGet (stmthp , OCI_HTYPE_STMT , errhp , (void**)&colhp , ub4 (i+1)) ) ; //讀取選擇項的資料長度ErrorProc (errhp , OCIAttrGet (colhp , OCI_DTYPE_PARAM , &collen[i] , 0 , OCI_ATTR_DATA_SIZE , errhp ) ) ; //讀取選擇項的資料類型ErrorProc (errhp , OCIAttrGet (colhp , OCI_DTYPE_PARAM , &coltype[i] , 0 , OCI_ATTR_DATA_TYPE , errhp) ) ; //若這個欄位為日期型, 則把其字元寬度置為50if (coltype[i]==SQLT_DATE)collen[i] =50 ;  colbuf[i]= (text*)new text[ (int)collen[i]+1] ; //分配緩衝區//擷取欄位名稱ErrorProc (errhp , OCIAttrGet (colhp , OCI_DTYPE_PARAM , (dvoid*)&namep , (ub4*)&sizep , OCI_ATTR_NAME , errhp ) ) ; strncpy ((char*)tempText , (char*)namep , (size_t)sizep) ; tempText [sizep]= '\0' ; //將表中欄位名稱寫入表格控制項第一行m_grid.SetItemText(0 , i+1 , (const char *)tempText ) ;}//處理SQL的第五步 , 定義變數for (int i=0 ;  i< (int)col_num ;  i++){if (status=OCIDefineByPos (stmthp , &defhp[i] , errhp , i+1 , (ub1*)colbuf[i] , collen[i]+1 , SQLT_STR , &ind[i] , 0 , 0 , OCI_DEFAULT)){ErrorProc (errhp , status ) ;  return ; }}//處理SQL的第六步, 取值int row=0 ; CString tempstr ; while ((OCIStmtFetch (stmthp , errhp , 1 , OCI_FETCH_NEXT , OCI_DEFAULT))!=OCI_NO_DATA){row = row+1 ; //m_grid.SetRows (row+1 ) ;  //根據資料的行數動態設定表格控制項的最大行數tempstr.Format ("%d" , row ) ; m_grid.SetItemText (row , 0 , tempstr ) ;  //設定序號for (int i=0 ;  i< (int)col_num ;  i++){tempstr= (char*)colbuf[i] ; tempstr.TrimRight (' ') ;  //刪除右空格// 把擷取的使用者的基表的資料寫入表格控制項m_grid.SetItemText (row , i+1 , tempstr ) ;   }}}

另一個button退出的代碼

void COCIExampleDlg::OnBnClickedButton2(){OCISessionEnd (svchp , errhp , authp , (ub4) 0 ) ;  //結束會話OCIServerDetach (srvhp , errhp , OCI_DEFAULT ) ;  //斷開與資料庫的串連//釋放OCI控制代碼OCIHandleFree ((dvoid*) srvhp , OCI_HTYPE_SERVER ) ; OCIHandleFree ((dvoid*) svchp , OCI_HTYPE_SVCCTX ) ; OCIHandleFree ((dvoid*) errhp , OCI_HTYPE_ERROR ) ; OCIHandleFree ((dvoid*) authp , OCI_HTYPE_SESSION  ) ; OCIHandleFree ((dvoid*) stmthp , OCI_HTYPE_STMT  ) ; OCIHandleFree ((dvoid*) dschp , OCI_HTYPE_DESCRIBE ) ; CDialog::OnCancel();}

    代碼都完成之後,編譯出現問題

    錯誤
32 error LNK2019: 無法解析的外部符號 "extern "C" int __cdecl OCIStmtExecute(struct
OCISvcCtx *,struct OCIStmt *,struct OCIError *,unsigned int,unsigned int,struct OCISnapshot const *,struct OCISnapshot *,unsigned int)"等31個錯。

   上網查的原因應該是對應的lib檔案沒有加進來。

在.h檔案中添加

#pragma   comment(lib,  
"kpucb.lib ")

#pragma  
comment(lib,  
"oci.lib ")

#pragma  
comment(lib,  
"ociw32.lib ")

#pragma   comment(lib,  
"oraocci9.lib ")

程式即可執行。

 

註:VC6.0與VS2008顯示資料的控制項不同,方法函數也不一樣如SetTextMatrix()應為
SetItemText()

設定寬度setColWidth()改為SetColumnWidth()

有的函數沒有如SetRows() SetCols();

經過改動,程式運行無錯,到執行完SQL語句一切正常,但是list control貌似顯示不出來,應為該練習主要學習與Oracle的串連,顯示部分就沒作深究了。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.