学习《实战OpenGL》之OCI接口连接Oracle数据库初探

来源:互联网 发布:淘宝只有退货没有换货 编辑:程序博客网 时间:2024/06/06 05:46

    在安装好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.0VS2008显示数据的控件不同,方法函数也不一样SetTextMatrix()应为SetItemText()

设置宽度setColWidth()改为SetColumnWidth()

有的函数没有如SetRows() SetCols();

经过改动,程序运行无错,到执行完SQL语句一切正常,但是list control貌似显示不出来,应为该练习主要学习与Oracle的连接,显示部分就没作深究了。

 



 

 

原创粉丝点击