iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >ODBC中怎么利用CRecordset类对数据库进行操作
  • 638
分享到

ODBC中怎么利用CRecordset类对数据库进行操作

2024-04-02 19:04:59 638人浏览 薄情痞子
摘要

ODBC中怎么利用CRecordset类对数据库进行操作,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 1.MFC中的ODBC类

ODBC中怎么利用CRecordset类对数据库进行操作,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

 

1.MFC中的ODBC类

主要有CDatabase、CRecordset、CRecordview、CDBException、CFieldExchange。这些类封装了ODBC
SDK函数,可以很方便的操作支持ODBC的数据库
(1)CDatabase类:封装应用程序与需要访问的数据库之间的连接,控制事务的提交和执行sql语句的方法。

(2)CRecordset类:封装大部分操纵数据库的方法,包括浏览、修改记录、控制游标移动,排序等操作。CRecordset类是MFC的ODBC类中最重要、功能最强大的一个类。CRecordset类对象提供了从数据源中提取出的记录集。在多任务操作系统网络环境中,多个用户可以共享同一个数据源。共享数据的一个主要问题是如何协调各个用户对数据源的修改。CRecordset提供了几种不同的方法来处理这个问题,这将由程序采用哪种类型的记录集来决定。

CRecordset对象通常用于两种形式:动态行集(dynasets)和快照集(snapshots)。动态行集能与其他用户所做的更改保持同步,快照集则是数据的一个静态视图,当别的用户改变了记录时(包括修改、添加和删除),快照中的记录不受影响,也就是说,快照不反映别的用户对数据源记录的改变.直到调用了CRecordset::Requery重新查询后,快照才会反映变化。每一种形式在记录集被打开时都提供一组记录,所不同的是,当在一个动态行集里滚动到一条记录时,由其他用户或是应用程序中其他记录集对该记录所做的更改会相应地显示出来,例如在火车联网销售系统中,应该实时的显示共享数据的变化。

(3)CRecordView类:提供与CRecordset对象相连接的视图,可以建立视图中的控件与数据库数据的对应,同时支持游标,修改记录等操作。

(4)CDBException类:提供对数据库操作的异常处理。

(5)CFieldExchange类:提供用户变量与数据库字段之间的数据交换。

2.域数据成员与数据交换

 CRecordset类代表一个记录集。用户一般用ClassWizard创建一个CRecordset的派生类。ClassWizard可以为派生的记录集类创建一批数据成员,这些数据成员与记录的各字段相对应,被称为字段数据成员或域数据成员。域数据成员与表中的字段名字类似,且类型匹配。
例如:这是一个CRecordset类的派生类的定义
class CSetdata : public CRecordset
{
public:
 CSetdata(CDatabase* pDatabase = NULL);
 DECLARE_DYNAMIC(CSetdata)

// Field/Param Data
 //{{AFX_FIELD(CSetdata, CRecordset)
 //定义域数据成员变量,域数据成员用来与记录集对应字段进行数据交换,起到一个缓冲区或中间桥梁的作用。也就是说,我们在处理记录集时,实际上是对域数据成员进行操作,而不是直接对数据库中的数据操作。
 CString m_number;               
 CString m_name;
 CString m_sex;
 long m_age;
 //}}AFX_FIELD
 CString number;

// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CSetdata)
 public:
 virtual CString GetDefaultConnect();    // Default connection string
 virtual CString GetDefaultSQL();    // Default SQL for Recordset
 virtual void DoFieldExchange(CFieldExchange* pFX);  // RFX support
 //}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
 virtual void AssertValid() const;
 virtual void Dump(CDumpContext& dc) const;
#endif
};

#endif 

域数据成员用来保存某条记录的各个字段,它们是程序与记录之间的缓冲区。域数据成员代表当前记录,当在记录集中滚动到某一记录时,框架自动地把记录的各个字段拷贝到记录集对象的域数据成员中。当用户要修改当前记录或增加新记录时,程序先将各字段的新值放入域数据成员中,然后调用相应的CRecordset成员函数把域数据成员设置到数据源中。

  不难看出,在记录集与数据源之间有一个数据交换问题.CRecordset类使用"记录域交换"(Record Field Exchange,缩写为RFX)机制自动地在域数据成员和数据源之间交换数据。RFX机制与对话数据交换(DDX)类似。CRecordset的成员函数DoFieldExchange负责数据交换任务,在该函数中调用了一系列RFX函数。当用户用ClassWizard加入域数据成员时,ClassWizard会自动在DoFieldExchange中建立RFX。
典型的DoFieldExchange函数

void CSetdata::DoFieldExchange(CFieldExchange* pFX)
{
 //{{AFX_FIELD_MAP(CSetdata)
 pFX->SetFieldType(CFieldExchange::outputColumn);
 RFX_Text(pFX, _T("[number]"), m_number);        //实现了域数据成员和数据源之间的数据交换
 RFX_Text(pFX, _T("[name]"), m_name);
 RFX_Text(pFX, _T("[sex]"), m_sex);
 RFX_Long(pFX, _T("[age]"), m_age);
  //}}AFX_FIELD_MAP
 pFX->SetFieldType(CFieldExchange::param);
 RFX_Text(pFX,_T("[]"),number);
}

3.记录集的建立和关闭

使用MFC的ODBC类操作数据库首先要建立一个CRecordset的派生类来关联对应的数据表,然后调用Open()函数来查询数据源中的数据并建立记录集。此外,在Open函数中,可能还会调用GetDefaultConnect和GetDefaultSQL函数。
(1)首先在派生类的构造函数中会有一个参数指向一个CDatabase对象,用来获取数据源。函数如下:
CRecordset(CDatabase* pDatabase = NULL);
如果pDatabase为NULL,则会在Open函数中自动构建一个CDatabase对象。如果CDatabase对象还未与数据源连接,那么在Open函数中会建立连接,连接字符串由成员函数GetDefaultConnect提供。

(2)virtual CString GetDefaultConnect();
该函数返回缺省的连接字符串。Open函数在必要的时侯会调用该函数获取连接字符串以建立与数据源的连接。一般需要在CRecordset派生类中覆盖该函数并在新版的函数中提供连接字符串。
例如:CSetdata为CRecordset类的派生类
CString CSetdata::GetDefaultConnect()
{
 return _T("ODBC;DSN=my data");
}
这个函数获取了数据库连接字符串,包括连接方式以及数据源的名称。

(3)virtual CString GetDefaultSQL();
Open函数在必要时会调用该函数返回缺省的SQL语句或表名以查询数据源中的记录。一般需要在CRecordset派生类中覆盖该函数并在新版的函数中提供SQL语句或表名。
例如:
CString CSetdata::GetDefaultSQL()
{
 return _T("[bingli]");
}
这个类返回的是数据源中数据表bingli的名称。

(4)virtual BOOL Open( UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE, LPCTSTR lpszSQL = NULL, DWord dwOptions = none );
throw( CDBException, CMemoryException );
该函数使用指定的SQL语句查询数据源中的记录并按指定的类型和选项建立记录集。参数nOpenType说明了记录集的类型,如下表所示。如果要求的类型驱动程序不支持,则函数将产生一个异常。参数lpszSQL是一个SQL的SELECT语句,或是一个表名。函数用lpszSQL来进行查询,如果该参数为NULL,则函数会调用GetDefaultSQL获取缺省的SQL语句。参数dwOptions可以是一些选项的组合,常用的选项在下表中列出。若创建成功则函数返回TRUE,若函数调用了CDatabase::Open且返回FALSE,则函数返回FALSE.

记录集的类型
类型                       
含义 
AFX_DB_USE_DEFAULT_TYPE     使用缺省值. 
CRecordset::dynaset         可双向滚动的动态集. 
CRecordset::snapshot        可双向滚动的快照. 
CRecordset::dynamic         提供比动态集更好的动态特性,大部分ODBC驱动程序不支持这种记录集. 
CRecordset::forwardOnly     只能前向滚动的只读记录集. 
 
创建记录集时的常用选项  
选项                          
含义 
CRecordset::none               无选项(缺省). 
CRecordset::appendOnly         不允许修改和删除记录,但可以添加记录. 
CRecordset::readOnly           记录集是只读的. 
CRecordset::skipDeletedRecords 有些数据库(如FoxPro)在删除记录时并不真删除,而是做个删除标记,在滚动时将跳过这些被删除的记录。
 
如果所有的参数都为空,例如:
CSetdata *pset = new CSetdata();   
pset->Open();
那么Open()函数将会调用GetDefaultSQL()函数获取指定数据表的数据并建立数据集。实际上,如果只提供表名,CRecordset类会构造一个SELECT语句来查询数据源。例如:SELECT
(能提供的字段名) FROM bingli(即GetDefaultSQL()函数返回的表名)。

(5) 建立记录集后,用户可以随时调用Requery成员函数来重新查询和建立记录集。Requery有两个重要用途:

使记录集能反映用户对数据源的改变

按照新的过滤或排序方法查询记录并重新建立记录集.

  在调用Requery之前,可调用CanRestart来判断记录集是否支持Requery操作。要记住Requery只能在成功调用Open后调用,所以程序应调用IsOpen来判断记录集是否已建立.函数的声明为

virtual BOOL Requery( );
throw( CDBException, CMemoryException );
返回TRUE表明记录集建立成功,否则返回FALSE。若函数内部出错则产生异常.

BOOL CanRestart( ) const; //若支持Requery则返回TRUE
BOOL IsOpen( ) const; //若记录集已建立则返回TRUE

  CRecordset类有两个公共数据成员m_strFilter和m_strSort用来设置对记录的过滤和排序。在调用Open或Requery前,如果在这两个数据成员中指定了过滤或排序,那么Open和Requery将按这两个数据成员指定的过滤和排序来查询数据源。
   成员m_strFilter用于指定过滤器。m_strFilter实际上包含了SQL的WHERE子句的内容,但它不含WHERE关键字。使用m_strFilter的一个例子为:
m_pSet->m_strFilter=“CourseID=‘MATH101’”; //只选择CourseID为MATH101的记录
if(m_pSet->Open(CRecordset::snapshot, “Section”))

. . . . . .

  成员m_strSort用于指定排序.m_strSort实际上包含了ORDER BY子句的内容,但它不含ORDER BY关键字.m_strSort的一个例子为

m_pSet->m_strSort=“CourseID DESC”; //按CourseID的降序排列记录

m_pSet->Open();

. . . . . .

  事实上,Open函数在构造SELECT语句时,会把m_strFilter和m_strSort的内容放入SELECT语句的WHERE和ORDER
BY子句中.如果在Open的lpszSQL参数中已包括了WHERE和ORDER BY子句,那么m_strFilter和m_strSort必需为空.

  调用无参数成员函数Close可以关闭记录集.在调用了Close函数后,程序可以再次调用Open建立新的记录集.CRecordset的析构函数会调用Close函数,所以当删除CRecordset对象时记录集也随之关闭。

4.滚动记录

CRecordset提供了几个成员函数用来在记录集中滚动,如下所示.当用这些函数滚动到一个新记录时,框架会自动地把新记录的内容拷贝到域数据成员中。

void MoveNext();  //前进一个记录
void MovePrev();  //后退一个记录
void MoveFirst(); //滚动到记录集中的第一个记录
void MoveLast();  //滚动到记录集中的最后一个记录
void SetAbsolutePosition( long nRows ); 
该函数用于滚动到由参数nRows指定的绝对位置处.若nRows为负数,则从后往前滚动.例如,当nRows为-1时,函数就滚动到记录集的末尾。注意,该函数不会跳过被删除的记录。

virtual void Move( long nRows, WORD wFetchType = SQL_FETCH_RELATIVE );
该函数功能强大.通过将wFetchType参数指定为SQL_FETCH_NEXT、SQL_FETCH_PRIOR、SQL_FETCH_FIRST、SQL_FETCH_LAST和SQL_FETCH_ABSOLUTE,可以完成上面五个函数的功能.若wFetchType为SQL_FETCH_RELATIVE,那么将相对当前记录移动,若nRows为正数,则向前移动,若nRows为负数,则向后移动。 

  如果在建立记录集时选择了CRecordset::skipDeletedRecords选项,那么除了SetAbsolutePosition外,在滚动记录时将跳过被删除的记录,这一点对象FoxPro这样的数据库十分重要。

 如果记录集是空的,那么调用上述函数将产生异常。另外,必须保证滚动没有超出记录集的边界。调用IsEOF和IsBOF可以进行这方面的检测。

BOOL IsEOF( ) const; //如果记录集为空或滚动过了最后一个记录,那么函数返回TRUE,否则返回FALSE。 
BOOL IsBOF( ) const; //如果记录集为空或滚动过了第一个记录,那么函数返回TRUE,否则返回FALSE。

下面是一个使用IsEOF的例子:
while(!m_pSet->IsEOF( ))
m_pSet->MoveNext( );

调用GetRecordCound可获得记录集中的记录总数,该函数的声明为:
long GetRecordCount( ) const;  
要注意这个函数返回的实际上是用户在记录集中滚动的最远距离.要想真正返回记录总数,只有调用MoveNext移动到记录集的末尾(MoveLast不行)。
 

5.修改、添加和删除记录

要修改当前记录,应该按下列步骤进行:

调用Edit成员函数.调用该函数后就进入了编辑模式,程序可以修改域数据成员.注意不要在一个空的记录集中调用Edit,否则会产生异常.

Edit函数会把当前域数据成员的内容保存在一个缓冲区中,这样做有两个目的,一是可以与域数据成员作比较以判断哪些字段被改变了,二是在必要的时侯可以恢复域数据成员原来的值.若再次调用Edit,则将从缓冲区中恢复域数据成员,调用后程序仍处于编辑模式.调用Move(AFX_MOVE_REFRESH)或Move(0)可退出编辑模式(AFX_MOVE_REFRESH的值为0),同时该函数会从缓冲区中恢复域数据成员.

设置域数据成员的新值.

调用Update完成编辑.Update把变化后的记录写入数据源并结束编辑模式. 

要向记录集中添加新的记录,应该按下列步骤进行:

调用AddNew成员函数.调用该函数后就进入了添加模式,该函数把所有的域数据成员都设置成NULL(注意,在数据库术语中,NULL是指没有值,这与c++的NULL是不同的).与Edit一样,AddNew会把当前域数据成员的内容保存在一个缓冲区中,在必要的时侯,程序可以再次调用AddNew取消添加操作并恢复域数据成员原来的值,调用后程序仍处于添加模式.调用Move(AFX_MOVE_REFRESH)可退出添加模式,同时该函数会从缓冲区中恢复域数据成员.

设置域数据成员.

调用Update.Update把域数据成员中的内容作为新记录写入数据源,从而结束了添加. 

如果记录集是快照,那么在添加一个新的记录后,需要调用Requery重新查询,因为快照无法反映添加操作.

要删除记录集的当前记录,应按下面两步进行:

调用Delete成员函数.该函数会同时给记录集和数据源中当前记录加上删除标记.注意不要在一个空记录集中调用Delete,否则会产生一个异常.

滚动到另一个记录上以跳过删除记录. 

上面提到的函数声明为:

virtual void Edit( );throw( CDBException, CMemoryException );

virtual void AddNew( );throw( CDBException );

virtual void Delete( );throw( CDBException );

virtual BOOL Update( );throw( CDBException ); 
若更新失败则函数返回FALSE,且会产生一个异常.

   在对记录集进行更改以前,程序也许要调用下列函数来判断记录集是否是可以更改的,因为如果在不能更改的记录集中进行修改、添加或删除将导致异常的产生.

BOOL CanUpdate( ) const; //返回TRUE表明记录是可以修改、添加和删除的.

BOOL CanAppend( ) const; //返回TRUE则表明可以添加记录.

关于ODBC中怎么利用CRecordset类对数据库进行操作问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网数据库频道了解更多相关知识。

您可能感兴趣的文档:

--结束END--

本文标题: ODBC中怎么利用CRecordset类对数据库进行操作

本文链接: https://www.lsjlt.com/news/57877.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • ODBC中怎么利用CRecordset类对数据库进行操作
    ODBC中怎么利用CRecordset类对数据库进行操作,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 1.MFC中的ODBC类...
    99+
    2022-10-18
  • Android中怎么利用LitePal对数据库进行操作
    Android中怎么利用LitePal对数据库进行操作,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先在app/build.grade文件中编辑dependencies{.....
    99+
    2023-06-04
  • Java中怎么利用Streams对数据库进行查询操作
    Java中怎么利用Streams对数据库进行查询操作,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。示例数据库我们使用的示例数据库是Saki...
    99+
    2022-10-18
  • 利用mybatis怎么对数据库进行增删改查操作
    这篇文章将为大家详细讲解有关利用mybatis怎么对数据库进行增删改查操作,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。所需要用到的其他工具或技术:项目管理工具 : Maven测试运行工具 ...
    99+
    2023-05-31
    mybatis
  • 利用hibernate怎么对数据库进行增删改查操作
    本篇文章给大家分享的是有关利用hibernate怎么对数据库进行增删改查操作,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Hibernate对数据删除操作删除User表中个一条...
    99+
    2023-05-31
    hibernate
  • python中怎么利用 mysqldb类库操作数据库
    这期内容当中小编将会给大家带来有关python中怎么利用 mysqldb类库操作数据库,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。安装MySQLdbpip install MySQLdb2.代码impo...
    99+
    2023-06-02
  • 怎么运用PHP进行数据库操作类
    这篇文章主要为大家展示了“怎么运用PHP进行数据库操作类”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么运用PHP进行数据库操作类”这篇文章吧。PHP高级实战...
    99+
    2022-10-18
  • 使用phonegap怎么对数据库进行操作
    使用phonegap怎么对数据库进行操作?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实例如下:<!DOCTYPE html> ...
    99+
    2023-06-09
  • C# 中怎么利用ODBC访问MySQL数据库
    C# 中怎么利用ODBC访问MySQL数据库,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。安装Microsoft ODBC.net:我安装的是mysql-con...
    99+
    2023-06-17
  • 使用Node怎么对MongoDB数据库进行操作
    这篇文章给大家介绍使用Node怎么对MongoDB数据库进行操作,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1.使用 MongoDB模块 进行操作 首先在工作目录安装 mo...
    99+
    2022-10-18
  • 使用gorm怎么对MySql数据库进行操作
    本篇文章给大家分享的是有关使用gorm怎么对MySql数据库进行操作,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、表中字段区分大小写的设置在使用gorm查询的时候,会出现账...
    99+
    2023-06-07
  • QT中怎么对Mat类进行操作
    本篇内容主要讲解“QT中怎么对Mat类进行操作”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“QT中怎么对Mat类进行操作”吧!一、类型转换opencv在QT中的应用通常会涉及到这三者的转换,即M...
    99+
    2023-07-02
  • Android应用中SQLite数据库怎么利用listview控件进行操作
    今天就跟大家聊聊有关Android应用中SQLite数据库怎么利用listview控件进行操作,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。利用SQLiteOpenHelper类建立...
    99+
    2023-05-31
    listview sqlite lite
  • PHP中利用数组差集对数据库进行修改操作的案例
    小编给大家分享一下PHP中利用数组差集对数据库进行修改操作的案例,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1.主要利用的函数array_diff_assoc() a.语法:array_diff_assoc(array1...
    99+
    2023-06-14
  • 怎么在Python中利用Selenium对Cookie进行操作
    本文章向大家介绍怎么在Python中利用Selenium对Cookie进行操作的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向对象...
    99+
    2023-06-06
  • C#中怎么利用FileStream对文件进行操作
    C#中怎么利用FileStream对文件进行操作,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。C# FileStream写文件的操作实例:///先导入命名空间:...
    99+
    2023-06-17
  • python中怎么利用sqlalchemy 操作数据库
    今天就跟大家聊聊有关python中怎么利用sqlalchemy 操作数据库,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。安装pip install sqlalchemy2....
    99+
    2023-06-02
  • Android中怎么利用LitePal操作数据库
    Android中怎么利用LitePal操作数据库,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。把图片转换为字节private byte[]img(Bitmap&nbs...
    99+
    2023-05-30
    android litepal
  • 怎么在python中利用loguru对日志进行操作
    本篇文章为大家展示了怎么在python中利用loguru对日志进行操作,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python可以做什么Python是一种编程语言,内置了许多有效的工具,Pytho...
    99+
    2023-06-14
  • 怎么在Java中利用File对文件进行操作
    本篇文章为大家展示了怎么在Java中利用File对文件进行操作,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.1java.io.FileFile用于表示文件系统中的一个文件或目录通过File可以:...
    99+
    2023-05-31
    java file
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作