📄 chap10_5.htm
字号:
<tr>
<td width="39%">
<p align="JUSTIFY">CRecordset::readOnly
</td>
<td width="61%">
<p align="JUSTIFY">记录集是只读的.
</td>
</tr>
<tr>
<td width="39%">
<p align="JUSTIFY">CRecordset::skipDeletedRecords
</td>
<td width="61%">
<p align="JUSTIFY">有些数据库(如FoxPro)在删除记录时并不真删除,而是做个删除标记,在滚动时将跳过这些被删除的记录.
</td>
</tr>
</table>
<p> </p>
<p align="JUSTIFY"> </p>
<blockquote>
<blockquote>
<p align="JUSTIFY">virtual CString GetDefaultSQL( );<br>
Open函数在必要时会调用该函数返回缺省的SQL语句或表名以查询数据源中的记录.一般需要在CRecordset派生类中覆盖该函数并在新版的函数中提供SQL语句或表名.下面是一些返回字符串的例子.<br>
“Section” //选择Section表中的所有记录到记录集中<br>
“Section, Course” //合并Section表和Course表的各列到记录集中</p>
<p align="JUSTIFY">//对Section表中的所有记录按CourseID的升序进行排序,然后建立记录集</p>
<p align="JUSTIFY">“SELECT * FROM Section ORDER BY CourseID ASC”</p>
</blockquote>
</blockquote>
<p align="JUSTIFY"> 上面的例子说明,通过合理地安排SQL语句和表名,Open函数可以十分灵活地查询数据源中的记录.用户可以合并多个表的字段,也可以只选择记录中的某些字段,还可以对记录进行过滤和排序.</p>
<p align="JUSTIFY"> 上一小节说过,在建立记录集时,CRecordset会构造一个SELECT语句来查询数据源.如果在调用Open时只提供了表名,那么SELECT语句还缺少选择列参数rfx-field-list(参见10.5.3).框架规定,如果只提供了表名,则选择列的信息从DoFieldExchange中的RFX语句里提取.例如,如果在调用Open时只提供了"Section"表名,那么将会构造如下一个SELECT语句:</p>
<p align="JUSTIFY">SELECT CourseID,SectionNo,InstructorID,RoomNo, Schedule,Capacity
FROM Section</p>
<p align="JUSTIFY"> </p>
<p align="JUSTIFY"> 建立记录集后,用户可以随时调用Requery成员函数来重新查询和建立记录集.Requery有两个重要用途:</p>
<ul>
<li>
<p align="JUSTIFY">使记录集能反映用户对数据源的改变(参见10.5.1).</p>
</li>
<li>
<p align="JUSTIFY">按照新的过滤或排序方法查询记录并重新建立记录集.</p>
</li>
</ul>
<p> </p>
<p align="JUSTIFY"> 在调用Requery之前,可调用CanRestart来判断记录集是否支持Requery操作.要记住Requery只能在成功调用Open后调用,所以程序应调用IsOpen来判断记录集是否已建立.函数的声明为</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">virtual BOOL Requery( );throw( CDBException,
CMemoryException );<br>
返回TRUE表明记录集建立成功,否则返回FALSE.若函数内部出错则产生异常.</p>
<p align="JUSTIFY">BOOL CanRestart( ) const; //若支持Requery则返回TRUE</p>
<p align="JUSTIFY">BOOL IsOpen( ) const; //若记录集已建立则返回TRUE</p>
</blockquote>
</blockquote>
<p align="JUSTIFY"> CRecordset类有两个公共数据成员m_strFilter和m_strSort用来设置对记录的过滤和排序.在调用Open或Requery前,如果在这两个数据成员中指定了过滤或排序,那么Open和Requery将按这两个数据成员指定的过滤和排序来查询数据源.</p>
<p align="JUSTIFY">成员m_strFilter用于指定过滤器.m_strFilter实际上包含了SQL的WHERE子句的内容,但它不含WHERE关键字.使用m_strFilter的一个例子为:</p>
<p align="JUSTIFY">m_pSet->m_strFilter=“CourseID=‘MATH101’”; //只选择CourseID为MATH101的记录</p>
<p align="JUSTIFY">if(m_pSet->Open(CRecordset::snapshot, “Section”))</p>
<p align="JUSTIFY"><b>. . . . . .</b></p>
<p align="JUSTIFY"> 成员m_strSort用于指定排序.m_strSort实际上包含了ORDER BY子句的内容,但它不含ORDER
BY关键字.m_strSort的一个例子为</p>
<p align="JUSTIFY">m_pSet->m_strSort=“CourseID DESC”; //按CourseID的降序排列记录</p>
<p align="JUSTIFY">m_pSet->Open();</p>
<p align="JUSTIFY"><b>. . . . . .</b></p>
<p align="JUSTIFY"> 事实上,Open函数在构造SELECT语句时,会把m_strFilter和m_strSort的内容放入SELECT语句的WHERE和ORDER
BY子句中.如果在Open的lpszSQL参数中已包括了WHERE和ORDER BY子句,那么m_strFilter和m_strSort必需为空.</p>
<p align="JUSTIFY"> 调用无参数成员函数Close可以关闭记录集.在调用了Close函数后,程序可以再次调用Open建立新的记录集.CRecordset的析构函数会调用Close函数,所以当删除CRecordset对象时记录集也随之关闭。</p>
<p><font color="#3973DE" face="Times New Roman" size="3">10.5.5 </font><font size="3" color="#3973DE">滚动记录</font></p>
<p align="JUSTIFY"> CRecordset提供了几个成员函数用来在记录集中滚动,如下所示.当用这些函数滚动到一个新记录时,框架会自动地把新记录的内容拷贝到域数据成员中.</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">void MoveNext( ); //前进一个记录</p>
<p align="JUSTIFY">void MovePrev( ); //后退一个记录</p>
<p align="JUSTIFY">void MoveFirst( ); //滚动到记录集中的第一个记录</p>
<p align="JUSTIFY">void MoveLast( ); //滚动到记录集中的最后一个记录</p>
<p align="JUSTIFY">void SetAbsolutePosition( long nRows ); <br>
该函数用于滚动到由参数nRows指定的绝对位置处.若nRows为负数,则从后往前滚动.例如,当nRows为-1时,函数就滚动到记录集的末尾.注意,该函数不会跳过被删除的记录.</p>
<p align="JUSTIFY">virtual void Move( long nRows, WORD wFetchType
= SQL_FETCH_RELATIVE );<br>
该函数功能强大.通过将wFetchType参数指定为SQL_FETCH_NEXT、SQL_FETCH_PRIOR、SQL_FETCH_FIRST、SQL_FETCH_LAST和SQL_FETCH_ABSOLUTE,可以完成上面五个函数的功能.若wFetchType为SQL_FETCH_RELATIVE,那么将相对当前记录移动,若nRows为正数,则向前移动,若nRows为负数,则向后移动.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY"> 如果在建立记录集时选择了CRecordset::skipDeletedRecords选项,那么除了SetAbsolutePosition外,在滚动记录时将跳过被删除的记录,这一点对象FoxPro这样的数据库十分重要.</p>
<p align="JUSTIFY"> 如果记录集是空的,那么调用上述函数将产生异常.另外,必须保证滚动没有超出记录集的边界.调用IsEOF和IsBOF可以进行这方面的检测.</p>
<p align="JUSTIFY"> </p>
<blockquote>
<blockquote>
<p align="JUSTIFY">BOOL IsEOF( ) const;<br>
如果记录集为空或滚动过了最后一个记录,那么函数返回TRUE,否则返回FALSE.</p>
<p align="JUSTIFY">BOOL IsBOF( ) const;<br>
如果记录集为空或滚动过了第一个记录,那么函数返回TRUE,否则返回FALSE.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY">下面是一个使用IsEOF的例子:</p>
<p align="JUSTIFY">while(!m_pSet->IsEOF( ))</p>
<p align="JUSTIFY">m_pSet->MoveNext( );</p>
<p align="JUSTIFY">调用GetRecordCound可获得记录集中的记录总数,该函数的声明为</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">long GetRecordCount( ) const;<br>
要注意这个函数返回的实际上是用户在记录集中滚动的最远距离.要想真正返回记录总数,只有调用MoveNext移动到记录集的末尾(MoveLast不行).</p>
</blockquote>
</blockquote>
<p><b> </b></p>
<p align="JUSTIFY"> <b></b><font color="#3973DE" face="Times New Roman" size="3">10.5.6
</font><font size="3" color="#3973DE">修改、添加和删除记录</font></p>
<p align="JUSTIFY">要修改当前记录,应该按下列步骤进行:</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">调用Edit成员函数.调用该函数后就进入了编辑模式,程序可以修改域数据成员.注意不要在一个空的记录集中调用Edit,否则会产生异常.Edit函数会把当前域数据成员的内容保存在一个缓冲区中,这样做有两个目的,一是可以与域数据成员作比较以判断哪些字段被改变了,二是在必要的时侯可以恢复域数据成员原来的值.若再次调用Edit,则将从缓冲区中恢复域数据成员,调用后程序仍处于编辑模式.调用Move(AFX_MOVE_REFRESH)或Move(0)可退出编辑模式(AFX_MOVE_REFRESH的值为0),同时该函数会从缓冲区中恢复域数据成员.</p>
<p align="JUSTIFY">设置域数据成员的新值.</p>
<p align="JUSTIFY">调用Update完成编辑.Update把变化后的记录写入数据源并结束编辑模式.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY">要向记录集中添加新的记录,应该按下列步骤进行:</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">调用AddNew成员函数.调用该函数后就进入了添加模式,该函数把所有的域数据成员都设置成NULL(注意,在数据库术语中,NULL是指没有值,这与C++的NULL是不同的).与Edit一样,AddNew会把当前域数据成员的内容保存在一个缓冲区中,在必要的时侯,程序可以再次调用AddNew取消添加操作并恢复域数据成员原来的值,调用后程序仍处于添加模式.调用Move(AFX_MOVE_REFRESH)可退出添加模式,同时该函数会从缓冲区中恢复域数据成员.</p>
<p align="JUSTIFY">设置域数据成员.</p>
<p align="JUSTIFY">调用Update.Update把域数据成员中的内容作为新记录写入数据源,从而结束了添加.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY">如果记录集是快照,那么在添加一个新的记录后,需要调用Requery重新查询,因为快照无法反映添加操作.</p>
<p align="JUSTIFY">要删除记录集的当前记录,应按下面两步进行:</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">调用Delete成员函数.该函数会同时给记录集和数据源中当前记录加上删除标记.注意不要在一个空记录集中调用Delete,否则会产生一个异常.</p>
<p align="JUSTIFY">滚动到另一个记录上以跳过删除记录.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY">上面提到的函数声明为:</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">virtual void Edit( );throw( CDBException, CMemoryException
);</p>
<p align="JUSTIFY">virtual void AddNew( );throw( CDBException );</p>
<p align="JUSTIFY">virtual void Delete( );throw( CDBException );</p>
<p align="JUSTIFY">virtual BOOL Update( );throw( CDBException );
<br>
若更新失败则函数返回FALSE,且会产生一个异常.</p>
</blockquote>
</blockquote>
<p> </p>
<p align="JUSTIFY"> 在对记录集进行更改以前,程序也许要调用下列函数来判断记录集是否是可以更改的,因为如果在不能更改的记录集中进行修改、添加或删除将导致异常的产生.</p>
<blockquote>
<blockquote>
<p align="JUSTIFY">BOOL CanUpdate( ) const; //返回TRUE表明记录是可以修改、添加和删除的.</p>
<p align="JUSTIFY">BOOL CanAppend( ) const; //返回TRUE则表明可以添加记录.</p>
</blockquote>
</blockquote>
<div align="center">
<center>
<table border="0" cellpadding="0" cellspacing="0" width="615">
<tr>
<td><a href="chap10_4.htm">上一页</a></td>
<td>
<p align="right"><a href="chap10_6.htm">下一页</a>
</td>
</tr>
</table>
<p><a href="http://www.cpcw.com">电脑报首页</a> <a href="../../index.htm">网络学院首页</a></p>
</center>
</div>
<font size="5">
<hr noshade color="#3973DE" size="1">
</font>
<p align="center"><font size="5"></font><font size="2" color="#000000">本教程由<a href="http://vcdynasty.yeah.net">Visual
C++王朝(Where programmers come together)</a>协助制作<br>
未经许可,请勿以任何形式复制</font>
</td>
</tr>
</table>
</center>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -