ODBC中CRecordSet中有没有可以得到某个字段函数的最大值与最小值最小值的函数

【图文】第十一章_数据库_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
第十一章_数据库
上传于||暂无简介
大小:585.00KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢2291人阅读
MFC(139)
MFC ODBC 用法(转载)
主要内容:
MFC &ODBC将ODBC
API封装在类CDatabase、CRecordSet、CFieldExchange、CRecordView和CDBException中
使用MFCODBC
开发数据库应用程序的一般步骤
使用AppWizard访问数据库
使用类CDatabase连接数据库
使用类CRecordSet打开记录集、获取数据
使用类CRecordSet的函数MoveFirst()、MoveLast()、MoveNext()、MovePrev()、IsBOF()和IsEOF()进行记录集的遍
使用类CRecordSet的函数AddNew和Update增加记录
使用类CRecordSet的函数Edit和Update修改记录
使用类CRecordSet的函数Delete
使用类CDatabase的函数ExecuteSQL直接执行SQL命令
使用类CDatabase的函数BeginTrans、CommitTrans和Rollback处理事务
MFC&OBDC技术
ODBC类对较复杂的ODBC API进行了封装,提供了简化的调用接口。
类主要包括以下 5 个类:
&CDatabase类:主要功能是建立与数据源的连接
&CRecordset类:代表从数据源选择的一组记录(记录集)
CRecordView类:提供了一个表单视图与某个记录集直接相连,利用对话框数据交替机制(DDX)在记录集与表单视图的控件之间传输数据
CFieldExchange类:支持记录字段数据交换(RFX),即记录集字段数据成员与相应的数据库的表的字段之间的数据交换。
CDBException类:代表ODBC类产生的异常。&
CDatabase类操作数据源
CDatabase类型的对象表示一个到数据源的连接,通过它可以操作数据源。该类的成员函数如下表:
&CDatabase
构造一个对象
关闭数据源连接
通过一个 ODBC 驱动程序创建到数据源的连接
通过一个 ODBC 驱动程序创建到数据源的连接
BeginTrans
BindParameters
允许在调用 CDatabase::ExecuteSQL 前绑定参数
取消异步操作或第二条线程中的过程
&CommitTrans
&ExecuteSQL
执行 SQL 语句,不返回记录
回滚事务,数据源返回先前的状态
该类的属性属性如下表:
&CanTransact
如果数据源支持事务,返回非零
&CanUpdate
如果 CDatabase 可以更新,返回非零&
&GetBookmarkPersistence
获得书签对记录集对象的持久性
&GetConnect
返回 ODBC 连接串
GetCursorCommitBehavio r
获得提交事务对记录集对象的影响
GetCursorRollbackBehav ior
获得回滚事务对记录集对象的影响
&GetDatabaseName
返回当前使用的数据库名
如果当前 CDatabase 对象连接到数据源,返回非零
&SetLoginTimeout
设置数据源连接的超时数(秒为单位)
&SetQueryTimeout
设置查询操作的超时数(秒为单位)
应用程序可使用多个 CDatabase 类型的对象。构造一个对象并调用 Open()
成员函数打开一个连接。接着构造CRecordset 类型的对象以操作连接的数据源,构造时向记录集对象传递 CDatabase 类型的指针。完成使用后,用 Close()成员函 数销毁 CDatabase 类型的对象。
一般情况下并不需要直接使用 CDatabase 类型的对象,因为 CRecordset 类型 的对象可以实现大多数的功能、但是在进行事务处理时,CDatabase 就起到关键 作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个都不提交,为的是确保多用户对数据源同时操作时的数据正确性。
CRecordset 类操作记录集
一个CRecordset 类型的对象代表从数据源选择的一组记录的集合——记录集,通过该类的方法实现对数据库中记录的各种操作。
该类常用的数据成员如下表:
包含记录集的 ODBC 陈述句柄,类型为 HSTMT
包含记录集中字段数据成员的数量,类型为 UNIT
&m_nParams
包含记录集中参数数据成员的数量,类型为 UNIT
&m_pDatabase
包含一个 CDatabase 对象指针,通过它访问数据源
&m_strFilter
包含 CString 对象,定义 SQL 中 WHERE 子句
&m_strSort
包含 CString 对象,定义 SQL 中 ORDER BY 子句
该类的构造方法如下表:
关闭记录集和与之相关的 HSTMT
&CRecordset
构造一个 CRecordset 对象
通过获得表或执行记录集所代表的查询来打开记录集
CRecordset 类记录集属性如下表:
如果新记录可以通过 Addnew 添加到记录集,返回非零
CanBookmark
如果记录集支持书签,返回非零
&CanRestart
如果 Requery 可以被调用来再次运行记录集查询,返回非零
&CanScroll
如果可以在记录中回滚,返回非零
&CanTransact
如果数据源支持事务,返回非零
&CanUpdate
如果记录集可以被更新,返回非零
GetODBCFieldCount
返回记录集中字段的数量
GetRecordCount
返回记录集中记录的数量
获得 SQL 字符串
&GetStatus
获得记录集的状态
&GetTableName
获得记录集所属的表名
如果记录集定位在第一条记录之前,返回非零
&IsDeleted
如果记录集定位在一条删除的记录,返回非零
如果记录集定位在最后一条记录之后,返回非零& & & &
如果调用过 Open 函数,返回非零
CRecordset 类更行操作如下表:
准备增加一条新纪录,调用 Update 之后完成添加
&CancelUpdate
取消任何未完成的更新
从记录集中删除当前记录
准备对当前记录进行修改,调用 Update 后完成修改
通过将新记录或编辑的数据存入数据源来完成 AddNew 或Edit 操作
记录集有两种形式:snapshot(表示数据的静态视图)和 dynaset(表示记
录集与其他用户对数据库的更新保持同步)。
CFieldExchange&类处理数据交换
CFieldExchange 类支持数据库类所使用的记录集字段交换(RFX)程式。如果使用自定义的数据类型写数据交换程式,会使用这个类。否则不会直接使用此类。RFX
在记录集对象的字段数据成员与数据源中当前记录的相应字段之间交换数据。
CRecordView 类显示记录
CRecordView 对象用于在控件中显示数据库记录的视图。这种视图是一种直 接连到一个 CRecordView 对象的格式视图,它从一个对话框模板创建资源,并将 CRecordView 对象的字段显示在对话框模版的控件里。对象利用DDX 和 RFX 机制, 使窗体上的空间和记录集的字段值之间数据移动自动化,也就是说,用户不需要编写一行代码就可以完成简单的数据库记录查看程序。
CDBException 类处理异常
由 CException 类派生,以 3 个继承的成员变量反映对数据库操作时的异常:
m_nRetCode:以 ODBC 返回代码(SQL_RETURN)的形式表明造成一场的原因
&m_strError:字符串,描述造成抛出异常的错误原因
&m_strStateNativeOrigin:字符串,用以描述以ODBC 错误代码表示的异常错误
使用MFC ODBC
编程建立应用程序
MFC& ODBC 编程模型概述
使用 MFCODBC 访问数据库比直接使用 ODBC API 简单得多,编程步骤如下:
使用CDatabase 打开数据源的连接,如果利用 AppWizard 生成一个 ODBC数据库应用程序,则会自动完成操作。
&使用 ClassWizard 向导加入由 CRecordset 类派生的用户记录集类,完成 对数据库的绑定。
创建记录集类对象,如果利用AppWizard 生成一个 ODBC 数据库应用程序,则会自动在文档类中创建。
&使用记录及对象对数据库进行遍历、增加、删除、修改等操作。
&使用CDatabase 类的 ExecuteSQL 函数直接执行 SQL 命令。
使用 CDatabase 类的 BeginTrans、CommitTrans 和 Rollback 函数进行事 务处理
使用CDatabase 类的 Close 函数关闭数据源连接。
通过 AppWizard建立数据库应用程序“New”--&”MFC&AppWizard(EXE)”--&”OK”-&”Single&document(单文
档)”--&NEXT--&”选择需要对什么样的数据库类型支持做出选择:None(不要任
何数据支持,今后再添加很麻烦)、Header files only(该工程需要数据库支持,但 不清楚细节时选择。工程会添加所要求的头文件和链接库,但必须自己在创建数据库类)、Database
view without file support(表示包含数据库头文件和链接库,并创建记录集和记录视图,应用程序虽有文档支持,但不支持串行化)、Databaseviewwith
&file support(表示包含数据库头文件、记录集和视图外,程序还支持串行化)--&”Data&Options
&对话框:在”Datasource”中选择ODBC单选按钮,选择一个已经注册号的数据源(实例程序Sample中使用的数据源叫students)。在”Recordsettype”(记录类型)中有三个选项:Snapshot(快照:它是当前表的一
个静态视图。表打开之后,表中的所有数据马上被载入到应用程序中。其他用户或程序对表的修改只有在下次打开表时才会体现出来,看不到其他用户对表的”即时”修改,因此它是静态的。Snapshot适用于用户查询信息(例如生成报表等)而不适用于数据编辑。)、Dynaset(动
态集:这个选项创建指向所请球的每个记 录的实际指针。只有屏幕需要显示记录时,才从数据库中提取数据。这种方式的好处是动态、即时的浏览到当前的记录。而 其他用户也会即时看到你对记录所 做出的修改。该选项适合于创建用户要发费很多时间来编辑数据的应用程序,并且,如果正在编写大型数据库应用程序,他也是最 &佳选择)、Table(表:表方法(仅
使用 DAO访问数据库时可用)把所做查询的内容放进一个临时表。这样做不但减小了从服务器下载的信息量,还意味着程序员有了更大的灵活性,因为可以直接
操作临时表字段和记录。但缺点是你看不到别人的修改。使用DAO且用户会执行同等数量的数据查询和数据编辑时,它是最佳选择。)”
&--&”Selete&&DatabaseTable(选择数据库表)”
&--&”Finish”.通过AppWizard创建了一个
MFC ODBC数据库工程后,该工程与一般的应用 程序工程有所不同:多了一个CRecordset
的派生类,对应前面选择的数据库表; 视图类的基类是CRecordView,负责显示数据;工具栏上多了遍历记录集的4个
使用CDatabase类方法打开数据源
通过CDatabase类的Open
函数来打开数据源,该函数原型如下:
virtualBOOL &Open(
LPCTSTRlpszDSN,
//一个数据源名,此数据源名是通过ODBC管理器注 册的。如果
DSN被设定在lpszConnect里,那么lpszDSN不应在被重新设定,lpszDSN应设为NULL。
如果没有设lpszConnect,而且又把lpszDSN设定
为 NULL,那么将出现一个对话框,让用户选择数据 源。
BOOL&bExclusive=
FALSE, //默认为 FALSE,表示以共享方式打开数据 源。当前版本的类库不支持独占方式,如果设定为TRUE,将失败
BOOL &bReadOnly= FALSE, //如果希望连接以只读方式打开,不想对数据源进行更新,那么设定为TRUE,所有依靠此
连接打开的记录集全部继承此属性。默认值为FALSE
&LPCTSTRlpszConnect=
_T(“ODBC;”),//连接串。连接串可能包含数据 源名、数据源中用户的ID、密码和
其他信息。整个连接串必须 以”ODBC;”开头。”ODBC;”表示连接是一个ODBC数据源。
BOOL &bUseCursorLib=TRUE //如果希望加载ODBC光标动态连接库,
设定为TRUE
下面的例子表示如何打开数据源:
//在文档类中加入
//CDatabase类对象
CDatabase &m_
//连接对象到一个数据源(没有密码),ODBC连接对话框将是中隐藏
m_pdatabase.Open(_T(“students”),&FALSE,
FALSE, _T(“ODBC;&UID= Admin”));
//或者也可以显示ODBC对话框,请用户提供连接信息
m_pdatabase.Open(NULL);
像程序Sample
一样,通过向导生成数据库工程,不用添加代码就能实现对数据源的打开。在CRecordset类中有一个名为GetDefaultConnect()的虚函数值得
注意,通过调用它可以返回默认的数据源连接(也就是在生成工程的时候所选择 的数据源)来打开数据源。该函数如下:
CStringCSampleSet::GetDefaultConnect()
return_T(“ODBC;&&DSN=
students”);
使用CRecordste类打开记录集
通过声明 CRecordset记录集类的对象,再利用记录集类的Open()函数可打
开记录集,从而获取数据库中表的数据。也正是在调用Open()函数后,记录集当 中的成员变量得到数据源中表的字段值。Open()函数的形式如下:
virtual BOOL &Open(
UNIT&nOpenType
= AFX_DB_USE_DEFAULT_TYPE, LPCTSTR& lpszSQL&= NULL,
DWORD&&dwOptions &= none
其中 nOpenType为打开的类型,可取只有一下4
CRecordset::dynaset:双向滚动的记录集,在记录集打开时,记录的 顺序和成员就被确定了。其他用户对数据的修改在fetch操作之后才可
访问,这也被叫做键集驱动的记录集。
CRecordset::dynamic:双向滚动的记录集,其他用户对数据的修改在fetch操作后才可访问。许多ODBC驱动程序都不支持此种记录集。
CRecordset::ForwardOnly:只读记录集,只向前滚动。第二个参数lpszSQL是一个CString的指针,指向以下内容之一:
一个NULL指针;
一个表名;
一个SQL查询语句
第三个参数 dwOptions为一系列选项的组合,它的默认值为None。
可以像下面这样调用Open()函数来打开记录集:
CDatabase &m_
m_pdatabase.Open(_T(“students”),&FALSE,
FALSE, _T(“ODBC;UID=Admin”));
CRecordset Sample(&m_pdatabase);
Sample.Open(CRecordset::dynaset,_T(“Selectnamefrom students”));
以上语句先用CDatabase对象打开一个数据源,之后构造记录及对象,最后记录及对象Sample以动态方式打开students表中的name字段。
下面的语句表示以全部默认方式执行记录记得打开操作:
CDatabase &m_
m_pdatabase.Open(_T(“students”),&FALSE,
FALSE, _T(“ODBC;UID=Admin”));
CRecordset Sample(&m_pdatabase);Sample.Open();
也可以像下面代码中那样打开一个表中的所有字段:
CDatabase &m_
m_pdatabase.Open(_T(“students”),&FALSE,
FALSE, _T(“ODBC;UID=Admin”));
CRecordset Sample(&m_pdatabase);Sample.Open(CRecordset::dynaset,&_T(“Select*&from&students”));
经过上面的操作,记录集对象的字段变量就获得了数据库中特定表中指定字
段的数据。
像程序Sample
一样,在向导当中选择数据源和表名。在CRecordset类中有 一个名为GetDefaultSQL()的虚函数值得注意,通过调用它可以返回默认的SQL语
句,用于形成记录集对象。该函数如下:
CString CSampleSet::GetDefaultSQL()
return _T(“[students]”);
绑定记录集
通过向导创建工程后,程序的框架就生成出来。如果打开CRecordset的派 生类CSampleSet,会发现里面已经有了5个变量:
//Field/Param &Data
//{{AFX_FIELD(CSampleSet, &CRecordset)
long &m_ CString& m_ Long& m_ Long& m_
CString m_
//}}AFX_FIELD
这 5个变量正好与要访问的表中的字段同名,并且变量的类型也与字段类型 一致。这是MFC自动添加的变量,已绑定表中的字段。如果表中的字段是中文
的,那么MFC会创建m_column1、m_column2等与之对应。RFX实现了这种绑
RFX(RecordField Exchange),记录字段交换使记录集(CREcordset)和隐
藏于后台的数据源(Datasource)之间建立其对应的关系。用户只需要操作记录 集,就可以实现对数据源的操作。MFC中提供了一组RFX
调用函数,利用这些 函数,就可以使记录集中的变量与数据源中的字段对应起来。使记录集和数据之 间进行数据交换成为可能,并且,这种交换是双向的。
可以在 CSampleSet类的DoFieldExchange函数中看到一组组的RFX
函数调用, 正是通过调用它们,使CSampleSet记录集中的变量与
students表中的字段对应 起来。
void &CSampleSet::&DoFieldExchange(CFieldExchange *pFx)
{//{{AFX_FIELD_MAP(CSampleSet)
pFX-&SetFieldType(CFieldExchange::outputColumn);RFX_Long(pFX, &_T(“[id]”),&m_id);
RFX_Long(pFX, _T(“[name]”),&m_name);
RFX_Long(pFX, _T(“[department]”),&m_department);RFX_Long(pFX,
&_T(“[age]”),&m_age);
RFX_Long(pFX, _T(“[comment]”),&m_comment);
//}}AFX_FIELD_MAP
RFX 函数通常有3个参数(个别的会有4
或 5个)。第一个参数为一个指向CFieldExchange类对象的指针,第二个参数为数据源中的一个字段名称,第三个
参数是与字段相对应的记录集中的变量名。常用的RFX 函数如下表:
&RFX_Binary
CByteArray
&RFX_Double
&RFX_LongBinary
& CLongBinary
参数化记录集和查询
CRecordset 类对象中有两个成员变量,一个为 m_strFilter(过滤字符串,负责对记录集进行过滤,返回过滤后的记录),另一个为 m_strSort(排序字符串,对 记录集进行排序)。
m_strFilter 存放着 SQL 语句中 WHERE 子句的条件字符串,m_strSort 中则 存放着 SQL 语句中ORDER BY 子句的字符串。经过对它们的赋值,可以更加灵活 的获得数据库中特定的数据,以及对记录进行排序。
下面的代码中向 m_strFilter 赋值“comment=good”,向 m_strSort 赋值 “name”:
CRecordset S
Sample.m_strFilter = “comment = good”;
Sample.m_strSort = “name”;
除了直接向 m_strFilter 赋值外,还可以使用参数化。利用参数化可以更直观, 更方便地完成条件查询任务。使用参数化的步骤如下:
首先声明参变量:CString age1; CString&comment1;
在构造函数中初始化参变量
age1 &= _T(“”);
comment = _T(“”);
将参变量与对应列绑定
pFX-&SetFieldType(CFieldExchange::param);
pFX-&Text(pFX,& _T(“[age]”),&age1);
pFX-&Text(pFX,& _T(“[comment]”),& comment1);
最后利用参变量进行条件查询
m_pSet-&m_strFilter&= “age=&?&AND &comment = ?”;
m_pSet-&age& = “21”;
m_pSet-&comment& = “good”;
m_pSet-&Requery();
参变量的值按绑定的顺序替换查询字符串中的“?”适配符。代码中的 m_pSet 是 CRecordView 类的一个记录集指针,指向当前文档类中的记录集变量。它是在 CRecordView 类的 OnInitialUpdate 中被赋予文档类下记录集对象的指针的。下面是程序中 CSampleView 类的 OnInitialUpdate 函数体:
void &CSampleView::OnInitialUpdate()
{ //为 m_pSet 赋予文档类下的记录集对象的指针
m_pSet = &GetDocument()-&m_sampleSCRecordView::OnInitialUpdate(); ResizeParentToFit();
遍历记录集合
CRecordset 类中有一组函数负责记录集指针的移动,例如使用记录集指针下移一个记录、使用记录集指针上移一个记录等。
1、&MoveFirst()函数:使指针移动到第一条记录
2、&MoveLast()函数:使指针移动到最后一条记录
3、&MoveNext()函数:使指针移动到下一条记录
4、&MovePrev()函数:使指针移动到前一条记录
5、 IsBOF()函数:当指针移动到第一条记录前面或者表中没有记录的时候 返回真
6、& IsEOF()函数:当指针移动到最后一条记录后面的时候返回真知道上面的这些函数的意义后,下面来看如何遍历记录集。下面的代码中
m_pSet 是一个记录集指针,m_list 为一个列表框控件(ClistBox 类)的变量:
if(!m_pSet-&IsOpen()) //用 IsOpen 函数检测记录集是否打开
m_pSet-&Open(); m_pSet-&MoveFirst();while(!m_pSet-&IsEOF())
m_list.AddString(m_pSet-&m_name);
m_pSet-&MoveNext();
m_pSet-&MoveFirst(); //遍历完成后,使记录集指针指向第一条记录
书签定位和绝对定位
当在记录集中浏览的时候,可能想返回记录集中特定的一条记录,CRecordset 提供了两种方法可以指定记录集到特定的位置。
1、&书签定位
可以在记录集中的某一条记录增加一个书签。在记录集浏览时由于用户的增
删操作使记录的绝对位置发生改变,所以以来绝对位置是不可靠的。因此需要使 用书签定位来为所想要的记录定位。CRecordset 类中提供的书签定位的方法是
GetBookmark 和 SetBookmark 两个函数,他们的原型如下:
void &GetBookmark(CDBVariant& varBookmark); //参数为 CDBVariant 的对
void &SetBookmark(const CDBVariant& varBookmark);
这里只需直接使用 CDBVariant 的对象即可。
//创建 CDBVariant 对象
//rs是 CRecordset 类或 CRecordset 类派生类的对象
rs.GetBookmark(bookmark);
//一系列移动到其他记录的代码
rs.MoveNext(); rs.MoveNext(); rs.SetBookmark(bookmark);
GetBookmark 函数将当前的记录存入一个 CDBVariant 的对象中,经过一系
列的纪录移动之后,在调用 SetBookmark,并且用刚才记录“书签”的
CDBVariant 对象 bookmark 作参数来使用当前记录集重新指向“书签”的位置。
是否支持书签定位取决于 ODBC 驱动程序和记录集类型。可以通过调用 CRecordset::CanBookmark 来确定是否支持书签定位。如果想支持书签定位,还 需要在记录集的 Open 函数的 dwOptions 参数位置中加入 CRecordset::useBookmarks 参数。注意 forward-only recordsets(只向前)类型的记录集也不支持书签定位。还有一点,就是在某些记录集操作之后,也应该及时检查 前面所设置的“书签”是否还可以继续使用。例如,对一个记录及进行了
Requery 操作之后,书签就可能不再有效了。所以,在调用 SetBookmark 函数之前,应该 先调用CDatabase::GetBookmarkPersistence 函数来核对是否可以安全的调用 SetBookmark函数。下面是该函数原型:DWORD GetBookmarkPersistence()
这个函数的返回值为 bitmask,这是一个 DWORD 类型的返回值。该值可以 是下表中的多个 bitmask 值的组合。
bitmask 值
书签的有效性
&SQL_BP_CLOSE
Requery 操作后,书签有效
&SQL_BP_DELETE
对某行执行 delete 操作后,书签对此行依然有效
&SQL_BP_DROP
一次 Close 操作后,书签有效
&SQL_BP_SCROLL
任何 Move 操作之后,书签都有效
&SQL_BP_TRANSACTION
一次事务被提交或回滚后,书签有效
&SQL_BP_UPDATE
对某行执行 Update 操作后,书签对此行有效
&SQL_BP_OTHER_HSTMT
与某记录集对象相关的书签对另一记录集也有效
2、& 绝对定位
相对于书签定位,绝对定位就好像记住某本书的某一个固定页码一样。绝对 定位就是通过原始的记录位置来设置当前记录,比如可以设置记录集中第 8 条记 录为当前记录。如想使用绝对定位来改变当前的记录集位置,可以调用 CRecordset::SetAbsolutePosition 函数。其原型为:
void &SetAbsolutePosition(long&nRows);
nRows表示记录集中的一个绝对位置。调用该函数会把记录集指针定位到
nRows 参数所指行号的记录上。
下面的代码表示把记录集定位到第 12 条记录的位置上:
long & row = 12; rs.SetAbsolutePositon(row);
对于 ODBC 的记录集来说,绝对位置 1 指的是记录集当中的第一条记录,
绝对位置如果是 0 则代表的是 BOF 位置(在第一条记录之前)。
(***forward-only&recordsets(只向前)类型的记录集不支持SetAbsolutePosition方法。此外,记录的绝对位置存在潜在的不可靠性。如果用户删除了某一条记录,那么后续记录的位置都发上变化,并且记录集也可能被再
次重新创建,不能确保某条记录在创建的记录集中有与原来相同位置,因此建议使用书签定位。 &***)
获取记录集的数据
通过在对话框上添加控件,并且为控件绑定变量来达到数据交换并显示的目
的,与控件绑定的变量正是记录集中的那些字段变量。步骤如下:
l按照所需显示的字段数量,在对话框窗体上添加几个编辑框控件,将控 件的ID改成与表中字段相似的名称
l再按住Ctrl的同时双击每一个控件,为它们增加成员变量
l在AddMember Variable对话框中单击“Membervariable
name”下拉框, 为每个控件一次选择记录集中的各个变量。
到底记录集中的变量是如何把数据显示在控件上呢?
下面讲述DDX
DDX 是DialogData
Exchange的缩写,即对话框数据交换。它在对话框的控 件与记录集的变量之间建立起一座桥梁,可以使他们双向交换数据。
CRecordView 类里面有一个DoDataExchange
函数,所有的DDX函数都是在
DoDataExchange中调用的。DoDataExchange函数为DDX
函数提供了一个CDataExchange类对象的指针。在工程刚刚创建时,CSampleView::DodataExchange函数是一个空函数,因此此时对话框上并没有控
件,更没有与控件对应的变量。但经过窗体添加控件、为控件添加变量之后,再打开DoDataExchange函数,将会出现下面这样的代码:
void &CSampleView::DoDataExchange(CDataExchange*&pDX)
{ CRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSampleView)
DDX_FieldText(pDX,
IDC_ID,m_pSet-&m_id,& m_pSet); DDX_FieldText(pDX,& IDC_NAME, &m_pSet-&m_name,& m_pSet); DDX_FieldText(pDX, IDC_DEPARTMENT,& m_pSet-&m_department,& m_pSet); DDX_FieldText(pDX, IDC_AGE, &m_pSet-&m_age,&m_pSet); DDX_FieldText(pDX, IDC_COMMENT, &m_pSet-&m_comment,&
//}}AFX_DATA_MAP
DDX_FieldText 函数负责在对话框控件和记录集中字段变量之间建立联系。
因为记录集中的字段变量对应的是数据库中表的每个字段,所以就能在控件上看到表中的数据了。DDX函数有四个参数,分别为:
l一个指向CDateExchange类对象的指针
l对话框上控件的ID值
l记录集中要与对象绑定的字段变量
l记录集对象的指针
DDX 可以管理以下类型数据变量与控件的数据交换。它们是short、long、int、
DWORD、CString、float、double、BOOL以及BYTE。
程序通过 UpdateData这个函数在控件与变量之间达到双向数据,而不是直 接调用DoDataExchange。UpdateData函数的原型如下:
BOOL &UpdateData(BOOL&bSaveAndValidate=TRUE);
bSaveAndValidate
指示了数据传输的方向,当为TRUE时就是控件向变量 传输。反之,就是变量向控件传输数据。默认值为TRUE
对记录的操作大多数都是由 CRecordset类来负责的,执行添加的任务也不
例外。CRecordset类中的函数AddNew()表示向表中添加一条新的纪录,该函数
原型如下:
virtual void &AddNew();
执行 AddNew()函数之后会新增加一条空记录,等待输入数据。此时记录的 每一个字段都被初始化NULL。在输入新的记录数据之后,需调用另一个CRecordset类的函数才能完成对新记录的添加,这个函数是Update(),函数原型
为:virtual BOOL Update();
在调用完 AddNew函数、输入新数据之后一定要调用Update,它负责把新
添加的数据保存到数据源。实际上AddNew函数只是在内存中创建了一块缓冲 区,等待输入数据,之后需要使用Update来真正把数据存入数据源。如果在调
用Update之前滚动到了另一条记录,那么新记录就会丢失,也不会提出警告。 对于dynaset(动态集)类型的记录集,新记录会添加到末尾。新记录不能被添
加到Snapshot类型的记录集中。最后还需要调用CRecordset::Requery函数以刷
新记录集:virtual BOOL Requery();
Requery 函数负责刷新记录集来反映当前最新的数据。在每次对记录进行添
加、删除后,都有必要调用Requery来更新记录集。调用Requery函数后,记录
集指针重新指向第一条记录。
下面的代码实现了在一个名为 OnAdd的函数中添加记录:
void &CSampleView::OnAdd()
//添加一条新记录
m_pSet-&AddNew();
//对记录集中的m_id、m_name、m_department、m_age等赋值
m_pSet-&m_id&= “1009”; m_pSet-&m_name&= “Jack”; m_pSet-&m_department&
= “3”; m_pSet-&m_age& = “20”;
m_pSet-&m_comment&= “good”;
//更新记录集,将新记录存入数据源
m_pSet-&Update();
//刷新记录集,并使记录集指针回到第一条记录
m_pSet-&Requery();
调用 CRecordset类中的Delete
函数进行删除记录。该函数用于删除当前记 录集指针指向的记录。原型如下:virtual void Delete();
一次成功的删除后,被删除记录的字段全部被设为
NULL,必须调用Move函数移动到其他记录上来一处被删除的记录。如果删除不成功,记录中的数据也
不会被破坏。一旦移除了删除的记录,就再也不能返回他了。在调用Delete
函 数时,记录集中必须有一条有效的记录,否则会产生错误。。如果Delete
条记录,但没有
Move到另一条记录就有进行了Delete操作,Delete会产生一个
CDBException类的错误。
下面的代码在一个名为 OnDelete的函数中实现了删除当前记录的操作:
void &CSampleView::OnDelete()
//删除当前记录
m_pSet-&Delete();
//刷新记录集
m_pSet-&Requery();
CRecordset::Edit
函数的作用是允许修改当前的记录。原型如下:
virtual void &Edit();
调用 Edit之后,就可以直接重新设定当前记录中每个字段的值了。再重新
设定之后,还需要调用 Update函数来保存对数据的修改。实际上,调用Edit之
后,要被修改的值先被保存起来。如果Edit之后没有Update,而是移动到另一
条记录,那么记录以前的值被重新恢复,不对记录作出修改。或者,调用了一次Edit,而对记录也作出了修改,然后又调用了一次Edit,那么记录还是被恢复到
第一次调用Edit之前的值。
下面的代码在名为 OnEdit的函数中实现对数据的编辑:
void &CSampleView::OnEdit()
m_pSet-&Edit();
m_pSet-&m_id&= m_
m_pSet-&m_name&= m_
m_pSet-&m_department&= m_
m_pSet-&m_age&= m_
m_pSet-&m_comment&= m_
m_pSet-&Update();
m_pSet-&Requery();
直接执行 SQL语句(增加、删除表等)
并不是所有的 ODBC功能都被数据库类所支持,所以有时候需要使用直接 执行
SQL语句来对数据库进行一些操作。
CDatabase 类中有一个函数ExecuteSQL,通过它可以直接执行SQL语句,
对数据库进行操作。原型如下:void ExecuteSQL(LPCTSTR lpszSQL);
参数 lpszSQL是一个CString类型的指针,包含一条可执行的、有效地SQL
命令。这个函数并不返回信息,如果要对记录进行操作,那么还是要使用记录集 对象。
下面的代码可以在一个名为 class的表中增加一条记录。m_database是一个CDatabase类的对象。VALUES中是新增记录的具体值,分别于表中的每一个字
段相对应。
m_pSet-&Open();
m_pSet-&AddNew();
m_database.ExecuteSQL(“insertinto
VALUES(,,006","Mary","19","FEMALE")”);
m_pSet.Update();
m_pSet-&Edit();
m_database.ExecuteSQL(“Delete&from &class WHERE Name& &= ,,Mary"”);
m_pSet.Update();
事务操作涉及 CDatabase类的几个成员函数,BeginTrans表示开始事务,
CommitTrans表示接受所有对数据源的修改,或者调用Rollback来终止整个事务。
执行事务的三个步骤:
l调用CDatabase类对象的BeginTrans成员函数开始事务
l调用AddNew-&Update、Edit-&Update、Delete等函数对同一数据库的一
个或者多个记录集进行一系列的添加、修改、删除操作
l调用CDatabase类的CommitTrans函数执行所有添加、修改、删除操作。如果一次更新出现错误,或者决定取消那些操作,调用Rollback函数。
下面的代码中要删除一家商店中的一项商品,因为要将两个记录集中涉及该商品的所有记录同时删除,所以要使用事务处理。记录集orderset为订单记录,
记录集 goodsset为商品品种记录。m_shop为CDatabase类对象,假设它已经连
接到了数据源。strgoodsID为用户输入的要删除商品的ID。两个记录集中都使用m_strFilter变量来过滤出要删除的记录。
BOOL &CShopDoc::RemoveGoods(CString&strgoodsID)
{//开始事务
if(!m_shop.BeginTrans())
return FALSE;
//创建订单记录集
COrderSet &orderset(&m_shop);
orderset.m_strFilter
=“goodsID &=” + strgoodsID;
if(!orderset.Open(CRecordset::dynaset))
return FALSE;
//创建商品记录集
CGoodsSet goodsset(&m_shop);
goodsset.m_strFilter
=“goodsID &=” + strgoodsID;
if(!goodsset.Open(CRecordset::dynaset))
return FALSE;
//操作中使用了try…catch()来捕获错误信息
//因为有时会经常出现一些意想不到的错误
{//删除订单记录
while(!orderSet.IsEOF())
{ orderset.Delete();orderset.MoveNext();
//删除商品条目
goodsset.Delete();
//执行事务
mitTrans();
} CATCH_ALL(e)
{//取消事务
m_shop.Rollback();
return FALSE;
} END_CATCH_ALL
//关闭记录集
orderset.Close();
goodsset.Close();returnTRUE;
使用多记录集
有时候需要使用多个记录集,以使在一个程序中可以操作多个表。生成工程 时,通常只选择一个表作为记录集要对应的对象。而且就算在生成工程时选择多 个表,那么AppWizard也只会产生多个表的一个笛卡尔乘积,并不会为每一个表产生一个记录集。
通过 Visual C++ 6.0的ClassWizard来为所需要的每个表创建一个与之对应
的记录集。
“View”à &“ClassWizard”à &“Add
Class”à &“New” &à &“New &Class对话 框”填入Name,”BaseClass”中选择
&CRecordset&单击”OK”à“DatabaseOptions”&选择ODBC
作为数据源,在下拉框中选择已注册的某个数据源,Recordset type
选择 dynaset,单击”OK”
&à &“Select &Database Tables对话框”,在其中选择想 要访问的表后单击”OK”。这样一个CRecordset类的派生类就创建好了。在需要使
用该派生类的类中#include“***.h”(该派生类的同文件)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:194330次
积分:3479
积分:3479
排名:第7123名
原创:156篇
评论:19条
(1)(1)(5)(10)(1)(1)(3)(62)(7)(11)(60)(1)(2)

我要回帖

更多关于 c语言求最大值最小值 的文章

 

随机推荐