CRecordset

表示从数据源选择的一组记录。

语法

class CRecordset : public CObject

成员

公共构造函数

名称 描述
CRecordset::CRecordset 构造 CRecordset 对象。 派生类必须提供调用此类的构造函数。

公共方法

名称 描述
CRecordset::AddNew 准备添加新记录。 调用 Update 以完成添加。
CRecordset::CanAppend 如果可以通过 AddNew 成员函数将新记录添加到记录集中,则返回非零值。
CRecordset::CanBookmark 如果记录集支持书签,则返回非零值。
CRecordset::Cancel 从第二个线程取消异步操作或进程。
CRecordset::CancelUpdate 由于 AddNewEdit 操作,取消任何挂起的更新。
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 通过在数据源上保存新数据或编辑的数据来完成 AddNewEdit 操作。

公共数据成员

“属性” 描述
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)。 有关动态集和快照的焦点,请参阅动态集快照文章。

继承层次结构

CObject

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)

示例

请参阅事务:在记录集中执行事务 (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 之前,取消任何由 EditAddNew 操作引起的挂起更新。

void CancelUpdate();

备注

注意

此成员函数不适用于使用批量行提取的记录集,因为此类记录集无法调用 EditAddNewUpdate。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)

如果启用了自动脏字段检查,则 CancelUpdate 会将成员变量还原到调用 EditAddNew 之前的值;否则,任何值更改都将保留。 默认情况下,打开记录集时会启用自动字段检查。 若要禁用它,必须在 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 在游标导航操作(例如 OpenRequery 或任何 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

AddNewEdit 不同,调用 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)。 数据会自动从数据源传输到记录集对象。 但是,无法调用 AddNewEditDeleteUpdate 将更改传输回数据源。 类 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_ERRORSQL_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 对象的引用,该对象将存储转换为文本的字段值,而不考虑字段的数据类型。

备注

可以按名称或索引查找字段。 可以将字段值存储在 CDBVariantCString 对象中。

如果已实现批量行提取,则当前记录始终位于行集中的第一条记录上。 若要在给定行集的记录上使用 GetFieldValue,必须先调用 SetRowsetCursorPosition 成员函数,将游标移动到该行集中的所需行。 然后对该行调用 GetFieldValue。 若要实现批量行提取,必须在 Open 成员函数中指定 dwOptions 参数的 CRecordset::useMultiRowFetch 选项。

可以使用 GetFieldValue 在运行时动态提取字段,而不是在设计时静态绑定它们。 例如,如果直接从 CRecordset 中声明记录集对象,则必须使用 GetFieldValue 来检索字段数据;记录字段交换 (RFX),或批量记录字段交换(批量 RFX)未实现。

注意

如果在不派生 CRecordset 的情况下声明记录集对象,则不会加载 ODBC 游标库。 游标库要求记录集至少有一个绑定列;但是,直接使用 CRecordset 时,不会绑定任何列。 成员函数 CDatabase::OpenExCDatabase::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:AddNewUpdate 添加一条记录会增加计数;通过 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 语句的 CStringconst 引用。

备注

这通常为 SQL SELECT 语句。 GetSQL 返回的字符串为只读。

GetSQL 返回的字符串通常不同于你传递给 Open 成员函数的 lpszSQL 参数中的记录集的任何字符串。 这是因为记录集基于你传递给 Open 的内容、通过 ClassWizard 指定的内容、可能已在 m_strFilterm_strSort 数据成员中指定的内容以及可能已指定的任何参数构造完整的 SQL 语句。 有关记录集如何构造此 SQL 语句的详细信息,请参阅记录集:记录集如何选择记录 (ODBC)

注意

仅在调用 Open 后调用此成员函数。

CRecordset::GetTableName

获取记录集查询所基于的 SQL 表名。

const CString& GetTableName() const;

返回值

如果记录集基于表,则是对包含表名的 CStringconst 引用;否则为空字符串。

备注

仅当记录集基于表而不是多个表的联接或预定义查询(存储过程)时,GetTableName 才有效。 名称为只读。

注意

仅在调用 Open 后调用此成员函数。

CRecordset::IsBOF

如果在第一条记录之前定位了记录集,则返回非零值。 没有最新记录。

BOOL IsBOF() const;

返回值

如果记录集不包含任何记录,或者在第一条记录之前向后滚动,则为非零值;否则为 0。

备注

在从一条记录滚动到另一条记录之前调用此成员函数,了解是否已在记录集的第一条记录之前滚动。 还可以将 IsBOFIsEOF 一起使用来确定记录集是否包含任何记录或为空。 调用 Open 后,如果记录集不包含任何记录,IsBOF 将立即返回非零值。 打开至少有一条记录的记录集时,第一条记录为当前记录且 IsBOF 返回 0。

如果第一条记录是当前记录并且你调用 MovePrev,则 IsBOF 将返回非零值。 如果 IsBOF 返回非零值且你调用 MovePrev,则会发生错误。 如果 IsBOF 返回非零值,则当前记录未定义,且任何需要当前记录的操作都将导致错误。

示例

此示例使用 IsBOFIsEOF 来检测在代码向两个方向滚动记录集时记录集的限制。

// 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

确定指定字段数据成员自调用 EditAddNew 以来是否已更改。

BOOL IsFieldDirty(void* pv);

参数

pv
指向要检查其状态的字段数据成员的指针,或用于确定是否有脏字段的 NULL

返回值

如果指定的字段数据成员自调用 AddNewEdit 后已更改,则为非零值;否则为 0。

注解

当通过调用 CRecordsetUpdate 成员函数(在调用 EditAddNew 之后)更新当前记录时,所有脏字段数据成员中的数据都将被转移到数据源上的记录。

注意

此成员函数不适用于使用批量行提取的记录集。 如果已实现批量行提取,则 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 字段设置为 NULLparam 字段不受影响。

若要处理 param 字段,必须提供要处理的单个 param 的实际地址,例如:

SetFieldNull(&m_strParam);

这意味着你不能像设置 outputColumn 字段那样将所有 param 字段设置为 NULL

IsFieldNullable 通过 DoFieldExchange 实现。

CRecordset::IsOpen

确定记录集是否已打开。

BOOL IsOpen() const;

返回值

如果记录集对象的 OpenRequery 成员函数以前已调用且记录集尚未关闭,则为非零值;否则为 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 后在 DoFieldExchangeDoBulkFieldExchange 中注册的“输出列”数相对应。

可以动态绑定列,如“记录集:动态绑定数据列”一文中所述。如果这样做,则必须增加 m_nFields 计数,以反映动态绑定列的 DoFieldExchangeDoBulkFieldExchange 成员函数中 RFX 或批量 RFX 函数调用数。

有关详细信息,请参阅文章记录集:动态绑定数据列 (ODBC)记录集:批量提取记录 (ODBC)

示例

请参阅记录字段交换:使用 RFX

CRecordset::m_nParams

包含记录集类中参数数据成员的数量;也就是说,与记录集查询一起传递的参数数量。

注解

如果记录集类具有任何参数数据成员,则类的构造函数必须用正确数字初始化 m_nParamsm_nParams 默认值为 0。 如果添加参数数据成员(必须手动),还必须在类构造函数中手动添加初始化,以反映参数数量(必须至少与 m_strFilterm_strSort 字符串中的 '' 占位符的数量相同。)

框架在参数化记录集的查询时使用此数字。

注意

该数字必须与使用 CFieldExchange::inputParamCFieldExchange::paramCFieldExchange::outputParamCFieldExchange::inoutParam 参数调用 SetFieldType 后在 DoFieldExchangeDoBulkFieldExchange 中注册的“参数”数量相对应。

示例

请参阅文章记录集:参数化记录集 (ODBC)记录字段交换:使用 RFX

CRecordset::m_pDatabase

包含指向 CDatabase 对象的指针,记录集通过该对象连接到数据源。

备注

此变量有两种设置方式。 通常,构造记录集对象时,会将指针传递给已连接的 CDatabase 对象。 如果改为传递 NULLCRecordset 将为你创建 CDatabase 对象并连接它。 在这两种情况下,CRecordset 将指针存储在此变量中。

通常,你不需要直接使用存储在 m_pDatabase 中的指针。 但是,如果编写自己的 CRecordset 扩展,则可能需要使用指针。 例如,如果引出自己的 CDBException,则可能需要指针。 或者,如果需要使用同一 CDatabase 对象执行某些操作,例如运行事务、设置超时或调用 CDatabaseExecuteSQL 成员函数来直接执行 SQL 语句,则可能需要它。

CRecordset::m_strFilter

构造记录集对象之后,但在调用其 Open 成员函数之前,使用此数据成员来存储包含 SQL WHERE 子句的 CString

备注

记录集使用此字符串来约束(或筛选)在调用 OpenRequery 期间选择的记录。 这对于选择记录的子集非常有用,例如“所有在加州的销售人员”(“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

备注

记录集使用此字符串对在调用 OpenRequery 期间选择的记录进行排序。 可以使用此功能对一个或多个列的记录集进行排序。 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 将结束任何当前 AddNewEdit 模式,并在调用 AddNewEdit 之前还原当前记录的值。

注意

在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅CRecordset::IsDeleted。 当你打开设置了 skipDeletedRecords 选项的 CRecordset 时,如果 nRows 参数为 0,则 Move 将断言。 此行为可防止刷新使用相同数据的其他客户端应用程序删除的行。 有关 skipDeletedRecords 的描述,请参阅 Open 中的 dwOption 参数。

Move 按行集重新定位记录集。 根据 nRowswFetchType 的值,Move 提取相应的行集,然后将该行集中的第一条记录制作为当前记录。 如果尚未实现批量行提取,则行集大小始终为 1。 提取行集时,Move 直接调用 CheckRowsetError 成员函数来处理提取产生的任何错误。

根据传递的值,Move 等效于其他 CRecordset 成员函数。 具体而言,wFetchType 的值可能指示一个更直观的成员函数,通常是移动当前记录的首选方法。

下表列出了 wFetchType 可能的值、Move 将基于 wFetchTypenRows 提取的行集,以及对应于 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_NEXTMove 才有效。

注意

如果记录集没有记录,则调用 Move 将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOFIsEOF

注意

如果已滚动到记录集的开头或结尾(IsBOFIsEOF 返回非零值),则调 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 函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOFIsEOF

注意

如果在更新或添加当前记录时调用任何 Move 函数,更新将丢失,而不会发出警告。

有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)

示例

请参阅 IsBOF 的示例。

CRecordset::MoveLast

使最后完成的行集中的第一条记录成为当前记录。

void MoveLast();

备注

如果尚未实现批量行提取,则记录集的大小为 1,因此 MoveLast 移动到记录集中的最后一条记录。

注意

此成员函数对仅向前记录集无效。

注意

在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted 成员函数。

注意

如果记录集没有记录,则调用任何 Move 函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOFIsEOF

注意

如果在更新或添加当前记录时调用任何 Move 函数,更新将丢失,而不会发出警告。

有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)

示例

请参阅 IsBOF 的示例。

CRecordset::MoveNext

使下一行集中的第一条记录成为当前记录。

void MoveNext();

备注

如果尚未实现批量行提取,则记录集的大小为 1,因此 MoveNext 移动到下一条记录。

注意

在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted 成员函数。

注意

如果记录集没有记录,则调用任何 Move 函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOFIsEOF

注意

此外,建议在调用 MoveNext 之前调用 IsEOF。 例如,如果滚动到记录集末尾,IsEOF 将返回非零值;后续调用 MoveNext 将引发异常。

注意

如果在更新或添加当前记录时调用任何 Move 函数,更新将丢失,而不会发出警告。

有关记录集导航的详细信息,请参阅文章“记录集:滚动 (ODBC)”和“记录集:书签和绝对位置 (ODBC)”。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)

示例

请参阅 IsBOF 的示例。

CRecordset::MovePrev

使前一行集中的第一条记录成为当前记录。

void MovePrev();

注解

如果尚未实现批量行提取,则记录集的大小为 1,因此 MovePrev 移动到上一条记录。

注意

此成员函数对仅向前记录集无效。

注意

在记录集中移动时,无法跳过已删除的记录。 有关详细信息,请参阅 IsDeleted 成员函数。

注意

如果记录集没有记录,则调用任何 Move 函数将引发异常。 若要确定记录集是否有任何记录,请调用 IsBOFIsEOF

注意

此外,建议在调用 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++ 向导可以与具有不同默认值的 ODBC CRecordset 和 DAO CDaoRecordset 进行交互。

有关这些记录集类型的详细信息,请参阅记录集 (ODBC) 。 相关信息请参阅 Windows SDK 中的“使用块和可滚动游标”。

注意

如果请求的类型不受支持,框架将引发异常。

lpszSQL
包含下列项之一的字符串指针:

  • 一个 NULL 指针。

  • 表的名称。

  • SQL SELECT 语句(SQL WHEREORDER BY 子句可选)。

  • 一个 CALL 语句,指定预定义查询的名称(存储过程)。 请注意不要在大括号和 CALL 关键字之间插入空格。

有关此字符串的详细信息,请参阅注解部分下有关 ClassWizard 角色的表和讨论。

注意

结果集中列的顺序必须与 DoFieldExchangeDoBulkFieldExchange 函数替代中 RFX 或批量 RFX 函数调用的顺序匹配。

dwOptions
位掩码,可以指定下面列出的值的组合。 其中一些是互斥的。 默认值为 none

  • CRecordset::none 未设置任何选项。 此参数值与所有其他值互斥。 默认情况下,可以使用 EditDelete 更新记录集,并允许使用 AddNew 来追加新记录。 可更新性取决于数据源和指定的 nOpenType 选项。 批量添加的优化不可用。 不会实现批量行提取。 记录集导航期间不会跳过已删除的记录。 书签不可用。 实现自动脏字段检查。

  • CRecordset::appendOnly 不允许记录集上有 EditDelete。 仅允许 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 浏览记录集时跳过所有已删除的记录。 这将降低某些相对提取的性能。 此选项对仅向前记录集无效。 如果在 MovenRows 参数设置为 0 时调用 ,并且设置了 CRecordset::skipDeletedRecords 选项,那么 Move 将断言。 CRecordset::skipDeletedRecords 类似于驱动程序打包,这意味着从记录集中删除已删除的行。 但是,如果驱动程序打包记录,则只会跳过删除的那些记录;打开记录集时,不会跳过其他用户删除的记录。 CRecordset::skipDeletedRecords 将跳过其他用户删除的行。

  • CRecordset::useBookmarks 可以在记录集上使用书签(如果支持)。 书签会减缓数据检索速度,但提高了数据导航的性能。 对仅向前记录集无效。 有关详细信息,请参阅记录集:书签和绝对位置 (ODBC)

  • CRecordset::noDirtyFieldCheck 关闭自动脏字段检查(双缓冲)。 这将提高性能;但是,必须通过调用 SetFieldDirtySetFieldNull 成员函数手动将字段标记为脏。 CRecordset 类中的双缓冲类似于 CDaoRecordset 类中的双缓冲。 但是,在 CRecordset 中,不能对单个字段启用双缓存;你可以为所有字段启用它,也可以为所有字段禁用它。 如果指定选项 CRecordset::useMultiRowFetch,则 CRecordset::noDirtyFieldCheck 会自动打开;但是,SetFieldDirtySetFieldNull 不能在实现批量行提取的记录集上使用。

  • 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 表名 DoFieldExchangeDoBulkFieldExchange 中表列表的所有列。 "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 WHEREORDER 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 函数 SQLSetPoswLockType 参数指定执行 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_strFilterm_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,但有时你可能希望确保无论字段数据成员中的值是什么,都会显式更新或插入列。

注意

仅在调用 EditAddNew 后调用此成员函数。

对函数的第一个参数使用 NULL 会将函数仅应用于 outputColumn 字段,而不是 param 字段。 例如,调用

SetFieldNull(NULL);

仅将 outputColumn 字段设置为 NULLparam 字段不受影响。

若要处理 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

注意

仅在调用 EditAddNew 后调用此成员函数。

对函数的第一个参数使用 NULL 会将函数仅应用于 outputColumn 字段,而不是 param 字段。 例如,调用

SetFieldNull(NULL);

仅将 outputColumn 字段设置为 NULLparam 字段不受影响。

若要处理 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。 例如,可以将 SetRowsetCursorPositionGetFieldValue 成员函数结合使用,以从记录集的任何记录动态检索数据。

若要使用 SetRowsetCursorPosition,必须通过在 Open 成员函数中指定 dwOptions 参数的 CRecordset::useMultiRowFetch 选项来实现批量行提取。

SetRowsetCursorPosition 调用 ODBC API 函数 SQLSetPoswLockType 参数指定执行 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

通过在数据源上保存新数据或编辑的数据来完成 AddNewEdit 操作。

virtual BOOL Update();

返回值

如果成功更新了一条记录,那么为非零值;如果未更改任何列,则为 0。 如果未更新任何记录,或者更新了多个记录,则会引发异常。 对于数据源上的任何其他故障,也会引发异常。

备注

调用 AddNewEdit 成员函数后调用此成员函数。 完成 AddNewEdit 操作需要进行此调用。

注意

如果已实现批量行提取,则无法调用 Update。 这将导致断言失败。 虽然类 CRecordset 不提供更新批量数据行的机制,但你可以使用 ODBC API 函数 SQLSetPos 编写自己的函数。 有关批量行提取的详细信息,请参阅记录集:批量提取记录 (ODBC)

AddNewEdit 都准备了一个编辑缓冲区,在其中放置添加或编辑的数据,以便保存到数据源。 Update 保存数据。 仅更新标记为或检测到“已更改”的字段。

如果数据源支持事务,则可以调用 Update(及其相应的 AddNewEdit 调用)作为事务的一部分。 有关事务的详细信息,请参阅事务 (ODBC)

注意

如果调用 Update 时没有事先调用 AddNewEdit,则 Update 将引发 CDBException。 如果调用 AddNewEdit,则必须在调用 Move 操作之前,或者关闭记录集或数据源连接之前调用 Update。 否则,更改会丢失且没有通知。

有关处理 Update 失败的详细信息,请参阅记录集:记录集如何更新记录 (ODBC)

示例

请参阅事务:在记录集中执行事务 (ODBC)

另请参阅

CObject
层次结构图
CDatabase
CRecordView