C++通过ODBC连接Oracle数据库

时间:2021-02-24 21:55:03

ODBC的基本介绍

ODBC是为数据库应用程序访问关系型数据库时提供的一个统一的接口,对于不同的数据库ODBC提供了一套统一的API,使应用程序可以访问任何一种提供了ODBC驱动程序的数据库。但是ODBC只能用于关系型数据库,这就使得利用ODBC很难访问对象型数据库及其他非关系型数据库。

    这种方法也是我目前所知道的C++访问数据库的5中方法中的最简单的一种,实际上,因为所用到的开发工具是Visual C++6.0,所以更准确的说应该是MFC ODBC。

    常用的类有:CDatabase数据库类、CRecordset记录集类、CRecordView可视记录集类和CDBException异常类。

    1)CDatabase类对象建立了和数据库数据源的一个连接,通过它可以对数据库进行操作。

    2)CRecordset类对象代表从一个从数据源中获取的记录集。有两种重要的打开方式,分别为Dynaset(动态集)和Snapshot(快照集)。Snapshot提供了对数据库的静态访问,就像对数据源的某些数据进行拍照一样,是静态的数据,别的用户对数据源的数据进行添加、修改、删除的时候,快照集里面的记录不受影响,只有在调用了CRecordset的Requery函数重新查询的时候,快照集才会产生改变。而Dynaset(动态及)则提供了对数据库的动态访问,和其他用户所作的更改保持同步,当别的用户修改或删除了记录集中的记录时,会在动态集中反应出来。

   3)CRecordView类对象提供了一个表单视图来显示和操作记录集,因为CRecordView类派生于CFormView类,同时又绑定了一个记录集,从而可以利用表单视图方便地显示、修改、添加和删除记录。CRecordView采用对话框数据交换技术(DDX)和记录字段交换技术(RFX)自动实现表单控件中的数据和数据库中的字段数据的关联。

   4)CDBException类对象处理MFC ODBC访问类在操作数据库的时候发生的一样,它继承与CException类。MFC ODBC在操作数据库的时候可能会抛出CDBException异常,这些异常一定要记得处理,否则后果会很严重!

  

实际应用的过程:

    1、首先要引入MFC ODBC数据库类的定义文件,为了防止反复的#include可以在工程下的StdAfx.h头文件中使用#include文件,这样就一劳永逸,之后就不用再在其他的文件中使用#include了。

    2、对数据源进行操作之前需要定义一个CDatabase对象。代码如下:CDtabase m_db;
    3、然后利用CDatabase类的OpenEx函数建立和数据库的连接。函数原型如下:
virtual BOOL OpenEx(LPCTSTR lpszConnectString,DWORD dwOptions=0);throw(CDBExcaption,CMemoryException);
lpszConnectString:数据库的连接字符串,一般格式为:
DSN=OracleServer_Source;UID=***,PWD=***

        4、要从数据库中查询数据,就必须要使用CRecordset类对象,在对数据集进行操作之前要先定义一个CRecordset类对象,并传入CDatabase指针,方法如下:
 CRecordset rs(&m_db);或是CRecordset rs;rs.m_pDatabase=&m_db;

     5、然后要调用CRecordset的Open方法打开记录集,Open函数的原型如下:
virtual BOOl Open(UINT nOpenType=AFX_DB_USE_DEFAULT_TYPE,LPCTSTR lpszSQL=NULL,DWORD dwOptions=none);throw(CDBException,CMemoryException);
1)nOpenType为记录集的打开方式,包括dynaset,Snapshot,dunamic和forwardOnly
2)lpszSQL可以是要打开记录集的SQL语句,也可以是一个表名或是一个存储过程。
3)dwOptions一般情况下为空

    6、添加、修改和删除数据都只需用到CDatabase类的ExecuteSQl方法来执行SQL语句,ExecuteSQL函数的原型如下:
void ExecuitSQL(LPCSTR lpszSQL);throw(CDBException);
1)lpszSQL代表一个SQL语句。

代码实例(昨天研究一天做出的一个小程序中的部分关键代码)

1、建立ODBC数据源

2、我的打开数据源连接的函数OnBtnDbconnect()

void CMemoDBSDlg::OnBtnDbconnect() 
{
 // TODO: Add your control notification handler code here
 //从界面控件中获取信息更新到控件变量中
 if(!UpdateData(true))
  return;
 //检出数据库是否已经连接,如果已经连接则返回
 if(m_db.IsOpen())
 {
  AfxMessageBox("数据库已经连接");
  return;
 }
 //检查数据库配置参数
 if(m_strDBSource.IsEmpty()||m_strDBUser.IsEmpty()||m_strDBPassword.IsEmpty())
 {
  AfxMessageBox("数据库参数不能够为空");
  return;
 }
 //创建连接字符串
 CString strConnect;
 strConnect.Format("DSN=%s;UID=%s;PWD=%s",m_strDBSource,m_strDBUser,m_strDBPassword);
 //打开数据库的连接,并且捕获异常
 try
 {
  m_db.OpenEx(strConnect,CDatabase::noOdbcDialog);
 }
 catch(CDBException *ex)
 {
  AfxMessageBox(ex->m_strError
  AfxMessageBox(ex->m_strStateNativeOrigin);
 }
 catch(CMemoryException *pEx)
 {
  pEx->ReportError();
  AfxMessageBox("memory exception");
 }
 catch(CException *e)
 {
  TCHAR szError[1000];
  e->GetErrorMessage(szError,1000);
  AfxMessageBox(szError);
 }
 InitCtrlData();
}

3、获取数据

//从数据库中读取数据并显示在列表框中
void CMemoDBSDlg::InitCtrlData()
{
 try
 {
  CRecordset rs;
  rs.m_pDatabase=&m_db;
  //////////////////////////////////
  ///向成员列表控件中添加成员记录信息
  //////////////////////////////////
  CString sql="select * from family_member_tab";
  rs.Open(CRecordset::dynaset,sql);
  MessageBox("查询家庭成员的SQL成功执行");
  int id;
  CString name,date;
  while(!rs.IsEOF())
  {
   CDBVariant var;
   //获取成员ID字段值
   rs.GetFieldValue((short)0,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    id=var.m_iVal;
   var.Clear();
   //获取姓名字段值
   rs.GetFieldValue(1,name);
   //获取出生日期字段值
   rs.GetFieldValue(2,date);
   //把记录值插入成员列表控件中
   InsertMemberItem(id,name,date.Left(10));
   //下一条数据
   rs.MoveNext();
  }
  rs.Close();
  //////////////////////////////////
  ///向备忘录类型控件中添加备忘录信息
  //////////////////////////////////
  sql="select * from memo_type_tab";
  //获取所有备忘录信息记录
  rs.Open(CRecordset::dynaset,sql);
  MessageBox("查询Memo类型的SQL成功执行");
  while(!rs.IsEOF())
  {
   CDBVariant var;
   //获取备忘类型ID字段值
   rs.GetFieldValue((short)0,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    id=var.m_iVal;
   var.Clear();
   //获取类型名字段值
   rs.GetFieldValue(1,name);
   //把记录值插入成员列表控件中
   InsertMemoTypeItem(id,name);
   //下一条数据
   rs.MoveNext();
  }
  rs.Close();
  ////////////////////////////////
  ///向备注列表中加入所有的备注信息
  ////////////////////////////////
  sql="select * from memo_info_tab";
  rs.Open(CRecordset::dynaset,sql);
  MessageBox("查询MemoInfo的SQL成功执行");
  while(!rs.IsEOF())
  {
   CDBVariant var;
   int memoID,memberID,isEvent,nType;
   CString happenDate,operDate,memoTxt,strName,strType;
   //获取备忘类型ID字段值
   rs.GetFieldValue((short)0,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    memoID=var.m_iVal;
   //获取成员字段ID值
   rs.GetFieldValue((short)1,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    memberID=var.m_iVal;
   //获取操作日期字段
   rs.GetFieldValue(2,operDate);
   //获取发生日期字段值
   rs.GetFieldValue(3,happenDate);
   var.Clear();
   //获取是否大事记字段值
   rs.GetFieldValue(4,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    isEvent=var.m_iVal;
   var.Clear();
   //获取备忘录类型ID
   rs.GetFieldValue(5,var,SQL_C_SLONG);
   if(var.m_dwType!=DBVT_NULL)
    nType=var.m_iVal;
   var.Clear();
   //获取备忘录内容字段值
   rs.GetFieldValue(6,memoTxt);
   
   CRecordset rs2;
   rs2.m_pDatabase=&m_db;
   //获取成员ID的姓名