CRecordset
类
表示从数据源选择的一组记录。
语法
class CRecordset : public CObject
成员
公共构造函数
名称 | 描述 |
---|---|
CRecordset::CRecordset |
构造 CRecordset 对象。 派生类必须提供调用此类的构造函数。 |
公共方法
名称 | 描述 |
---|---|
CRecordset::AddNew |
准备添加新记录。 调用 Update 以完成添加。 |
CRecordset::CanAppend |
如果可以通过 AddNew 成员函数将新记录添加到记录集中,则返回非零值。 |
CRecordset::CanBookmark |
如果记录集支持书签,则返回非零值。 |
CRecordset::Cancel |
从第二个线程取消异步操作或进程。 |
CRecordset::CancelUpdate |
由于 AddNew 或 Edit 操作,取消任何挂起的更新。 |
CRecordset::CanRestart |
如果可以调用 Requery 以再次运行记录集的查询,则返回非零值。 |
CRecordset::CanScroll |
如果可以滚动浏览记录,则返回非零值。 |
CRecordset::CanTransact |
如果数据库支持事务,则返回非零。 |
CRecordset::CanUpdate |
如果可以更新记录集(可以添加、更新或删除记录),则返回非零值。 |
CRecordset::CheckRowsetError |
调用以处理记录提取期间生成的错误。 |
CRecordset::Close |
关闭记录集及其关联的 ODBC HSTMT 。 |
CRecordset::Delete |
从记录集中删除当前记录。 删除后,必须显式滚动到另一条记录。 |
CRecordset::DoBulkFieldExchange |
调用以将批量数据行从数据源交换到记录集。 实现批量记录字段交换(批量 RFX)。 |
CRecordset::DoFieldExchange |
调用以在记录集的字段数据成员与数据源上的相应记录之间(双向)交换数据。 实现记录字段交换 (RFX)。 |
CRecordset::Edit |
准备对当前记录进行更改。 调用 Update 以完成编辑。 |
CRecordset::FlushResultSet |
如果使用预定义查询时要检索另一个结果集,则返回非零值。 |
CRecordset::GetBookmark |
将记录的书签值分配给参数对象。 |
CRecordset::GetDefaultConnect |
调用以获取默认的连接字符串。 |
CRecordset::GetDefaultSQL |
调用以获取要执行的默认 SQL 字符串。 |
CRecordset::GetFieldValue |
返回记录集中字段的值。 |
CRecordset::GetODBCFieldCount |
返回记录集中的字段数。 |
CRecordset::GetODBCFieldInfo |
返回有关记录集中字段的特定类型信息。 |
CRecordset::GetRecordCount |
返回记录集中的记录数。 |
CRecordset::GetRowsetSize |
返回希望在单个提取期间检索的记录数。 |
CRecordset::GetRowsFetched |
返回提取期间检索的实际行数。 |
CRecordset::GetRowStatus |
返回提取后行的状态。 |
CRecordset::GetSQL |
获取用于为记录集选择记录的 SQL 字符串。 |
CRecordset::GetStatus |
获取记录集状态:当前记录索引以及是否已获取记录的最终计数。 |
CRecordset::GetTableName |
获取记录集所基于的表的名称。 |
CRecordset::IsBOF |
如果在第一条记录之前定位了记录集,则返回非零值。 没有最新记录。 |
CRecordset::IsDeleted |
如果记录集位于已删除的记录上,则返回非零值。 |
CRecordset::IsEOF |
如果记录集位于最后一条记录之后,则返回非零值。 没有最新记录。 |
CRecordset::IsFieldDirty |
如果当前记录中的指定字段已更改,则返回非零值。 |
CRecordset::IsFieldNull |
如果当前记录中的指定字段为 null(没有值),则返回非零值。 |
CRecordset::IsFieldNullable |
如果当前记录中的指定字段可以设置为 null(没有值),则返回非零值。 |
CRecordset::IsOpen |
如果此前调用过 Open ,则返回非零值。 |
CRecordset::Move |
将记录集置于任一方向上当前记录的指定数目记录。 |
CRecordset::MoveFirst |
将当前记录放置在记录集中的第一条记录上。 首先测试 IsBOF 。 |
CRecordset::MoveLast |
将当前记录放置在最后一条记录或最后一行集上。 首先测试 IsEOF 。 |
CRecordset::MoveNext |
将当前记录放置在下一条记录或下一行集上。 首先测试 IsEOF 。 |
CRecordset::MovePrev |
将当前记录放置在前一条记录或前一行集上。 首先测试 IsBOF 。 |
CRecordset::OnSetOptions |
调用以为指定 ODBC 语句设置选项(在选择时使用)。 |
CRecordset::OnSetUpdateOptions |
调用以为指定 ODBC 语句设置选项(在更新时使用)。 |
CRecordset::Open |
通过检索表或执行记录集所表示的查询来打开记录集。 |
CRecordset::RefreshRowset |
刷新指定行的数据和状态。 |
CRecordset::Requery |
再次运行记录集的查询以刷新所选记录。 |
CRecordset::SetAbsolutePosition |
将记录集放置在对应于指定记录编号的记录上。 |
CRecordset::SetBookmark |
将记录集放置在书签指定的记录上。 |
CRecordset::SetFieldDirty |
将当前记录中的指定字段标记为已更改。 |
CRecordset::SetFieldNull |
将当前记录中指定字段的值设置为 null(没有值)。 |
CRecordset::SetLockingMode |
将锁定模式设置为“乐观”锁定(默认)或“悲观”锁定。 确定如何锁定记录以进行更新。 |
CRecordset::SetParamNull |
将指定参数设置为 null(没有值)。 |
CRecordset::SetRowsetCursorPosition |
将游标置于行集中的指定行上。 |
CRecordset::SetRowsetSize |
指定希望在提取期间检索的记录数。 |
CRecordset::Update |
通过在数据源上保存新数据或编辑的数据来完成 AddNew 或 Edit 操作。 |
公共数据成员
“属性” | 描述 |
---|---|
CRecordset::m_hstmt |
包含记录集的 ODBC 语句句柄。 键入 HSTMT 。 |
CRecordset::m_nFields |
包含记录集中的字段数据成员数。 键入 UINT 。 |
CRecordset::m_nParams |
包含记录集中的参数数据成员数。 键入 UINT 。 |
CRecordset::m_pDatabase |
包含指向 CDatabase 对象的指针,记录集通过该对象连接到数据源。 |
CRecordset::m_strFilter |
包含指定结构化查询语言 (SQL) WHERE 子句的 CString 。 用作筛选器,仅选择满足特定条件的记录。 |
CRecordset::m_strSort |
包含一个指定 SQL ORDER BY 子句的 CString 。 用于控制记录的排序方式。 |
备注
称为“记录集”,CRecordset
对象通常采用两种形式:动态集和快照。 动态集与其他用户进行的数据更新保持同步。 快照是数据的静态视图。 每个窗体表示一组在打开记录集时固定的记录。 滚动到动态集中的记录时,它会反映其他用户或应用程序中其他记录集对记录所做的更改。
注意
如果使用数据访问对象 (DAO) 类而不是开放式数据库连接 (ODBC) 类,请改用 CDaoRecordset
类。 有关详细信息,请参阅概述:数据库编程。
若要使用任一类型的记录集,通常从 CRecordset
中派生特定于应用程序的记录集类。 记录集从数据源中选择记录,然后可以:
滚动浏览记录。
更新记录并指定锁定模式。
筛选记录集以约束它从数据源上可用的记录中选择的记录。
对记录集进行排序。
参数化记录集以使用在运行时之前未知的信息自定义其选择。
若要使用类,请打开数据库并构造记录集对象,并将构造函数传递给指向 CDatabase
对象的指针。 然后调用记录集的 Open
成员函数,可在其中指定对象是动态集还是快照。 调用 Open
会从数据源中选择数据。 打开记录集对象后,使用其成员函数和数据成员滚动浏览记录并对其执行操作。 可用的操作取决于对象是动态集还是快照,它是可更新的还是只读(这取决于开放式数据库连接 (ODBC) 数据源的功能),以及是否实现了批量行提取。 若要刷新自调用 Open
以来可能已更改或添加的记录,请调用对象的 Requery
成员函数。 调用对象的 Close
成员函数,并在使用结束时销毁该对象。
在派生 CRecordset
类中,记录字段交换 (RFX) 或批量记录字段交换(批量 RFX)用于支持读取和更新记录字段。
有关记录集和记录字段交换的详细信息,请参阅文章概述:数据库编程、记录集 (ODBC)、记录集:批量提取记录 (ODBC),以及记录字段交换 (RFX)。 有关动态集和快照的焦点,请参阅动态集和快照文章。
继承层次结构
CRecordset
要求
标头:afxdb.h
CRecordset::AddNew
准备向表添加新记录。
virtual void AddNew();
备注
必须调用 Requery
成员函数才能查看新添加的记录。 记录的字段最初为 Null。 (在数据库术语中,Null 表示“没有值”,并且与 C++ 中的 NULL 不同。)若要完成该操作,必须调用 Update
成员函数。 Update
保存对数据源的更改。
注意
如果已实现批量行提取,则无法调用 AddNew
。 这将导致断言失败。 虽然类 CRecordset
不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos
编写自己的函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
AddNew
使用记录集的字段数据成员准备新的空记录。 调用 AddNew
后,在记录集的字段数据成员中设置所需的值。 (不需要为此调用 Edit 成员函数;仅对现有记录使用 Edit
。)调用 Update
时,字段数据成员中的更改值将保存在数据源上。
注意
如果在调用 Update
之前滚动到新记录,则新记录将丢失,并且不会发出任何警告。
如果数据源支持事务,则可以调用 AddNew
作为事务的一部分。 有关事务的详细信息,请参阅 CDatabase
类。 在调用 AddNew
之前调用 CDatabase::BeginTrans
。
注意
对于动态集,新记录将作为最后一条记录添加到记录集中。 未将添加的记录添加到快照中;必须调用 Requery
来刷新记录集。
对未调用 Open
成员函数的记录集调用 AddNew
是非法的。 如果对无法追加到的记录集调用 AddNew
,则会引发 CDBException
。 可以通过调用 CanAppend
来确定记录集是否可更新。
有关详细信息,请参阅以下文章:记录集:记录集如何更新记录 (ODBC)、记录集:添加、更新和删除记录 (ODBC) ,以及事务 (ODBC)。
示例
CRecordset::CanAppend
确定以前打开的记录集是否允许添加新记录。
BOOL CanAppend() const;
返回值
如果记录集允许添加新记录,则为非零值;否则为 0。 如果打开的记录集为只读,CanAppend
将返回 0。
CRecordset::CanBookmark
确定记录集是否允许使用书签标记记录。
BOOL CanBookmark() const;
返回值
如果记录集支持书签,则为非零值;否则为 0。
备注
此函数独立于 Open
成员函数 dwOptions
参数中的 CRecordset::useBookmarks
选项。 CanBookmark
指示给定的 ODBC 驱动程序和游标类型是否支持书签。 CRecordset::useBookmarks
指示是否提供书签,前提是它们受支持。
注意
仅向前记录集不支持书签。
有关书签和记录集导航的详细信息,请参阅记录集:书签和绝对位置 (ODBC) 和记录集:滚动 (ODBC)。
CRecordset::Cancel
请求数据源从第二个线程取消正在进行的异步操作或进程。
void Cancel();
备注
MFC ODBC 类不再使用异步处理;若要执行异步操作,必须直接调用 ODBC API 函数 SQLSetConnectOption
。 有关详细信息,请参阅《ODBC SDK 程序员指南》中的“异步执行函数”。
CRecordset::CancelUpdate
在调用 Update
之前,取消任何由 Edit
或 AddNew
操作引起的挂起更新。
void CancelUpdate();
备注
注意
此成员函数不适用于使用批量行提取的记录集,因为此类记录集无法调用 Edit
、AddNew
或 Update
。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
如果启用了自动脏字段检查,则 CancelUpdate
会将成员变量还原到调用 Edit
或 AddNew
之前的值;否则,任何值更改都将保留。 默认情况下,打开记录集时会启用自动字段检查。 若要禁用它,必须在 Open 成员函数的 dwOptions
参数中指定 CRecordset::noDirtyFieldCheck
。
有关更新数据的详细信息,请参阅记录集:添加、更新和删除记录 (ODBC)。
CRecordset::CanRestart
确定记录集是否允许通过调用 Requery
成员函数来重启查询(以刷新其记录)。
BOOL CanRestart() const;
返回值
如果允许重新查询,则为非零值;否则为 0。
CRecordset::CanScroll
确定记录集是否允许滚动。
BOOL CanScroll() const;
返回值
如果记录集允许滚动,则为非零值;否则为 0。
注解
有关滚动的详细信息,请参阅记录集:滚动 (ODBC)。
CRecordset::CanTransact
确定记录集是否允许事务。
BOOL CanTransact() const;
返回值
如果记录集允许事务,则为非零值;否则为 0。
注解
有关详细信息,请参阅事务 (ODBC)。
CRecordset::CanUpdate
确定是否可以更新记录集。
BOOL CanUpdate() const;
返回值
如果记录集可以更新,则为非零值;否则为 0。
备注
如果基础数据源为只读,或者在打开记录集时在 dwOptions
参数中指定 CRecordset::readOnly
,则记录集可能为只读。
CRecordset::CheckRowsetError
调用以处理记录提取期间生成的错误。
virtual void CheckRowsetError(RETCODE nRetCode);
参数
nRetCode
ODBC API 函数返回代码。 有关详细信息,请参阅“备注”。
注解
此虚拟成员函数处理在提取记录时发生的错误,并在批量行提取期间非常有用。 可能需要考虑重写 CheckRowsetError
来实现自己的错误处理。
CheckRowsetError
在游标导航操作(例如 Open
、Requery
或任何 Move
操作)中自动调用。 它传递 ODBC API 函数 SQLExtendedFetch
的返回值。 下表将列出 nRetCode
参数可能的值。
nRetCode | 说明 |
---|---|
SQL_SUCCESS |
函数成功完成;没有其他信息可用。 |
SQL_SUCCESS_WITH_INFO |
函数成功完成,可能出现非严重错误。 可以通过调用 SQLError 获取其他信息。 |
SQL_NO_DATA_FOUND |
已提取结果集中的所有行。 |
SQL_ERROR |
函数失败。 可以通过调用 SQLError 获取其他信息。 |
SQL_INVALID_HANDLE |
由于环境句柄、连接句柄或语句句柄无效,函数失败。 这表示编程错误。 SQLError 中无其他可用信息。 |
SQL_STILL_EXECUTING |
异步启动的函数仍在执行。 默认情况下,MFC 永远不会将此值传递给 CheckRowsetError ;MFC 将继续调用 SQLExtendedFetch ,直到它不再返回 SQL_STILL_EXECUTING 。 |
有关 SQLError
的详细信息,请参阅 Windows SDK。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::Close
关闭记录集。
virtual void Close();
备注
解除分配框架为记录集分配的 ODBC HSTMT
和所有内存。 通常调用 Close
后,如果 C++ 记录集对象已分配 new
,则删除该对象。
可以在调用 Close
后再次调用 Open
。 这样,便可以重复使用记录集对象。 替代方法是调用 Requery
。
示例
// Construct a snapshot object
CCustomer rsCustSet(NULL);
if (!rsCustSet.Open())
return;
// Use the snapshot ...
// Close the snapshot
rsCustSet.Close();
// Destructor is called when the function exits
CRecordset::CRecordset
构造 CRecordset
对象。
CRecordset(CDatabase* pDatabase = NULL);
参数
pDatabase
包含指向 CDatabase
对象或 NULL
值的指针。 如果不是 NULL
,并且没有调用 CDatabase
对象的 Open
成员函数来将其连接到数据源,则记录集将尝试在自己的 Open
调用期间打开它。 如果传递 NULL
,将使用通过 ClassWizard 派生记录集类时指定的数据源信息来构造和连接 CDatabase
对象。
注解
可以直接使用 CRecordset
,也可以从 CRecordset
中派生特定于应用程序的类。 可以使用 ClassWizard 派生记录集类。
注意
派生类必须提供自己的构造函数。 在派生类的构造函数中,调用构造函数 CRecordset::CRecordset
,并向其传递相应的参数。
将 NULL
传递给记录集构造函数,以便自动构造并连接 CDatabase
对象。 这是一个有用的速记,不需要在构造记录集之前构造和连接 CDatabase
对象。
示例
有关详细信息,请参阅记录集:声明表类 (ODBC)。
CRecordset::Delete
删除当前记录。
virtual void Delete();
备注
成功删除后,记录集的字段数据成员将设置为 Null 值,并且必须显式调用其中一个 Move
函数才能移出已删除的记录。 一旦移出删除的记录,就无法返回该记录。 如果数据源支持事务,则可以调用 Delete
作为事务的一部分。 有关详细信息,请参阅事务 (ODBC)。
注意
如果已实现批量行提取,则无法调用 Delete
。 这将导致断言失败。 虽然类 CRecordset
不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos
编写自己的函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
注意
记录集必须可更新,并且调用 Delete
时记录集必须有有效的当前记录;否则将发生错误。 例如,如果删除了记录,但在再次调用 Delete
之前不会滚动到新记录,则 Delete
会引发 CDBException。
与 AddNew
和 Edit
不同,调用 Delete
后不会跟着调用 Update
。 如果 Delete
调用失败,则字段数据成员保持不变。
示例
此示例演示在函数帧上创建的记录集。 该示例假定存在 m_dbCust
、类型为 CDatabase
的成员变量已连接到数据源。
// Create a derived CRecordset object
CCustomer rsCustSet(&m_dbCust);
rsCustSet.Open();
if (rsCustSet.IsEOF() || !rsCustSet.CanUpdate() ||
!rsCustSet.CanTransact())
{
return;
}
m_dbCust.BeginTrans();
// Perhaps scroll to a new record...
// Delete the current record
rsCustSet.Delete();
// Finished commands for this transaction
if (IDYES == AfxMessageBox(_T("Commit transaction?"), MB_YESNO))
m_dbCust.CommitTrans();
else // User changed mind
m_dbCust.Rollback();
CRecordset::DoBulkFieldExchange
调用以将批量数据行从数据源交换到记录集。 实现批量记录字段交换(批量 RFX)。
virtual void DoBulkFieldExchange(CFieldExchange* pFX);
参数
pFX
一个指向 CFieldExchange
对象的指针。 框架已设置此对象,以指定字段交换操作的上下文。
备注
实现批量行提取后,框架将调用此成员函数,以自动将数据从数据源传输到记录集对象。 DoBulkFieldExchange
还将参数数据成员(如果有)绑定到用于记录集选择的 SQL 语句字符串中的参数占位符。
如果未实现批量行提取,框架将调用 DoFieldExchange
。 若要实现批量行提取,必须在 Open
成员函数中指定 dwOptions 参数的 CRecordset::useMultiRowFetch
选项。
注意
只有当使用派生自 CRecordset
的类时,DoBulkFieldExchange
才可用。 如果已直接从 CRecordset
创建记录集对象,则必须调用 GetFieldValue
成员函数来检索数据。
批量记录字段交换(批量 RFX)类似于记录字段交换 (RFX)。 数据会自动从数据源传输到记录集对象。 但是,无法调用 AddNew
、Edit
、Delete
或 Update
将更改传输回数据源。 类 CRecordset
当前不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos
编写自己的函数。
ClassWizard 不支持批量记录字段交换;因此,你必须通过编写对批量 RFX 函数的调用来手动重写 DoBulkFieldExchange
。 有关这些函数的详细信息,请参阅记录字段交换函数。
有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。 相关信息请参阅记录字段交换 (RFX)。
CRecordset::DoFieldExchange
调用以在记录集的字段数据成员与数据源上的相应记录之间(双向)交换数据。 实现记录字段交换 (RFX)。
virtual void DoFieldExchange(CFieldExchange* pFX);
参数
pFX
一个指向 CFieldExchange
对象的指针。 框架已设置此对象,以指定字段交换操作的上下文。
注解
如果未实现批量行提取,框架将调用此成员函数,以在记录集对象的字段数据成员与数据源上当前记录的相应列之间自动交换数据。 DoFieldExchange
还将参数数据成员(如果有)绑定到用于记录集选择的 SQL 语句字符串中的参数占位符。
如果实现了批量行提取,框架将调用 DoBulkFieldExchange
。 若要实现批量行提取,必须在 Open
成员函数中指定 dwOptions
参数的 CRecordset::useMultiRowFetch
选项。
注意
只有当使用派生自 CRecordset
的类时,DoFieldExchange
才可用。 如果已直接从 CRecordset
创建记录集对象,则必须调用 GetFieldValue 成员函数来检索数据。
字段数据的交换(称为记录字段交换 (RFX))双向工作:从记录集对象的字段数据成员到数据源上的记录字段,以及从数据源上的记录到记录集对象。
要为派生的记录集类实现 DoFieldExchange
,通常必须采取的唯一操作是使用 ClassWizard 创建类,并指定字段数据成员的名称和数据类型。 还可以将代码添加到 ClassWizard 写入的内容,以指定参数数据成员或处理动态绑定的任何列。 有关详细信息,请参阅记录集:动态绑定数据列 (ODBC)。
使用 ClassWizard 声明派生的记录集类时,向导会为你写入 DoFieldExchange
的重写,类似于以下示例:
void CCustomer::DoFieldExchange(CFieldExchange* pFX)
{
pFX->SetFieldType(CFieldExchange::outputColumn);
// Macros such as RFX_Text() and RFX_Int() are dependent on the
// type of the member variable, not the type of the field in the database.
// ODBC will try to automatically convert the column value to the requested type
RFX_Long(pFX, _T("[CustomerID]"), m_CustomerID);
RFX_Text(pFX, _T("[ContactFirstName]"), m_ContactFirstName);
RFX_Text(pFX, _T("[PostalCode]"), m_PostalCode);
RFX_Text(pFX, _T("[L_Name]"), m_L_Name);
RFX_Long(pFX, _T("[BillingID]"), m_BillingID);
pFX->SetFieldType(CFieldExchange::inputParam);
RFX_Text(pFX, _T("Param"), m_strParam);
}
有关 RFX 函数的详细信息,请参阅记录字段交换函数。
有关 DoFieldExchange
的进一步示例和详细信息,请参阅记录字段交换:RFX 的工作原理。 有关 RFX 的常规信息,请参阅记录字段交换。
CRecordset::Edit
允许对当前记录进行更改。
virtual void Edit();
备注
调用 Edit
后,可以通过直接重置字段数据成员的值来更改它们。 调用 Update
成员函数来保存对数据源的更改时,操作就完成了。
注意
如果已实现批量行提取,则无法调用 Edit
。 这将导致断言失败。 虽然类 CRecordset
不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos
编写自己的函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
Edit
保存记录集的数据成员的值。 如果调用 Edit
、进行更改,然后再次调用 Edit
,记录的值将还原到第一次调用 Edit
之前的值。
在某些情况下,你可能希望通过使其为 Null(不包含数据)来更新列。 为此,请使用 TRUE 参数调用 SetFieldNull
以标记字段 Null;这也会导致更新列。 如果希望将字段写入数据源,即使其值尚未更改,请使用 TRUE 参数调用 SetFieldDirty
。 即使字段的值为 Null,也可以这样做。
如果数据源支持事务,则可以调用 Edit
作为事务的一部分。 在调用 Edit
之前和记录集打开后调用 CDatabase::BeginTrans
。 此外,调用 CDatabase::CommitTrans
不是调用 Update
以完成 Edit
操作的替代方法。 有关事务的详细信息,请参阅 CDatabase
类。
根据当前锁定模式,更新的记录可能会被 Edit
锁定,直到调用 Update
或滚动到另一条记录,或者可能只在调用 Edit
期间锁定。 可以使用 SetLockingMode
来更改锁定模式。
如果在调用 Update
之前滚动到新记录,将还原当前记录的上一个值。 如果对无法更新的记录集调用 Edit
,或者当前没有记录,则会引发 CDBException
。
有关详细信息,请参阅事务 (ODBC) 和记录集:锁定记录 (ODBC)。
示例
// To edit a record, first set up the edit buffer
rsCustSet.Edit();
// Then edit field data members for the record
rsCustSet.m_BillingID = 2795;
rsCustSet.m_ContactFirstName = _T("Jones Mfg");
// Finally, complete the operation
if (!rsCustSet.Update())
{
// Handle the failure to update
AfxMessageBox(_T("Couldn't update record!"));
}
CRecordset::FlushResultSet
如果有多个结果集,则检索预定义查询(存储过程)的下一个结果集。
BOOL FlushResultSet();
返回值
如果要检索更多结果集,则为非零值;否则为 0。
注解
只有在当前结果集中完成使用游标时,才应调用 FlushResultSet
。 通过调用 FlushResultSet
检索下一个结果集时,游标在该结果集上无效;应在调用 FlushResultSet
后调用 MoveNext
成员函数。
如果预定义查询使用输出参数或输入/输出参数,则必须调用 FlushResultSet
,直到它返回 FALSE
(值 0),才能获取这些参数值。
FlushResultSet
调用 ODBC API 函数 SQLMoreResults
。 如果 SQLMoreResults
返回 SQL_ERROR
或 SQL_INVALID_HANDLE
,则 FlushResultSet
会引发异常。 有关 SQLMoreResults
的详细信息,请参阅 Windows SDK。
如果要调用 FlushResultSet
,存储过程需要有绑定字段。
示例
以下代码假定 COutParamRecordset
是一个 CRecordset
派生对象,它基于一个带有输入参数和输出参数的预定义查询,并且具有多个结果集。 请注意 DoFieldExchange
重写的结构。
// DoFieldExchange override
//
// Only necessary to handle parameter bindings.
// Don't use CRecordset-derived class with bound
// fields unless all result sets have same schema
// OR there is conditional binding code.
void CCourses::DoFieldExchange(CFieldExchange* pFX)
{
pFX->SetFieldType(CFieldExchange::outputParam);
RFX_Long(pFX, _T("Param1"), m_nCountParam);
// The "Param1" name here is a dummy name
// that is never used
pFX->SetFieldType(CFieldExchange::inputParam);
RFX_Text(pFX, _T("Param2"), m_strNameParam);
// The "Param2" name here is a dummy name
// that is never used
}
// Assume db is an already open CDatabase object
CCourses rs(&m_dbCust);
rs.m_strNameParam = _T("History");
// Get the first result set
// NOTE: SQL Server requires forwardOnly cursor
// type for multiple rowset returning stored
// procedures
rs.Open(CRecordset::forwardOnly,
_T("{? = CALL GetCourses( ? )}"),
CRecordset::readOnly);
// Loop through all the data in the first result set
while (!rs.IsEOF())
{
CString strFieldValue;
for (short nIndex = 0; nIndex < rs.GetODBCFieldCount(); nIndex++)
{
rs.GetFieldValue(nIndex, strFieldValue);
// TO DO: Use field value string.
}
rs.MoveNext();
}
// Retrieve other result sets...
while (rs.FlushResultSet())
{
// must call MoveNext because cursor is invalid
rs.MoveNext();
while (!rs.IsEOF())
{
CString strFieldValue;
for (short nIndex = 0; nIndex < rs.GetODBCFieldCount(); nIndex++)
{
rs.GetFieldValue(nIndex, strFieldValue);
// TO DO: Use field value string.
}
rs.MoveNext();
}
}
// All result sets have been flushed. Cannot
// use the cursor, but the output parameter,
// m_nCountParam, has now been written.
// Note that m_nCountParam is not valid until
// CRecordset::FlushResultSet has returned FALSE,
// indicating no more result sets will be returned.
// TO DO: Use m_nCountParam
// Cleanup
rs.Close();
CRecordset::GetBookmark
获取当前记录的书签值。
void GetBookmark(CDBVariant& varBookmark);
参数
varBookmark
对表示当前记录上的书签的 CDBVariant
对象的引用。
注解
若要确定记录集是否支持书签,请调用 CanBookmark
。 若要使书签可用(如果受支持),必须在 Open
成员函数的 dwOptions
参数中设置 CRecordset::useBookmarks
选项。
注意
如果书签不受支持或不可用,则调用 GetBookmark
将导致引发异常。 仅向前记录集不支持书签。
GetBookmark
将当前记录的书签值分配给 CDBVariant
对象。 若要在移动到其他记录后随时返回到该记录,请使用相应的 SetBookmark
对象调用 CDBVariant
。
注意
某些记录集操作后,书签可能不再有效。 例如,如果调用 GetBookmark
后调用 Requery
,则可能无法返回到具有 SetBookmark
的记录。 调用 CDatabase::GetBookmarkPersistence
,以检查是否可以安全调用 SetBookmark
。
有关书签和记录集导航的详细信息,请参阅记录集:书签和绝对位置 (ODBC) 和记录集:滚动 (ODBC)。
CRecordset::GetDefaultConnect
调用以获取默认的连接字符串。
virtual CString GetDefaultConnect();
返回值
一个包含连接字符串的 CString
。
注解
框架调用此成员函数,以获取记录集所基于的数据源的默认连接字符串。 ClassWizard
通过标识你在 ClassWizard
中用于获取关于表和列的信息的相同数据源来实现此函数。 开发应用程序时,你可能会发现依赖此默认连接会很方便。 但默认连接可能不适合应用程序的用户。 如果是这种情况,则应重新实现此函数,放弃 ClassWizard
版本。 有关连接字符串的详细信息,请参阅数据源 (ODBC)。
CRecordset::GetDefaultSQL
调用以获取要执行的默认 SQL 字符串。
virtual CString GetDefaultSQL();
返回值
包含默认 SQL 语句的 CString
。
注解
框架调用此成员函数,以获取记录集所基于的默认 SQL 语句。 这可能是表名或 SQL SELECT
语句。
可以通过使用 ClassWizard
声明记录集类来间接定义默认 SQL 语句,而 ClassWizard
将为你执行此任务。
如果需要 SQL 语句字符串供自己使用,请调用 GetSQL
,该字符串返回用于在打开记录集时选择记录集记录的 SQL 语句。 可以在类的 GetDefaultSQL
重写中编辑默认 SQL 字符串。 例如,可以使用 CALL
语句指定对预定义查询的调用。 (但是,请注意,如果编辑 GetDefaultSQL
,则还需要修改 m_nFields
以匹配数据源中的列数。)
有关详细信息,请参阅记录集:声明表类 (ODBC)。
注意
如果框架无法标识表名、提供多个表名或无法解释 CALL
语句,则表名为空。 使用 CALL
语句时,不要在大括号和 CALL
关键字之间插入空格,也不要在 SELECT
语句中的大括号或 SELECT
关键字之前插入空格。
CRecordset::GetFieldValue
检索当前记录中的字段数据。
void GetFieldValue(
LPCTSTR lpszName,
CDBVariant& varValue,
short nFieldType = DEFAULT_FIELD_TYPE);
void GetFieldValue(
LPCTSTR lpszName,
CStringA& strValue
);
void GetFieldValue(
LPCTSTR lpszName,
CStringW& strValue
);
void GetFieldValue(
short nIndex,
CDBVariant& varValue,
short nFieldType = DEFAULT_FIELD_TYPE);
void GetFieldValue(
short nIndex,
CStringA& strValue);
void GetFieldValue(
short nIndex,
CStringW& strValue);
参数
lpszName
字段名称。
varValue
对将存储字段值的 CDBVariant
对象的引用。
nFieldType
字段的 ODBC C 数据类型。 使用默认值 DEFAULT_FIELD_TYPE
强制 GetFieldValue
根据下表从 SQL 数据类型确定 C 数据类型。 否则,可以直接指定数据类型或选择兼容的数据类型;例如,可以将任何数据类型存储在 SQL_C_CHAR
中。
C 数据类型 | SQL 数据类型 |
---|---|
SQL_C_BIT |
SQL_BIT |
SQL_C_UTINYINT |
SQL_TINYINT |
SQL_C_SSHORT |
SQL_SMALLINT |
SQL_C_SLONG |
SQL_INTEGER |
SQL_C_FLOAT |
SQL_REAL |
SQL_C_DOUBLE |
SQL_FLOATSQL_DOUBLE |
SQL_C_TIMESTAMP |
SQL_DATESQL_TIMESQL_TIMESTAMP |
SQL_C_CHAR |
SQL_NUMERICSQL_DECIMALSQL_BIGINTSQL_CHARSQL_VARCHARSQL_LONGVARCHAR |
SQL_C_BINARY |
SQL_BINARYSQL_VARBINARYSQL_LONGVARBINARY |
有关 ODBC 数据类型的详细信息,请参阅 Windows SDK 附录 D 中的主题“SQL 数据类型”和“C 数据类型”。
nIndex
该字段的从零开始的索引。
strValue
对 CString
对象的引用,该对象将存储转换为文本的字段值,而不考虑字段的数据类型。
备注
可以按名称或索引查找字段。 可以将字段值存储在 CDBVariant
或 CString
对象中。
如果已实现批量行提取,则当前记录始终位于行集中的第一条记录上。 若要在给定行集的记录上使用 GetFieldValue
,必须先调用 SetRowsetCursorPosition
成员函数,将游标移动到该行集中的所需行。 然后对该行调用 GetFieldValue
。 若要实现批量行提取,必须在 Open
成员函数中指定 dwOptions
参数的 CRecordset::useMultiRowFetch
选项。
可以使用 GetFieldValue
在运行时动态提取字段,而不是在设计时静态绑定它们。 例如,如果直接从 CRecordset
中声明记录集对象,则必须使用 GetFieldValue
来检索字段数据;记录字段交换 (RFX),或批量记录字段交换(批量 RFX)未实现。
注意
如果在不派生 CRecordset
的情况下声明记录集对象,则不会加载 ODBC 游标库。 游标库要求记录集至少有一个绑定列;但是,直接使用 CRecordset
时,不会绑定任何列。 成员函数 CDatabase::OpenEx
和 CDatabase::Open
控制是否加载游标库。
GetFieldValue
调用 ODBC API 函数 SQLGetData
。 如果驱动程序输出值 SQL_NO_TOTAL 作为字段值的实际长度,GetFieldValue
将引发异常。 有关 SQLGetData
的详细信息,请参阅 Windows SDK。
示例
以下示例代码演示了对直接从 CRecordset
中声明的记录集对象的 GetFieldValue
调用。
// Create and open a database object;
// do not load the cursor library
CDatabase db;
db.OpenEx(NULL, CDatabase::forceOdbcDialog);
// Create and open a recordset object
// directly from CRecordset. Note that a
// table must exist in a connected database.
// Use forwardOnly type recordset for best
// performance, since only MoveNext is required
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly, _T("SELECT * FROM Customer"));
// Create a CDBVariant object to
// store field data
CDBVariant varValue;
// Loop through the recordset,
// using GetFieldValue and
// GetODBCFieldCount to retrieve
// data in all columns
short nFields = rs.GetODBCFieldCount();
while (!rs.IsEOF())
{
for (short index = 0; index < nFields; index++)
{
rs.GetFieldValue(index, varValue);
// do something with varValue
}
rs.MoveNext();
}
rs.Close();
db.Close();
注意
与 DAO 类 CDaoRecordset
不同,CRecordset
没有 SetFieldValue
成员函数。 如果直接从 CRecordset
中创建对象,则它实际上为只读。
有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::GetODBCFieldCount
检索记录集对象中的字段总数。
short GetODBCFieldCount() const;
返回值
记录集中的字段数。
备注
有关创建记录集的详细信息,请参阅记录集:创建和关闭记录集 (ODBC)。
CRecordset::GetODBCFieldInfo
获取记录集中字段的相关信息。
void GetODBCFieldInfo(
LPCTSTR lpszName,
CODBCFieldInfo& fieldinfo);
void GetODBCFieldInfo(
short nIndex,
CODBCFieldInfo& fieldinfo);
参数
lpszName
字段名称。
fieldinfo
对 CODBCFieldInfo
结构的引用。
nIndex
该字段的从零开始的索引。
注解
该函数的一个版本允许按名称查找字段。 使用其他版本,可以按索引查找字段。
有关返回的信息的说明,请参阅 CODBCFieldInfo
结构。
有关创建记录集的详细信息,请参阅记录集:创建和关闭记录集 (ODBC)。
CRecordset::GetRecordCount
确定记录集的大小。
long GetRecordCount() const;
返回值
记录集中的记录数;如果记录集不包含任何记录,则为 0;如果无法确定记录计数,则为 -1。
备注
注意
记录计数保持为“高水印”,这是用户浏览记录时看到的最高编号记录。 只有在用户超出最后一条记录后,才会知道记录总数。 出于性能原因,调用 MoveLast
时不会更新计数。 若要自行对记录进行计数,请重复调用 MoveNext
,直到 IsEOF
返回非零值。 通过 CRecordset:AddNew
和 Update
添加一条记录会增加计数;通过 CRecordset::Delete
删除记录会减少计数。
CRecordset::GetRowsetSize
获取在给定提取期间要检索的行数的当前设置。
DWORD GetRowsetSize() const;
返回值
在给定提取期间要检索的行数。
注解
如果使用批量行提取,则打开记录集时的默认行集大小为 25;否则为 1。
要实现批量行提取,必须在 Open
成员函数的 dwOptions
参数中指定 CRecordset::useMultiRowFetch
选项。 若要更改行集大小的设置,请调用 SetRowsetSize
。
有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::GetRowsFetched
确定提取后检索的记录数。
DWORD GetRowsFetched() const;
返回值
给定提取后从数据源检索的行数。
备注
实现批量行提取时,这非常有用。 行集大小通常指示将从提取中检索的行数。 但是,记录集中的行总数也会影响行集中检索的行数。 例如,如果记录集有 10 条记录,其行集大小设置为 4 条,则通过调用 MoveNext
循环访问记录集将导致最后一个行集只有两条记录。
若要实现批量行提取,必须在 Open
成员函数的 dwOptions 参数中指定 CRecordset::useMultiRowFetch
选项。 若要指定行集大小,请调用 SetRowsetSize。
有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
示例
CMultiCustomer rs(&m_dbCust);
// Set the rowset size
rs.SetRowsetSize(5);
// Open the recordset
rs.Open(CRecordset::dynaset, NULL, CRecordset::useMultiRowFetch);
// loop through the recordset by rowsets
while (!rs.IsEOF())
{
for (int rowCount = 0; rowCount < (int)rs.GetRowsFetched(); rowCount++)
{
// do something
}
rs.MoveNext();
}
rs.Close();
CRecordset::GetRowStatus
获取当前行集中行的状态。
WORD GetRowStatus(WORD wRow) const;
参数
wRow
行在当前行集中基于 1 的位置。 此值的范围可以是 1 到行集的大小。
返回值
行的状态值。 有关详细信息,请参阅“备注”。
备注
GetRowStatus
返回一个值,该值指示自上次从数据源检索到该行以来的行状态的任何更改,或者没有提取与 wRow
对应的行。 下表列出可能的返回值。
状态值 | 说明 |
---|---|
SQL_ROW_SUCCESS |
该行保持不变。 |
SQL_ROW_UPDATED |
已更新该行。 |
SQL_ROW_DELETED |
已删除该行。 |
SQL_ROW_ADDED |
已添加该行。 |
SQL_ROW_ERROR |
由于错误,该行无法检索。 |
SQL_ROW_NOROW |
没有行对应于 wRow 。 |
有关详细信息,请参阅 Windows SDK 中的 ODBC API 函数 SQLExtendedFetch
。
CRecordset::GetStatus
确定记录集中当前记录的索引以及是否看到最后一条记录。
void GetStatus(CRecordsetStatus& rStatus) const;
参数
rStatus
对 CRecordsetStatus
对象的引用。 有关更多信息,请参见备注。
注解
CRecordset
尝试跟踪索引,但在某些情况下,可能无法跟踪索引。 有关说明,请参阅 GetRecordCount
。
CRecordsetStatus
结构采用以下格式:
struct CRecordsetStatus
{
long m_lCurrentRecord;
BOOL m_bRecordCountFinal;
};
这两个 CRecordsetStatus
成员具有以下含义:
m_lCurrentRecord
包含记录集中当前记录的从零开始的索引(如果已知)。 如果无法确定索引,则此成员包含AFX_CURRENT_RECORD_UNDEFINED
(-2)。 如果IsBOF
为 TRUE(空记录集或尝试在首次记录之前滚动),则m_lCurrentRecord
设置为AFX_CURRENT_RECORD_BOF
(-1)。 如果位于第一条记录上,那么设置为 0,如果在第二条记录上,则设置为 1,依此类推。m_bRecordCountFinal
如果已确定记录集中的记录总数,则为非零。 通常,必须从记录集的开头开始并调用MoveNext
,直到IsEOF
返回非零值,才能完成此操作。 如果此成员为零,则记录计数为GetRecordCount
返回的值,如果不是 -1,则只是记录的“高水印”计数。
CRecordset::GetSQL
调用此成员函数可获取用于在打开记录集时用于选择记录集记录的 SQL 语句。
const CString& GetSQL() const;
返回值
对包含 SQL 语句的 CString
的 const
引用。
备注
这通常为 SQL SELECT
语句。 GetSQL
返回的字符串为只读。
GetSQL
返回的字符串通常不同于你传递给 Open
成员函数的 lpszSQL
参数中的记录集的任何字符串。 这是因为记录集基于你传递给 Open
的内容、通过 ClassWizard
指定的内容、可能已在 m_strFilter
和 m_strSort
数据成员中指定的内容以及可能已指定的任何参数构造完整的 SQL 语句。 有关记录集如何构造此 SQL 语句的详细信息,请参阅记录集:记录集如何选择记录 (ODBC)。
注意
仅在调用 Open
后调用此成员函数。
CRecordset::GetTableName
获取记录集查询所基于的 SQL 表名。
const CString& GetTableName() const;
返回值
如果记录集基于表,则是对包含表名的 CString
的 const
引用;否则为空字符串。
备注
仅当记录集基于表而不是多个表的联接或预定义查询(存储过程)时,GetTableName
才有效。 名称为只读。
注意
仅在调用 Open
后调用此成员函数。
CRecordset::IsBOF
如果在第一条记录之前定位了记录集,则返回非零值。 没有最新记录。
BOOL IsBOF() const;
返回值
如果记录集不包含任何记录,或者在第一条记录之前向后滚动,则为非零值;否则为 0。
备注
在从一条记录滚动到另一条记录之前调用此成员函数,了解是否已在记录集的第一条记录之前滚动。 还可以将 IsBOF
与 IsEOF
一起使用来确定记录集是否包含任何记录或为空。 调用 Open
后,如果记录集不包含任何记录,IsBOF
将立即返回非零值。 打开至少有一条记录的记录集时,第一条记录为当前记录且 IsBOF
返回 0。
如果第一条记录是当前记录并且你调用 MovePrev
,则 IsBOF
将返回非零值。 如果 IsBOF
返回非零值且你调用 MovePrev
,则会发生错误。 如果 IsBOF
返回非零值,则当前记录未定义,且任何需要当前记录的操作都将导致错误。
示例
此示例使用 IsBOF
和 IsEOF
来检测在代码向两个方向滚动记录集时记录集的限制。
// Open a recordset; first record is current
// Open a recordset; first record is current
CCustomer rsCustSet(&m_dbCust);
rsCustSet.Open();
if(rsCustSet.IsBOF())
return;
// The recordset is empty
// Scroll to the end of the recordset, past
// the last record, so no record is current
while (!rsCustSet.IsEOF())
rsCustSet.MoveNext();
// Move to the last record
rsCustSet.MoveLast();
// Scroll to beginning of the recordset, before
// the first record, so no record is current
while(!rsCustSet.IsBOF())
rsCustSet.MovePrev();
// First record is current again
rsCustSet.MoveFirst();
CRecordset::IsDeleted
确定是否已删除当前记录。
BOOL IsDeleted() const;
返回值
如果记录集定位在已删除的记录上,则返回非零值;否则返回 0。
注解
如果滚动到记录且 IsDeleted
返回 TRUE
(非零值),则必须滚动到另一条记录,然后才能执行任何其他记录集操作。
IsDeleted
的结果取决于许多因素,例如记录集类型、记录集是否可更新、打开记录集时是否指定 CRecordset::skipDeletedRecords
了选项、驱动程序是否打包已删除的记录,以及是否存在多个用户。
有关 CRecordset::skipDeletedRecords
和驱动程序打包的详细信息,请参阅 Open 成员函数。
注意
如果已实现批量行提取,则不应调用 IsDeleted
。 请改为调用 GetRowStatus 成员函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::IsEOF
如果记录集位于最后一条记录之后,则返回非零值。 没有最新记录。
BOOL IsEOF() const;
返回值
如果记录集不包含任何记录,或者滚动到最后一条记录之外,则为非零值;否则为 0。
备注
在从一条记录滚动到另一条记录时调用此成员函数,了解是否已滚动到记录集的最后一条记录之外。 还可以使用 IsEOF
来确定记录集是否包含任何记录或为空。 调用 Open
后,如果记录集不包含任何记录,IsEOF
将立即返回非零值。 打开至少有一条记录的记录集时,第一条记录为当前记录且 IsEOF
返回 0。
如果最后一条记录是当前记录并且你调用 MoveNext
,则 IsEOF
将返回非零值。 如果 IsEOF
返回非零值且你调用 MoveNext
,则会发生错误。 如果 IsEOF
返回非零值,则当前记录未定义,且任何需要当前记录的操作都将导致错误。
示例
请参阅 IsBOF
的示例。
CRecordset::IsFieldDirty
确定指定字段数据成员自调用 Edit
或 AddNew
以来是否已更改。
BOOL IsFieldDirty(void* pv);
参数
pv
指向要检查其状态的字段数据成员的指针,或用于确定是否有脏字段的 NULL
。
返回值
如果指定的字段数据成员自调用 AddNew
或 Edit
后已更改,则为非零值;否则为 0。
注解
当通过调用 CRecordset
的 Update
成员函数(在调用 Edit
或 AddNew
之后)更新当前记录时,所有脏字段数据成员中的数据都将被转移到数据源上的记录。
注意
此成员函数不适用于使用批量行提取的记录集。 如果已实现批量行提取,则 IsFieldDirty
始终返回 FALSE,并会导致断言失败。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
调用 IsFieldDirty
会将前面调用的效果重置为 SetFieldDirty,因为字段的脏状态会被重新计算。 在 AddNew
案例中,如果当前字段值不同于伪 null 值,则字段状态设置为脏。 在 Edit
案例中,如果字段值不同于伪缓存值,则字段状态设置为脏。
IsFieldDirty
通过 DoFieldExchange
实现。
有关脏标志的详细信息,请参阅记录集:记录集如何选择记录 (ODBC)。
CRecordset::IsFieldNull
如果当前记录中的指定字段为 Null(没有值),则返回非零值。
BOOL IsFieldNull(void* pv);
参数
pv
指向要检查其状态的字段数据成员的指针,或用于确定是否有字段为 Null 的 NULL
。
返回值
如果指定的字段数据成员标记为 Null,则返回非零值;否则返回 0。
备注
调用此成员函数可确定记录集的指定字段数据成员是否已标记为 Null。 (在数据库术语中,Null 表示“没有值”,并且与 C++ 中的 NULL
不同。)如果字段数据成员标记为 Null,则会将其解释为当前记录中没有值的列。
注意
此成员函数不适用于使用批量行提取的记录集。 如果已实现批量行提取,则 IsFieldNull
始终返回 FALSE
,并将导致断言失败。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
IsFieldNull
通过 DoFieldExchange
实现。
CRecordset::IsFieldNullable
如果当前记录中的指定字段可以设置为 Null(没有值),则返回非零值。
BOOL IsFieldNullable(void* pv);
参数
pv
指向要检查其状态的字段数据成员的指针,或用于确定是否有任何字段可以设置为 Null 值的 NULL
。
备注
调用此成员函数,以确定指定的字段数据成员是否“可为空”(可设置为 Null 值;C++ NULL
与 Null 不同,后者在数据库术语中表示“没有值”)。
注意
如果已实现批量行提取,则无法调用 IsFieldNullable
。 请调用 GetODBCFieldInfo
成员函数来确定字段是否可以设置为 Null 值。 无论是否已实现批量行提取,都可以始终调用 GetODBCFieldInfo
。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
不能为 Null 的字段必须有值。 如果在添加或更新记录时尝试将此类字段设置为 Null,数据源将拒绝添加或更新,且 Update
会引发异常。 调用 Update
时发生异常,而不是在调用 SetFieldNull
时发生。
对函数的第一个参数使用 NULL
会将函数仅应用于 outputColumn
字段,而不是 param
字段。 例如,调用
SetFieldNull(NULL);
仅将 outputColumn
字段设置为 NULL
;param
字段不受影响。
若要处理 param
字段,必须提供要处理的单个 param
的实际地址,例如:
SetFieldNull(&m_strParam);
这意味着你不能像设置 outputColumn
字段那样将所有 param
字段设置为 NULL
。
IsFieldNullable
通过 DoFieldExchange 实现。
CRecordset::IsOpen
确定记录集是否已打开。
BOOL IsOpen() const;
返回值
如果记录集对象的 Open
或 Requery
成员函数以前已调用且记录集尚未关闭,则为非零值;否则为 0。
CRecordset::m_hstmt
包含与记录集关联的类型为 HSTMT
的 ODBC 语句数据结构的句柄。
备注
对 ODBC 数据源的每个查询都与 HSTMT
关联。
注意
在调用 Open
之前不要使用 m_hstmt
。
通常不需要直接访问 HSTMT
,但可能需要它来直接执行 SQL 语句。 CDatabase
类的 ExecuteSQL
成员函数提供了 m_hstmt
使用示例。
CRecordset::m_nFields
包含记录集类中的字段数据成员数;也就是说,记录集从数据源中选择的列数。
备注
记录集类的构造函数必须用正确的数字初始化 m_nFields
。 如果尚未实现批量行提取,ClassWizard
将在你使用它来声明记录集类时为你编写此初始化。 你也可以手动编写此初始化。
框架使用此数字来管理字段数据成员与数据源上当前记录的相应列之间的交互。
注意
该数字必须与使用 CFieldExchange::outputColumn
参数调用 SetFieldType
后在 DoFieldExchange
或 DoBulkFieldExchange
中注册的“输出列”数相对应。
可以动态绑定列,如“记录集:动态绑定数据列”一文中所述。如果这样做,则必须增加 m_nFields
计数,以反映动态绑定列的 DoFieldExchange
或 DoBulkFieldExchange
成员函数中 RFX 或批量 RFX 函数调用数。
有关详细信息,请参阅文章记录集:动态绑定数据列 (ODBC) 和记录集:批量提取记录 (ODBC)。
示例
请参阅记录字段交换:使用 RFX。
CRecordset::m_nParams
包含记录集类中参数数据成员的数量;也就是说,与记录集查询一起传递的参数数量。
注解
如果记录集类具有任何参数数据成员,则类的构造函数必须用正确数字初始化 m_nParams
。 m_nParams
默认值为 0。 如果添加参数数据成员(必须手动),还必须在类构造函数中手动添加初始化,以反映参数数量(必须至少与 m_strFilter
或 m_strSort
字符串中的 '' 占位符的数量相同。)
框架在参数化记录集的查询时使用此数字。
注意
该数字必须与使用 CFieldExchange::inputParam
、CFieldExchange::param
、CFieldExchange::outputParam
或 CFieldExchange::inoutParam
参数调用 SetFieldType
后在 DoFieldExchange
或 DoBulkFieldExchange
中注册的“参数”数量相对应。
示例
请参阅文章记录集:参数化记录集 (ODBC) 和记录字段交换:使用 RFX。
CRecordset::m_pDatabase
包含指向 CDatabase
对象的指针,记录集通过该对象连接到数据源。
备注
此变量有两种设置方式。 通常,构造记录集对象时,会将指针传递给已连接的 CDatabase
对象。 如果改为传递 NULL
,CRecordset
将为你创建 CDatabase
对象并连接它。 在这两种情况下,CRecordset
将指针存储在此变量中。
通常,你不需要直接使用存储在 m_pDatabase
中的指针。 但是,如果编写自己的 CRecordset
扩展,则可能需要使用指针。 例如,如果引出自己的 CDBException
,则可能需要指针。 或者,如果需要使用同一 CDatabase
对象执行某些操作,例如运行事务、设置超时或调用 CDatabase
类 ExecuteSQL
成员函数来直接执行 SQL 语句,则可能需要它。
CRecordset::m_strFilter
构造记录集对象之后,但在调用其 Open
成员函数之前,使用此数据成员来存储包含 SQL WHERE
子句的 CString
。
备注
记录集使用此字符串来约束(或筛选)在调用 Open
或 Requery
期间选择的记录。 这对于选择记录的子集非常有用,例如“所有在加州的销售人员”(“state = CA”)。 WHERE
子句的 ODBC SQL 语法为
WHERE search-condition
不要在字符串中包含 WHERE
关键字。 框架会提供它。
还可以通过在筛选器字符串中放置 '' 占位符、为每个占位符在类中声明参数数据成员以及在运行时将参数传递给记录集来参数化筛选器字符串。 这样就可以在运行时构造筛选器。 有关详细信息,请参阅记录集:参数化记录集 (ODBC)。
有关 SQL WHERE
子句的详细信息,请参阅 SQL。 有关选择和筛选记录的详细信息,请参阅记录集:筛选记录 (ODBC)。
示例
CCustomer rsCustSet(&m_dbCust);
// Set the filter
rsCustSet.m_strFilter = _T("L_Name = 'Flanders'");
// Run the filtered query
rsCustSet.Open(CRecordset::snapshot, _T("Customer"));
CRecordset::m_strSort
构造记录集对象之后,但在调用其 Open
成员函数之前,使用此数据成员来存储包含 SQL ORDER BY
子句的 CString
。
备注
记录集使用此字符串对在调用 Open
或 Requery
期间选择的记录进行排序。 可以使用此功能对一个或多个列的记录集进行排序。 ORDER BY
子句的 ODBC SQL 语法为
ORDER BY sort-specification [, sort-specification]...
其中,排序规范是整数或列名。 还可以通过在排序字符串的列列表中添加“ASC”或“DESC”来指定升序或降序(默认为升序)。 所选记录首先按列出的第一列进行排序,然后按第二列排序,依此类推。 例如,可以按姓和名对“Customers”记录集进行排序。 可以列出的列数取决于数据源。 有关详细信息,请参阅 Windows SDK。
不要在字符串中包含 ORDER BY
关键字。 框架会提供它。
有关 SQL 子句的详细信息,请参阅 SQL。 有关对记录进行排序的详细信息,请参阅记录集:对记录进行排序 (ODBC)。
示例
CCustomer rsCustSet(&m_dbCust);
// Set the sort string
rsCustSet.m_strSort = _T("L_Name, ContactFirstName");
// Run the sorted query
rsCustSet.Open(CRecordset::snapshot, _T("Customer"));
CRecordset::Move
在记录集中向前或向后移动当前记录指针。
virtual void Move(
long nRows,
WORD wFetchType = SQL_FETCH_RELATIVE);
参数
nRows
向前或向后移动的行数。 正值朝记录集末尾向前移动。 负值朝开头向后移动。
wFetchType
确定 Move
将提取的行集。 有关详细信息,请参阅“备注”。
注解
如果为 nRows
传递值 0,则 Move
将刷新当前记录;Move
将结束任何当前 AddNew
或 Edit
模式,并在调用 AddNew
或 Edit
之前还原当前记录的值。
注意
在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅CRecordset::IsDeleted
。 当你打开设置了 skipDeletedRecords
选项的 CRecordset
时,如果 nRows
参数为 0,则 Move
将断言。 此行为可防止刷新使用相同数据的其他客户端应用程序删除的行。 有关 skipDeletedRecords
的描述,请参阅 Open
中的 dwOption
参数。
Move
按行集重新定位记录集。 根据 nRows
和 wFetchType
的值,Move
提取相应的行集,然后将该行集中的第一条记录制作为当前记录。 如果尚未实现批量行提取,则行集大小始终为 1。 提取行集时,Move
直接调用 CheckRowsetError
成员函数来处理提取产生的任何错误。
根据传递的值,Move
等效于其他 CRecordset
成员函数。 具体而言,wFetchType
的值可能指示一个更直观的成员函数,通常是移动当前记录的首选方法。
下表列出了 wFetchType
可能的值、Move
将基于 wFetchType
和 nRows
提取的行集,以及对应于 wFetchType
的任何等效成员函数。
wFetchType | 提取的行集 | 等效成员函数 |
---|---|---|
SQL_FETCH_RELATIVE (默认值) |
从当前行集的第一行开始 nRows 行的行集。 |
|
SQL_FETCH_NEXT |
下一个行集;nRows 将被忽略。 |
MoveNext |
SQL_FETCH_PRIOR |
上一个行集;nRows 将被忽略。 |
MovePrev |
SQL_FETCH_FIRST |
记录集中的第一个行集;nRows 将被忽略。 |
MoveFirst |
SQL_FETCH_LAST |
记录集中最后完成的行集;nRows 将被忽略。 |
MoveLast |
SQL_FETCH_ABSOLUTE |
如果 nRows > 0,则从记录集开头开始 nRows 行的行集。 如果 nRows < 0,则从记录集末尾开始 nRows 行的行集。 如果 nRows = 0,则返回文件开头 (BOF) 条件。 |
SetAbsolutePosition |
SQL_FETCH_BOOKMARK |
从书签值对应于 nRows 的行开始的行集。 |
SetBookmark |
注意
对于仅向前记录集,只有当 wFetchType
的值为 SQL_FETCH_NEXT
时 Move
才有效。
注意
如果已滚动到记录集的开头或结尾(IsBOF
或 IsEOF
返回非零值),则调 Move
用函数可能会引发 CDBException
。 例如,如果 IsEOF
返回非零值而 IsBOF
没有返回非零值,则 MoveNext
将引发异常,但 MovePrev
不会引发异常。
注意
如果在更新或添加当前记录时调用 Move
,更新将丢失,而不会发出警告。
有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。 相关信息请参阅 Windows SDK 中的 ODBC API 函数SQLExtendedFetch
。
示例
// rs is a CRecordset or a CRecordset-derived object
// Change the rowset size to 5
rs.SetRowsetSize(5);
// Open the recordset
rs.Open(CRecordset::dynaset, NULL, CRecordset::useMultiRowFetch);
// Move to the first record in the recordset
rs.MoveFirst();
// Move to the sixth record
rs.Move(5);
// Other equivalent ways to move to the sixth record:
rs.Move(6, SQL_FETCH_ABSOLUTE);
rs.SetAbsolutePosition(6);
// In this case, the sixth record is the first record in the next rowset,
// so the following are also equivalent:
rs.MoveFirst();
rs.Move(1, SQL_FETCH_NEXT);
rs.MoveFirst();
rs.MoveNext();
CRecordset::MoveFirst
使第一行集中的第一条记录成为当前记录。
void MoveFirst();
注解
无论是否实现了批量行提取,这始终是记录集中的第一条记录。
打开记录集后,无需立即调用 MoveFirst
。 此时,第一条记录(如果有)将自动成为当前记录。
注意
此成员函数对仅向前记录集无效。
注意
在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted
成员函数。
注意
如果记录集没有记录,则调用任何 Move
函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOF
和 IsEOF
。
注意
如果在更新或添加当前记录时调用任何 Move
函数,更新将丢失,而不会发出警告。
有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
示例
请参阅 IsBOF
的示例。
CRecordset::MoveLast
使最后完成的行集中的第一条记录成为当前记录。
void MoveLast();
备注
如果尚未实现批量行提取,则记录集的大小为 1,因此 MoveLast
移动到记录集中的最后一条记录。
注意
此成员函数对仅向前记录集无效。
注意
在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted
成员函数。
注意
如果记录集没有记录,则调用任何 Move
函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOF
和 IsEOF
。
注意
如果在更新或添加当前记录时调用任何 Move
函数,更新将丢失,而不会发出警告。
有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
示例
请参阅 IsBOF
的示例。
CRecordset::MoveNext
使下一行集中的第一条记录成为当前记录。
void MoveNext();
备注
如果尚未实现批量行提取,则记录集的大小为 1,因此 MoveNext
移动到下一条记录。
注意
在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted
成员函数。
注意
如果记录集没有记录,则调用任何 Move
函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOF
和 IsEOF
。
注意
此外,建议在调用 MoveNext
之前调用 IsEOF
。 例如,如果滚动到记录集末尾,IsEOF
将返回非零值;后续调用 MoveNext
将引发异常。
注意
如果在更新或添加当前记录时调用任何 Move
函数,更新将丢失,而不会发出警告。
有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
示例
请参阅 IsBOF
的示例。
CRecordset::MovePrev
使前一行集中的第一条记录成为当前记录。
void MovePrev();
注解
如果尚未实现批量行提取,则记录集的大小为 1,因此 MovePrev
移动到上一条记录。
注意
此成员函数对仅向前记录集无效。
注意
在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted
成员函数。
注意
如果记录集没有记录,则调用任何 Move
函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOF
和 IsEOF
。
注意
此外,建议在调用 MovePrev
之前调用 IsBOF
。 例如,如果滚动到记录集开头,IsBOF
将返回非零值;后续调用 MovePrev
将引发异常。
注意
如果在更新或添加当前记录时调用任何 Move
函数,更新将丢失,而不会发出警告。
有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
示例
请参阅 IsBOF
的示例。
CRecordset::OnSetOptions
调用以为指定 ODBC 语句设置选项(在选择时使用)。
virtual void OnSetOptions(HSTMT hstmt);
参数
hstmt
要设置其选项的 ODBC 语句的 HSTMT
。
备注
调用 OnSetOptions
以为指定 ODBC 语句设置选项(在选择时使用)。 框架调用此成员函数,以设置记录集的初始选项。 OnSetOptions
确定数据源对可滚动游标和游标并发的支持,并相应地设置记录集选项。 (OnSetOptions
用于选择操作,OnSetUpdateOptions
则用于更新操作。)
重写 OnSetOptions
以设置特定于驱动程序或数据源的选项。 例如,如果数据源支持打开供独占访问,则可以重写 OnSetOptions
以利用此功能。
有关游标的详细信息,请参阅 ODBC。
CRecordset::OnSetUpdateOptions
调用以为指定 ODBC 语句设置选项(在更新时使用)。
virtual void OnSetUpdateOptions(HSTMT hstmt);
参数
hstmt
要设置其选项的 ODBC 语句的 HSTMT
。
备注
调用 OnSetUpdateOptions
,为指定 ODBC 语句设置选项(在更新时使用)。 框架在创建 HSTMT
以更新记录集中的记录后调用此成员函数。 (OnSetOptions
用于选择操作,OnSetUpdateOptions
则用于更新操作。)OnSetUpdateOptions
确定数据源对可滚动游标和游标并发性的支持,并相应地设置记录集选项。
重写 OnSetUpdateOptions
以在使用该语句访问数据库之前设置 ODBC 语句选项。
有关游标的详细信息,请参阅 ODBC。
CRecordset::Open
通过检索表或执行记录集所表示的查询来打开记录集。
virtual BOOL Open(
UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
LPCTSTR lpszSQL = NULL,
DWORD dwOptions = none);
参数
nOpenType
接受默认值 AFX_DB_USE_DEFAULT_TYPE
,或使用下列 enum OpenType
中的值之一:
CRecordset::dynaset
具有双向滚动的记录集。 打开记录集可确定记录的成员身份和排序,但其他用户对数据值所做的更改在提取操作后可见。 动态集也称为键集驱动的记录集。CRecordset::snapshot
具有双向滚动的静态记录集。 打开记录集可确定记录的成员身份和排序。 提取记录将确定数据值。 在关闭记录集,然后重新打开记录集之前,其他用户所做的更改不可见。CRecordset::dynamic
具有双向滚动的记录集。 其他用户对成员身份、排序和数据值所做的更改在提取操作后可见。 许多 ODBC 驱动程序不支持这种类型的记录集。CRecordset::forwardOnly
仅向前滚动的只读记录集。CRecordset
的默认值为CRecordset::snapshot
。 使用默认值机制,Visual C++ 向导可以与具有不同默认值的 ODBCCRecordset
和 DAOCDaoRecordset
进行交互。
有关这些记录集类型的详细信息,请参阅记录集 (ODBC) 。 相关信息请参阅 Windows SDK 中的“使用块和可滚动游标”。
注意
如果请求的类型不受支持,框架将引发异常。
lpszSQL
包含下列项之一的字符串指针:
一个
NULL
指针。表的名称。
SQL
SELECT
语句(SQLWHERE
或ORDER BY
子句可选)。一个
CALL
语句,指定预定义查询的名称(存储过程)。 请注意不要在大括号和CALL
关键字之间插入空格。
有关此字符串的详细信息,请参阅注解部分下有关 ClassWizard 角色的表和讨论。
注意
结果集中列的顺序必须与 DoFieldExchange
或 DoBulkFieldExchange
函数替代中 RFX 或批量 RFX 函数调用的顺序匹配。
dwOptions
位掩码,可以指定下面列出的值的组合。 其中一些是互斥的。 默认值为 none
。
CRecordset::none
未设置任何选项。 此参数值与所有其他值互斥。 默认情况下,可以使用Edit
或Delete
更新记录集,并允许使用AddNew
来追加新记录。 可更新性取决于数据源和指定的nOpenType
选项。 批量添加的优化不可用。 不会实现批量行提取。 记录集导航期间不会跳过已删除的记录。 书签不可用。 实现自动脏字段检查。CRecordset::appendOnly
不允许记录集上有Edit
或Delete
。 仅允许AddNew
。 此选项与CRecordset::readOnly
互斥。CRecordset::readOnly
将记录集打开为只读。 此选项与CRecordset::appendOnly
互斥。CRecordset::optimizeBulkAdd
使用准备好的 SQL 语句一次优化添加多个记录。 仅当未使用 ODBC API 函数SQLSetPos
更新记录集时才适用。 第一次更新确定哪些字段标记为脏。 此选项与CRecordset::useMultiRowFetch
互斥。CRecordset::useMultiRowFetch
实现批量行提取,以允许在单个提取操作中检索多个行。 这是一项旨在提高性能的高级功能;但是,ClassWizard
不支持批量记录字段交换。 此选项与CRecordset::optimizeBulkAdd
互斥。 如果指定CRecordset::useMultiRowFetch
,则选项CRecordset::noDirtyFieldCheck
将自动打开(双缓冲将不可用);在仅向前记录集上,选项CRecordset::useExtendedFetch
将自动打开。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。CRecordset::skipDeletedRecords
浏览记录集时跳过所有已删除的记录。 这将降低某些相对提取的性能。 此选项对仅向前记录集无效。 如果在Move
nRows 参数设置为 0 时调用 ,并且设置了CRecordset::skipDeletedRecords
选项,那么Move
将断言。CRecordset::skipDeletedRecords
类似于驱动程序打包,这意味着从记录集中删除已删除的行。 但是,如果驱动程序打包记录,则只会跳过删除的那些记录;打开记录集时,不会跳过其他用户删除的记录。CRecordset::skipDeletedRecords
将跳过其他用户删除的行。CRecordset::useBookmarks
可以在记录集上使用书签(如果支持)。 书签会减缓数据检索速度,但提高了数据导航的性能。 对仅向前记录集无效。 有关详细信息,请参阅记录集:书签和绝对位置 (ODBC)。CRecordset::noDirtyFieldCheck
关闭自动脏字段检查(双缓冲)。 这将提高性能;但是,必须通过调用SetFieldDirty
和SetFieldNull
成员函数手动将字段标记为脏。CRecordset
类中的双缓冲类似于CDaoRecordset
类中的双缓冲。 但是,在CRecordset
中,不能对单个字段启用双缓存;你可以为所有字段启用它,也可以为所有字段禁用它。 如果指定选项CRecordset::useMultiRowFetch
,则CRecordset::noDirtyFieldCheck
会自动打开;但是,SetFieldDirty
和SetFieldNull
不能在实现批量行提取的记录集上使用。CRecordset::executeDirect
请勿使用准备好的 SQL 语句。 为了提高性能,如果永远不会调用Requery
成员函数,请指定此选项。CRecordset::useExtendedFetch
实现SQLExtendedFetch
而不是SQLFetch
。 这是针对仅向前记录集实现批量行提取而设计的。 如果在仅向前记录集上指定选项CRecordset::useMultiRowFetch
,则CRecordset::useExtendedFetch
会自动打开。CRecordset::userAllocMultiRowBuffers
用户将为数据分配存储缓冲区。 如果要分配自己的存储,可以对CRecordset::useMultiRowFetch
使用此选项。 否则,框架将自动分配所需的存储。 有关详细信息,请参阅记录集:批量提取记录 (ODBC)。 指定CRecordset::userAllocMultiRowBuffers
而不指定CRecordset::useMultiRowFetch
会导致断言失败。
返回值
如果 CRecordset
成功打开对象,则为非零值;如果 CDatabase::Open
(如已调用)返回 0,则为 0。
备注
必须调用此成员函数以运行记录集定义的查询。 在调用 Open
之前,必须构造记录集对象。
此记录集与数据源的连接取决于在调用 Open
之前如何构造记录集。 如果将对象 CDatabase
传递给尚未连接到数据源的记录集构造函数,则此成员函数将使用 GetDefaultConnect
尝试打开数据库对象。 如果将 NULL 传递给记录集构造函数,则构造函数会为你构造一个 CDatabase
对象,并且 Open
会尝试连接数据库对象。 有关在这些不同情况下关闭记录集和连接的详细信息,请参阅 Close
。
注意
始终共享通过 CRecordset
对象访问数据源。 与 CDaoRecordset
类不同,不能使用 CRecordset
对象打开供独占访问的数据源。
调用 Open
时,查询(通常是 SQL SELECT
语句)会根据下表所示的条件选择记录。
lpszSQL 参数的值 |
所选记录的确定方式 | 示例 |
---|---|---|
NULL |
GetDefaultSQL 返回的字符串。 |
|
SQL 表名 | DoFieldExchange 或 DoBulkFieldExchange 中表列表的所有列。 |
"Customer" |
预定义查询(存储过程)名称 | 定义查询要返回的列。 | "{call OverDueAccts}" |
SELECT column-list FROM table-list |
指定表中的指定列。 | "SELECT CustId, CustName FROM Customer" |
注意
不要在 SQL 字符串中插入额外的空格。 例如,如果在大括号和 CALL
关键字之间插入空格,MFC 会将 SQL 字符串错误解释为表名并将其合并到 SELECT
语句,这将导致引发异常。 同样,如果预定义查询使用输出参数,请不要在大括号和 '' 符号之间插入空格。 最后,不得在 CALL
语句的大括号或 SELECT
语句的 SELECT
关键字前插入空格。
通常的过程是将 NULL
传递给 Open
;在这种情况下,Open
调用 GetDefaultSQL。 如果使用的是派生 CRecordset
类,GetDefaultSQL
将给出在 ClassWizard
中指定的表名。 可以改为在 lpszSQL
参数中指定其他信息。
无论传递什么,Open
都会为查询构造最终的 SQL 字符串(该字符串可能将 SQL WHERE
和 ORDER BY
子句追加到传递的 lpszSQL
的字符串),然后执行查询。 可以通过调用 Open
后调用 GetSQL
来检查构造的字符串。 有关记录集如何构造 SQL 语句和选择记录的更多详细信息,请参阅记录集:记录集如何选择记录 (ODBC)。
记录集类的字段数据成员绑定到所选数据列。 如果返回任何记录,则第一条记录将成为当前记录。
如果要为记录集(如筛选器或排序)设置选项,请在构造记录集对象之后但在调用 Open
之前指定这些选项。 如果要在记录集打开后刷新记录集中的记录,请调用 Requery
。
有关详细信息(包括更多示例),请参阅记录集 (ODBC)、记录集:记录集如何选择记录集 (ODBC),以及记录集:创建和关闭记录集 (ODBC)。
示例
下面的代码示例显示了不同形式的 Open
调用。
// rsSnap, rsLName, and rsDefault are CRecordset or CRecordset-derived
// objects
// Open rs using the default SQL statement, implement bookmarks, and turn
// off automatic dirty field checking
rsSnap.Open(CRecordset::snapshot, NULL, CRecordset::useBookmarks |
CRecordset::noDirtyFieldCheck);
// Pass a complete SELECT statement and open as a dynaset
rsLName.Open(CRecordset::dynaset, _T("Select L_Name from Customer"));
// Accept all defaults
rsDefault.Open();
CRecordset::RefreshRowset
更新当前行集中行的数据和状态。
void RefreshRowset(
WORD wRow,
WORD wLockType = SQL_LOCK_NO_CHANGE);
参数
wRow
行在当前行集中基于 1 的位置。 此值的范围可以是 0 到行集的大小。
wLockType
该值指示如何在刷新行后锁定该行。 有关详细信息,请参阅“备注”。
备注
如果为 wRow
传递的值为零,则将刷新行集中的每一行。
若要使用 RefreshRowset
,必须通过在 Open
成员函数中指定 CRecordset::useMulitRowFetch
选项来实现批量行提取。
RefreshRowset
调用 ODBC API 函数 SQLSetPos
。 wLockType
参数指定执行 SQLSetPos
后行的锁定状态。 下表描述了 wLockType
可能的值。
wLockType | 说明 |
---|---|
SQL_LOCK_NO_CHANGE (默认值) |
驱动程序或数据源可确保该行处于与调用 RefreshRowset 前相同的锁定或解锁状态。 |
SQL_LOCK_EXCLUSIVE |
驱动程序或数据源以独占方式锁定行。 并非所有数据源都支持此锁定类型。 |
SQL_LOCK_UNLOCK |
驱动程序或数据源解锁行。 并非所有数据源都支持此锁定类型。 |
有关 SQLSetPos
的详细信息,请参阅 Windows SDK。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::Requery
重新生成(刷新)记录集。
virtual BOOL Requery();
返回值
如果记录集已成功重新生成,则为非零值;否则为 0。
备注
如果返回任何记录,则第一条记录将成为当前记录。
为了使记录集反映你或其他用户对数据源进行的添加和删除,必须通过调用 Requery
重新生成记录集。 如果记录集是动态集,它会自动反映你或其他用户对其现有记录所做的更新(但不是添加)。 如果记录集是快照,则必须调用 Requery
来反映其他用户的编辑以及添加和删除。
对于动态集或快照,如果希望使用新筛选器或排序或新参数值重新生成记录集,请调用 Requery
。 通过在调用 Requery
之前将新值分配给 m_strFilter
和 m_strSort
,设置新的筛选器或排序属性。 通过在调用 Requery
之前将新值分配给参数数据成员来设置新参数。 如果筛选器和排序字符串保持不变,则可以重复使用查询,从而提高性能。
如果尝试重新生成记录集失败,则会关闭记录集。 在调用 Requery
之前,可以通过调用 CanRestart
成员函数来确定是否可以重新查询记录集。 CanRestart
不保证 Requery
成功。
注意
仅在调用 Open
后调用 Requery
。
示例
本示例重新生成记录集以应用不同的排序顺序。
CCustomer rsCustSet(&m_dbCust);
// Open the recordset
rsCustSet.Open();
// Use the recordset ...
// Set the sort order and Requery the recordset
rsCustSet.m_strSort = _T("L_Name, ContactFirstName");
if (!rsCustSet.CanRestart())
return; // Unable to requery
if (!rsCustSet.Requery())
// Requery failed, so take action
AfxMessageBox(_T("Requery failed!"));
CRecordset::SetAbsolutePosition
将记录集放置在对应于指定记录编号的记录上。
void SetAbsolutePosition(long nRows);
参数
nRows
记录集中当前记录的基于 1 的序号位置。
备注
SetAbsolutePosition
根据此序号位置移动当前记录指针。
注意
此成员函数对仅前进记录集无效。
对于 ODBC 记录集,绝对位置设置为 1 表示记录集中的第一条记录;设置为 0 表示文件开头 (BOF) 位置。
还可以将负值传递给 SetAbsolutePosition
。 在这种情况下,记录集的位置从记录集末尾开始计算。 例如,SetAbsolutePosition( -1 )
将当前记录指针移动到记录集中的最后一条记录。
注意
绝对位置不应用作代理项记录编号。 书签仍然是保留并返回到给定位置的建议方法,因为删除前一条记录时记录的位置会改变。 此外,如果再次重新创建记录集,则无法确保给定记录集具有相同的绝对位置,因为不能保证记录集中各个记录的顺序,除非使用 ORDER BY
子句通过 SQL 语句创建记录集。
有关记录集导航和书签的详细信息,请参阅记录集:滚动 (ODBC) 和记录集:书签和绝对位置 (ODBC)。
CRecordset::SetBookmark
将记录集放置在包含指定书签的记录上。
void SetBookmark(const CDBVariant& varBookmark);
参数
varBookmark
对包含特定记录书签值的 CDBVariant
对象的引用。
备注
若要确定记录集是否支持书签,请调用 CanBookmark
。 若要使书签可用(如果受支持),必须在 Open
成员函数的 dwOptions
参数中设置 CRecordset::useBookmarks
选项。
注意
如果书签不受支持或不可用,则调用 SetBookmark
将导致引发异常。 仅向前记录集不支持书签。
若要首先检索当前记录的书签,请调用 GetBookmark
,它将书签值保存到 CDBVariant
对象。 稍后,可以通过调用 SetBookmark
使用已保存的书签值返回到该记录。
注意
执行某些记录集操作后,应在调用 SetBookmark
之前检查书签持久性。 例如,如果检索带有 GetBookmark
的书签,然后调用 Requery
,则该书签可能不再有效。 调用 CDatabase::GetBookmarkPersistence
,以检查是否可以安全调用 SetBookmark
。
有关书签和记录集导航的详细信息,请参阅记录集:书签和绝对位置 (ODBC) 和记录集:滚动 (ODBC)。
CRecordset::SetFieldDirty
将记录集的字段数据成员标记为已更改或未更改。
void SetFieldDirty(void* pv, BOOL bDirty = TRUE);
参数
pv
包含记录集中或 NULL
中的字段数据成员的地址。 如果为 NULL
,则会标记记录集中的所有字段数据成员。 (C++ NULL
与数据库术语中的 Null 不同,后者意味着“没有值”。)
bDirty
如果字段数据成员标记为“脏”(已更改),则为 TRUE
。 如果字段数据成员标记为“干净”(未更改),则为 FALSE
。
注解
将字段标记为未更改可确保字段未更新,并导致 SQL 流量减少。
注意
此成员函数不适用于使用批量行提取的记录集。 如果已实现批量行提取,则 SetFieldDirty
将导致断言失败。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
框架标记更改的字段数据成员,以确保它们通过记录字段交换 (RFX) 机制写入到数据源中的记录。 更改字段的值通常会自动将字段设置为“脏”,因此很少需要自行调用 SetFieldDirty
,但有时你可能希望确保无论字段数据成员中的值是什么,都会显式更新或插入列。
对函数的第一个参数使用 NULL
会将函数仅应用于 outputColumn
字段,而不是 param
字段。 例如,调用
SetFieldNull(NULL);
仅将 outputColumn
字段设置为 NULL
;param
字段不受影响。
若要处理 param
字段,必须提供要处理的单个 param
的实际地址,例如:
SetFieldNull(&m_strParam);
这意味着你不能像设置 outputColumn
字段那样将所有 param
字段设置为 NULL
。
CRecordset::SetFieldNull
将记录集的字段数据成员标记为 Null(特别是没有值)或非 Null。
void SetFieldNull(void* pv, BOOL bNull = TRUE);
参数
pv
包含记录集中或 NULL
中的字段数据成员的地址。 如果为 NULL
,则会标记记录集中的所有字段数据成员。 (C++ NULL
与数据库术语中的 Null 不同,后者意味着“没有值”。)
bNull
如果将字段数据成员标记为没有值 (Null),则为非零值。 如果字段数据成员标记为“非 Null”,则为 0。
备注
向记录集添加新记录时,所有字段数据成员最初都设置为 Null 值,并标记为“脏”(已更改)。 从数据源检索记录时,其列已有值或为 Null。
注意
不要对正在使用批量行提取的记录集调用此成员函数。 如果已实现批量行提取,那么调用 SetFieldNull
将导致断言失败。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
如果特别希望将当前记录的字段指定为没有值,则调用 SetFieldNull
,同时将 bNull
设置为 TRUE
,将其标记为 Null。 如果字段之前标记为 Null,并且现在想要为其指定一个值,请设置其新值。 无需使用 SetFieldNull
删除 Null 标记。 若要确定是否允许字段为 Null,请调用 IsFieldNullable
。
对函数的第一个参数使用 NULL
会将函数仅应用于 outputColumn
字段,而不是 param
字段。 例如,调用
SetFieldNull(NULL);
仅将 outputColumn
字段设置为 NULL
;param
字段不受影响。
若要处理 param
字段,必须提供要处理的单个 param
的实际地址,例如:
SetFieldNull(&m_strParam);
这意味着你不能像设置 outputColumn
字段那样将所有 param
字段设置为 NULL
。
注意
将参数设置为 Null 时,在打开记录集之前调用 SetFieldNull
将导致断言。 在这种情况下,调用 SetParamNull
。
SetFieldNull
通过 DoFieldExchange
实现。
CRecordset::SetLockingMode
将锁定模式设置为“乐观”锁定(默认)或“悲观”锁定。 确定如何锁定记录以进行更新。
void SetLockingMode(UINT nMode);
参数
nMode
包含 enum LockMode
中的以下值之一:
optimistic
乐观锁定将仅锁定在调用Update
期间更新的记录。pessimistic
悲观锁定在调用Edit
时立即锁定该记录,并保持锁定状态,直到Update
调用完成或移至新记录。
备注
如果需要指定记录集用于更新的两种记录锁定策略中的一种,请调用此成员函数。 默认情况下,记录集的锁定模式为 optimistic
。 可以将此更改为更谨慎的 pessimistic
锁定策略。 在构造并打开记录集对象之后且调用 Edit
之前调用 SetLockingMode
。
CRecordset::SetParamNull
将参数标记为 Null(特别是没有值)或非 Null。
void SetParamNull(
int nIndex,
BOOL bNull = TRUE);
参数
nIndex
参数的从零开始的索引。
bNull
如果为 TRUE
(默认值),则该参数将标记为 Null。 否则,参数将标记为非 Null。
注解
与 SetFieldNull
不同,可以在打开记录集之前调用 SetParamNull
。
SetParamNull
通常与预定义查询一起使用(存储过程)。
CRecordset::SetRowsetCursorPosition
将光标移动到当前行集中的行。
void SetRowsetCursorPosition(WORD wRow, WORD wLockType = SQL_LOCK_NO_CHANGE);
参数
wRow
行在当前行集中基于 1 的位置。 此值的范围可以是 1 到行集的大小。
wLockType
该值指示如何在刷新行后锁定该行。 有关详细信息,请参阅“备注”。
备注
实现批量行提取时,将按行集检索记录,其中所提取的行集中的第一条记录为当前记录。 若要在行集中创建另一条记录,请调用 SetRowsetCursorPosition
。 例如,可以将 SetRowsetCursorPosition
与 GetFieldValue
成员函数结合使用,以从记录集的任何记录动态检索数据。
若要使用 SetRowsetCursorPosition
,必须通过在 Open
成员函数中指定 dwOptions
参数的 CRecordset::useMultiRowFetch
选项来实现批量行提取。
SetRowsetCursorPosition
调用 ODBC API 函数 SQLSetPos
。 wLockType
参数指定执行 SQLSetPos
后行的锁定状态。 下表描述了 wLockType
可能的值。
wLockType |
说明 |
---|---|
SQL_LOCK_NO_CHANGE (默认值) |
驱动程序或数据源可确保该行处于与调用 SetRowsetCursorPosition 前相同的锁定或解锁状态。 |
SQL_LOCK_EXCLUSIVE |
驱动程序或数据源以独占方式锁定行。 并非所有数据源都支持此锁定类型。 |
SQL_LOCK_UNLOCK |
驱动程序或数据源解锁行。 并非所有数据源都支持此锁定类型。 |
有关 SQLSetPos
的详细信息,请参阅 Windows SDK。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::SetRowsetSize
指定希望在提取期间检索的记录数。
virtual void SetRowsetSize(DWORD dwNewRowsetSize);
参数
dwNewRowsetSize
在给定提取期间要检索的行数。
备注
此虚拟成员函数指定在使用批量行提取时在单个提取期间要检索的行数。 要实现批量行提取,必须在 Open
成员函数的 dwOptions
参数中设置 CRecordset::useMultiRowFetch
选项。
注意
在不实现批量行提取的情况下调用 SetRowsetSize
将导致断言失败。
在调用 Open
之前调用 SetRowsetSize
以最初设置记录集的行集大小。 实现大容量行提取时的默认行集大小为 25。
注意
调用 SetRowsetSize
时要谨慎使用。 如果手动为数据分配存储(由 Open
中 dwOptions 参数的 CRecordset::userAllocMultiRowBuffers
选项指定),则应在调用 SetRowsetSize
之后且执行任何游标导航操作之前,检查是否需要重新分配这些存储缓冲区。
若要获取行集大小的当前设置,请调用 GetRowsetSize
。
有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
CRecordset::Update
通过在数据源上保存新数据或编辑的数据来完成 AddNew
或 Edit
操作。
virtual BOOL Update();
返回值
如果成功更新了一条记录,那么为非零值;如果未更改任何列,则为 0。 如果未更新任何记录,或者更新了多个记录,则会引发异常。 对于数据源上的任何其他故障,也会引发异常。
备注
调用 AddNew
或 Edit
成员函数后调用此成员函数。 完成 AddNew
或 Edit
操作需要进行此调用。
注意
如果已实现批量行提取,则无法调用 Update
。 这将导致断言失败。 虽然类 CRecordset
不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos
编写自己的函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)。
AddNew
和 Edit
都准备了一个编辑缓冲区,在其中放置添加或编辑的数据,以便保存到数据源。 Update
保存数据。 仅更新标记为或检测到“已更改”的字段。
如果数据源支持事务,则可以调用 Update
(及其相应的 AddNew
或 Edit
调用)作为事务的一部分。 有关事务的详细信息,请参阅事务 (ODBC)。
注意
如果调用 Update
时没有事先调用 AddNew
或 Edit
,则 Update
将引发 CDBException
。 如果调用 AddNew
或 Edit
,则必须在调用 Move
操作之前,或者关闭记录集或数据源连接之前调用 Update
。 否则,更改会丢失且没有通知。
有关处理 Update
失败的详细信息,请参阅记录集:记录集如何更新记录 (ODBC)。