一.概述
  ODBC 是一种使用SQL 的程序设计接口。使用ODBC 让应用程序的编写者避免了与数据源相联的复杂性。这项技术目前已经得到了大多数DBMS 厂商们的广泛支持。
  Microsoft Developer Studio 为大多数标准的数据库格式提供了32 位ODBC 驱动器。这些标准数据格式包括有:SQL Server、Access、Paradox、dBase、FoxPro、Excel、Oracle 以及Microsoft Text。如果用户希望使用其他数据格式,用户需要相应的ODBC 驱动器及DBMS。
  用户使用自己的DBMS 数据库管理功能生成新的数据库模式后,就可以使用ODBC 来登录数据源。对用户的应用程序来说,只要安装有驱动程序,就能注册很多不同的数据库。登录数据库的具体操作参见有关ODBC 的联机帮助。
  二.MFC 提供的ODBC 数据库类
  Visual C++ 的MFC 基类库定义了几个数据库类。在利用ODBC 编程时,经常要使用到CDatabase( 数据库类),CRecordSet( 记录集类) 和CRecordView( 可视记录集类)。其中:
  CDatabase 类对象提供了对数据源的连接,通过它你可以对数据源进行操作。
  CRecordSet 类对象提供了从数据源中提取出的记录集。CRecordSet 对象通常用于两种形式:动态行集(dynasets)和快照集(snapshots)。动态行集能保持与其他用户所做的更改保持同步。快照集则是数据的一个静态视图。每一种形式在记录集被打开时都提供一组记录,所不同的是,当你在一个动态行集里滚动到一条记录时,由其他用户或是你应用程序中的其他记录集对该记录所做的更改会相应地显示出来。
  CRecordView 类对象能以控制的形式显示数据库记录。这个视图是直接连到一个CRecordSet 对象的表视图。
  三.应用ODBC 编程
  应用Visual C++ 的AppWizard 可以自动生成一个ODBC 应用程序框架。方法是:打开File 菜单的New 选项,选取Projects,填入工程名,选择MFC AppWizard (exe),然后按AppWizard 的提示进行操作。当AppWizard 询问是否包含数据库支持时,如果你想读写数据库,那么选定Database view with file support;Database view without file support 选项就比较合适了。选择了数据库支持之后Database Source 按钮会激活,选中它去调用Data Options 对话框。在Database Options 对话框中会显示已向ODBC 注册的数据库资源,选定你所要操作的数据库,如:Super_ES,单击OK 后会出现Select Database Tables 对话框,其中列举了你所选中的数据库中包含的全部表,选择你希望操作的表后,单击OK。在选定了数据库和数据表之后,你可以按照惯例继续进行AppWizard 操作。
  特别需要指出的是:在生成的应用程序框架View 类(如:CSuper_ESView)中包含一个指向CSuper_ESSet 对象的指针m_pSet,该指针由AppWizard 建立,目的是在视表单和记录集之间建立联系,使得记录集中的查询结果能够很容易地在视表单上显示出来。有关m_pSet 的详细用法可以参见Visual C++ Online Book。
  程序与数据语言建立联系,使用CDatebase::OpenEx() 或CDatabase::Open() 函数来进行初始化。数据库对象必须在你使用它构造一个记录集对象之前被初始化。

  下面举例说明在Visual C++ 环境中ODBC 的编程技巧:
  1 .查询记录
  查询记录使用CRecordSet::Open() 和CRecordSet::Requery() 成员函数。在使用CRecordSet 类对象之前,必须使用CRecordSet::Open() 函数来获得有效的记录集。一旦已经使用过CRecordSet::Open() 函数,再次查询时就可以应用CRecordSet::Requery() 函数。在调用CRecordSet::Open() 函数时,如果已经将一个已经打开的CDatabase 对象指针传给CRecordSet 类对象的m_pDatabase 成员变量,则使用该数据库对象建立ODBC 连接;否则如果m_pDatabase 为空指针,就新建一个CDatabase 类对象并使其与缺省的数据源相连,然后进行CRecordSet 类对象的初始化。缺省数据源由GetDefaultConnect() 函数获得。你也可以提供你所需要的SQL 语句,并以它来调用CRecordSet::Open() 函数,例如:
  Super_ESSet.Open(AFX_DATABASE_USE_DEFAULT,strSQL);
  如果没有指定参数,程序则使用缺省的SQL 语句,即对在GetDefaultSQL() 函数中指定的SQL 语句进行操作:
  CString CSuper_ESSet::GetDefaultSQL()
  {return _T("[BasicData],[MainSize]");}
  对于GetDefaultSQL() 函数返回的表名,对应的缺省操作是SELECT 语句,即:
  SELECT * FROM BasicData,MainSize
  查询过程中也可以利用CRecordSet 的成员变量m_strFilter 和m_strSort 来执行条件查询和结果排序。m_strFilter 为过滤字符串,存放着SQL 语句中WHERE 后的条件串;m_strSort 为排序字符串,存放着SQL 语句中ORDER BY 后的字符串。如:
  Super_ESSet.m_strFilter="TYPE=电动机";
  Super_ESSet.m_strSort="VOLTAGE";
  Super_ESSet.Requery();
  对应的SQL语句为:
  SELECT * FROM BasicData,MainSize
  WHERE TYPE=电动机
  ORDER BY VOLTAGE
  除了直接赋值给m_strFilter 以外,还可以使用参数化。利用参数化可以更直观,更方便地完成条件查询任务。使用参数化的步骤如下:
  (1) .声明参变量:
  CString p1;
  float p2;
  (2) .在构造函数中初始化参变量
  p1=_T("");
  p2=0.0f;
  m_nParams=2;
  (3) .将参变量与对应列绑定
  pFX- >SetFieldType(CFieldExchange::param)
  RFX_Text(pFX,_T("P1"),p1);
  RFX_Single(pFX,_T("P2"),p2);
  完成以上步骤之后就可以利用参变量进行条件查询了:
  m_pSet- >m_strFilter="TYPE=? AND VOLTAGE=?";
  m_pSet- >p1=" 电动机";
  m_pSet- >p2=60.0;
  m_pSet- >Requery();
  参变量的值按绑定的顺序替换查询字串中的"?" 适配符。
  如果查询的结果是多条记录的话,可以用CRecordSet 类的函数Move(),MoveNext(),MovePrev(),MoveFirst() 和MoveLast() 来移动光标。

  2 .增加记录
  增加记录使用AddNew() 函数,要求数据库必须是以允许增加的方式打开:
  m_pSet- >AddNew(); //在表的末尾增加新记录
  m_pSet- >SetFieldNull(&(m_pSet- >m_type), FALSE);
  m_pSet- >m_type=" 电动机";
  ... //输入新的字段值
  m_pSet- > Update(); //将新记录存入数据库
  m_pSet- >Requery(); //重建记录集
  3 .删除记录
  直接使用Delete() 函数,并且在调用Delete() 函数之后不需调用Update() 函数:
  m_pSet- >Delete();
  if (!m_pSet- >IsEOF())
  m_pSet- >MoveNext();
  else
  m_pSet- >MoveLast();
  4 .修改记录
  修改记录使用Edit() 函数:
  m_pSet- >Edit(); //修改当前记录
  m_pSet- >m_type="发电机";
  //修改当前记录字段值
  ...
  m_pSet- >Update(); //将修改结果存入数据库
  m_pSet- >Requery();
  5 .撤消操作
  如果用户选择了增加或者修改记录后希望放弃当前操作,可以在调用Update() 函数之前调用:
  CRecordSet::Move(AFX_MOVE_REFRESH);
  来撤消增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中的参数AFX_MOVE_REFRESH 的值为零。
  6 .数据库连接的复用
  在CRecordSet 类中定义了一个成员变量m_pDatabase:
  CDatabase* m_pDatabase;
  它是指向对象数据库类的指针。如果在CRecordSet 类对象调用Open() 函数之前,将一个已经打开的CDatabase 类对象指针传给m_pDatabase,就能共享相同的CDatabase 类对象。如:
  CDatabase m_db;
  CRecordSet m_set1,m_set2;
  m_db.Open(_T("Super_ES"));//建立ODBC连接
  m_set1.m_pDatabase=&m_db;
  //m_set1复用m_db对象
  m_set2.m_pDatabse=&m_db;
  // m_set2复用m_db对象
  7 .SQL 语句的直接执行
  虽然通过CRecordSet 类,我们可以完成大多数的查询操作,而且在CRecordSet::Open() 函数中也可以提供SQL 语句,但是有的时候我们还想进行一些其他操作,例如建立新表,删除表,建立新的字段等等,这时就需要使用到CDatabase 类的直接执行SQL 语句的机制。通过调用CDatabase::ExecuteSQL() 函数来完成SQL 语句的直接执行:
  BOOL CDB::ExecuteSQLAndReportFailure(const CString& strSQL)
  {
  TRY
  {
  m_pdb- >ExecuteSQL(strSQL);//直接执行SQL语句
  }
  CATCH (CDBException,e)
  {
  CString strMsg;
  strMsg.LoadString(IDS_EXECUTE_SQL_FAILED);
  strMsg+=strSQL;
  return FALSE;
  }
  END_CATCH
  return TRUE;
  }
  应当指出的是,由于不同DBMS 提供的数据操作语句不尽相同,直接执行SQL 语句可能会破坏软件的DBMS 无关性,因此在应用中应当慎用此类操作。
  8 .动态连接表
  表的动态连接可以利用在调用CRecordSet::Open() 函数时指定SQL 语句来实现。同一个记录集对象只能访问具有相同结构的表,否则查询结果将无法与变量相对应。
  void CDB::ChangeTable()
  {
  if (m_pSet- >IsOpen()) m_pSet- >Close();
  switch (m_id)
  {
  case 0:
  m_pSet- >Open(AFX_DB_USE_DEFAULT_TYPE,
  "SELECT * FROM SLOT0"); //连接表SLOT0
  m_id=1;
  break;
  case 1:
  m_pSet- >Open(AFX_DB_USE_DEFAULT_TYPE,
  "SELECT * FROM SLOT1"); //连接表SLOT1
  m_id=0;
  break;
  }
  }

  9 .动态连接数据库
  由于与数据库的连接是通过CDatabase 类对象来实现的,所以我们可以通过赋与CRecordSet 类对象参数m_pDatabase 以连接不同数据库的CDatabase 对象指针,就可以动态连接数据库。
  void CDB::ChangeConnect()
  {
  CDatabase* pdb=m_pSet- >m_pDatabase;
  pdb- >Close();
  switch (m_id)
  {
  case 0:
  if (!pdb- >Open(_T("Super_ES")))
  //连接数据源Super_ES
  {
  AfxMessageBox("数据源Super_ES打开失败,"
  "请检查相应的ODBC连接", MB_OK|MB_ICONWARNING);
  exit(0);
  }
  m_id=1;
  break;
  case 1:
  if (!pdb- >Open(_T("Motor")))
  //连接数据源Motor
  {
  AfxMessageBox("数据源Motor打开失败,"
  "请检查相应的ODBC连接", MB_OK|MB_ICONWARNING);
  exit(0);
  }
  m_id=0;
  break;
  }
  }

ODBC CRecordSet访问的更多相关文章

  1. 如何在客户端配置ODBC来访问远程DB2 for Windows服务器

    如何在客户端配置ODBC来访问远程DB2 for Windows服务器                                  马根峰                    (广东联合电子服 ...

  2. 巨高兴,偶的文章 “如何在服务器上配置ODBC来访问本机DB2for Windows服务器”被推荐至CSDN博客首页

    非常高兴,偶的文章 "如何在服务器上配置ODBC来访问本机DB2for Windows服务器"被推荐至CSDN博客首页,截图留念.                  文章被推荐在C ...

  3. 如何在服务器上配置ODBC来访问本机DB2 for Windows服务器

    如何在服务器上配置ODBC来访问本机 DB2 for Windows服务器                         马根峰             (广东联合电子服务股份有限公司, 广州 51 ...

  4. C++中使用ODBC API访问数据库例程

    使用ODBC API访问数据库简单流程,供参考使用:  ODBC API 123456789101112131415161718192021222324252627282930313233343536 ...

  5. 通过ODBC接口访问人大金仓数据库

      国产化软件和国产化芯片的窘境一样,一方面市场已经存在性能优越的同类软件,成本很低,但小众的国产化软件不仅需要高价买入版权,并且软件开发维护成本高:另一方面,国产软件目前普遍难用,性能不稳定,Bug ...

  6. python 通过Sybase ASE ODBC Driver访问sybase数据库,无需配置DSN【自己整理的】

    Python语言对于开发工程师或者测试工程师来说,应该是最高效的开发语言之一.但python访问sybase数据库的资料相对少见.而且sybase字符集为GB1803时,python访问sybase库 ...

  7. Windows下使用ODBC API访问数据库之关键

    本文采用SQL2005 + VS2008环境,以ODBC API方式成功连接数据库. 1.SQL安装和环境配置 这部分网上随便搜一下都有很多资料,而且很容易就可以配置成功. 注意的关键点: SA账号配 ...

  8. 数据库访问接口(ODBC、OLE DB、ADO)

    最近在学C#的数据库编程,对于数据库接口技术这块的知识一直比较模糊,网上查了不少资料,看了几天还是朦朦胧胧的,只能做些笔记再研究了. 我们都知道,“数据库”是指一组相关信息的集合,最早的计算机应用之一 ...

  9. R(六): RODBC 访问SqlServer

    在我的实际工作中,数据来源一方面是关系型数据库MS SqlServer, 别一方面是HBase.本节主要介绍通过RODBC访问MS SqlServer 安装配置,参见资料(https://msdn.m ...

随机推荐

  1. eclipse中设置新建jsp文件的编码格式

    每次新建jsp文件时,默认都是ISO-8859-1,每次涉及有中文的时候都得改成UTF-8,这就很麻烦了. 解决的方法就是,设置新建jsp文件的编码格式. 解决方法 结果 或者更改它的encoding

  2. Java中List集合的常用方法

    List接口是继承Collection接口,所以Collection集合中有的方法,List集合也继承过来. 这篇文章就不讲继承Collection接口的那些方法了 https://www.cnblo ...

  3. 分享:自定义JAVA注解

    元注解 元注解指用来定义注解的注解,例如:@Retention @Target Inherited @Documented等等.最为重要和经常使用的是@Retention @Target. @Rete ...

  4. 7z压缩gopath的src的批处理

    7zGoPath.bat @echo off pushd "%~dp0" :config for /f "delims=" %%t in ('powershel ...

  5. 卸载mac多余的音频驱动:internal audio driver corel painter

    $ kextstat | grep corel 130 0 0xffffff7f81042000 0x4000 0x4000 com.corel.painter.PainterAudioDriver ...

  6. delete 与 delete []的区别

    一. 针对类class,这两种方式的效果是不同的. 当你通过下列方式分配一个类对象数组:   class A   {   private:      char *m_cBuffer;      int ...

  7. button出现投影

    style="?android:attr/borderlessButtonStyle" xml中加上这属性

  8. 条款23:宁以non-member, non-friend,替换member函数。

    考虑下面这种经常出现的使用方式: class webBroswer{ public: ... void clearCache(); void clearHistory(); void removeCo ...

  9. 面试题48:用C++设计一个不能被继承的类

    解法一:把构造函数设为私有 将构造函数定义为私有,然后通过定义公有的静态函数来创建和释放类的实例. { public: static SealedClass1* GetInstance() { ret ...

  10. socket INADDR_ANY

    linux下的socket INADDR_ANY表示的是一个服务器上所有的网卡(服务器可能不止一个网卡)多个本地ip地址都进行绑定端口号,进行侦听. 不光是多个网卡的问题. 见如下server lis ...