记录集:AddNew、Edit 和 Delete 的工作方式 (ODBC)

本主题适用于 MFC ODBC 类。

本主题介绍 CRecordset 类的 AddNewEditDelete 成员函数的工作方式。 涵盖的主题包括:

注意

本主题适用于从 CRecordset 派生的对象,其中尚未实现批量提取行。 如果使用批量提取行,请参阅记录集:批量提取记录 (ODBC)

作为补充,你可能需要阅读记录字段交换:RFX 的工作原理,其中描述了 RFX 在更新操作中的相应角色。

添加记录

向记录集添加新记录涉及调用记录集的 AddNew 成员函数、设置新记录的字段数据成员的值,以及调用 Update 成员函数以将记录写入数据源。

作为调用 AddNew 的前提条件,记录集不得以只读方式打开。 使用 CanUpdateCanAppend 成员函数可以确定这些条件。

调用 AddNew 时:

  • 将存储编辑缓冲区中的记录,因此如果取消该操作,可以还原其内容。

  • 将标记字段数据成员,因此以后可以检测其中的更改。 字段数据成员也标记为干净(未更改)并设置为 Null。

调用 AddNew 后,编辑缓冲区表示新的空记录,可以在其中填充值。 为此,可以通过分配值来手动设置这些值。 可以调用 SetFieldNull 来指定值 Null,而不是为字段指定实际数据值。

若要提交更改,请调用 Update。 为新记录调用 Update 时:

  • 如果 ODBC 驱动程序支持 ::SQLSetPos ODBC API 函数,则 MFC 将使用该函数在数据源上添加记录。 使用 ::SQLSetPos,MFC 可以更高效地添加记录,因为它不必构造和处理 SQL 语句。

  • 如果无法使用 ::SQLSetPos,MFC 将执行以下操作:

    1. 如果未检测到任何更改,Update 不执行任何操作并返回 0。

    2. 如果有更改,Update 将构造 SQL INSERT 语句。 所有脏字段数据成员表示的列都列在 INSERT 语句中。 若要强制包含列,请调用 SetFieldDirty 成员函数:

      SetFieldDirty( &m_dataMember, TRUE );
      
    3. Update 提交新记录 - 执行 INSERT 语句,并将记录提交到数据源(以及记录集,如果不是快照)上的表,除非事务正在进行中

    4. 存储的记录将还原到编辑缓冲区。 无论 INSERT 语句是否已成功执行,调用 AddNew 之前的当前记录都会再次成为当前记录。

    提示

    若要完全控制新记录,请采用以下方法:设置将具有值的任何字段的值,然后通过使用指向字段的指针和参数 TRUE(默认值)调用 SetFieldNull 来显式设置将保持 Null 的任何字段。 如果要确保不将某个字段写入数据源,请使用指向该字段的指针和参数 FALSE 调用 SetFieldDirty,并且不要修改字段的值。 若要确定是否允许某个字段为 Null,请调用 IsFieldNullable

    提示

    为了检测记录集数据成员何时更改值,MFC 使用适用于可以存储在记录集中的每种数据类型的 PSEUDO_NULL 值。 如果必须将字段显式设置为 PSEUDO_NULL 值,并且该字段恰好已标记为 Null,则还必须调用 SetFieldNull,在第一个参数中传递字段的地址,在第二个参数中传递 FALSE。

添加的记录的可见性

添加的记录何时对记录集可见? 添加的记录有时会显示,有时不可见,具体取决于两项因素:

  • 驱动程序能够执行的操作。

  • 框架可以利用的内容。

如果 ODBC 驱动程序支持 ::SQLSetPos ODBC API 函数,则 MFC 将使用该函数添加记录。 使用 ::SQLSetPos,添加的记录对任何可更新的 MFC 记录集都可见。 如果没有对函数的支持,则添加的记录不可见,必须调用 Requery 才能查看这些记录。 使用 ::SQLSetPos 也更高效。

编辑现有记录

编辑记录集中的现有记录涉及滚动到记录、调用记录集的 Edit 成员函数、设置新记录的字段数据成员的值以及调用 Update 成员函数以将更改的记录写入数据源。

作为调用 Edit 的前提条件,记录集必须是可更新的并且位于记录上。 使用 CanUpdateIsDeleted 成员函数可以确定这些条件。 当前记录也必须尚未删除,并且记录集中必须有记录(IsBOFIsEOF 返回 0)。

调用 Edit 时,将存储编辑缓冲区(当前记录)中的记录。 稍后将使用存储的记录的值来检测是否有任何字段已更改。

调用 Edit 后,编辑缓冲区仍表示当前记录,但现在已准备好接受对字段数据成员的更改。 若要更改记录,请手动设置要编辑的任何字段数据成员的值。 可以调用 SetFieldNull 来指定值 Null,而不是为字段指定实际数据值。 若要提交更改,请调用 Update

提示

若要退出 AddNewEdit 模式,请使用参数 AFX_MOVE_REFRESH 调用 Move

作为调用 Update 的前提条件,记录集不得为空,并且不得已删除当前记录。 IsBOFIsEOFIsDeleted 都应返回 0。

为已编辑的记录调用 Update 时:

  • 如果 ODBC 驱动程序支持 ::SQLSetPos ODBC API 函数,则 MFC 将使用该函数在数据源上更新记录。 使用 ::SQLSetPos,驱动程序会将编辑缓冲区与服务器上的相应记录进行比较,如果两者不同,则更新服务器上的记录。 使用 ::SQLSetPos,MFC 可以更高效地更新记录,因为它不必构造和处理 SQL 语句。

    - 或 -

  • 如果无法使用 ::SQLSetPos,MFC 将执行以下操作:

    1. 如果没有更改,Update 不执行任何操作并返回 0。

    2. 如果有更改,Update 将构造 SQL UPDATE 语句。 UPDATE 语句中列出的列基于已更改的字段数据成员

    3. Update 提交更改(执行 UPDATE 语句),数据源上的记录发生更改,但如果事务正在进行,则不会提交(有关事务如何影响更新的信息,请参阅事务:在记录集中执行事务 (ODBC)。 ODBC 保留记录的副本,该副本也会更改。

    4. AddNew 过程不同,Edit 过程不会还原存储的记录。 已编辑的记录将保留为当前记录。

    注意

    准备通过调用 Update 来更新记录集时,请注意记录集包括构成表主键的所有列(或表上任何唯一索引的所有列,或可唯一标识行的足够多的列)。 在某些情况下,框架只能使用在记录集中选择的列来标识表中要更新的记录。 如果没有所有必要的列,则可能会更新表中的多个记录。 在这种情况下,调用 Update 时,框架会引发异常。

    提示

    如果在之前调用任一函数后但在调用 Update 之前调用 AddNewEdit,则编辑缓冲区将使用存储的记录刷新,从而替换正在添加或编辑的记录。 此行为提供了一种中止 AddNewEdit 并开始处理新记录的方法:如果确定正在处理的记录有问题,只需再次调用 EditAddNew

删除记录

从记录集中删除记录涉及滚动到该记录并调用记录集的 Delete 成员函数。 与 AddNewEdit 不同,Delete 不需要对 Update 进行匹配调用。

作为调用 Delete 的前提条件,记录集必须是可更新的,并且必须位于记录上。 使用 CanUpdateIsBOFIsEOFIsDeleted 成员函数可以确定这些条件。

调用 Delete 时:

  • 如果 ODBC 驱动程序支持 ::SQLSetPos ODBC API 函数,则 MFC 将使用该函数在数据源上删除记录。 使用 ::SQLSetPos 通常比使用 SQL 更高效。

    - 或 -

  • 如果无法使用 ::SQLSetPos,MFC 将执行以下操作:

    1. 编辑缓冲区中的当前记录不会像 AddNewEdit 中那样备份。

    2. Delete 构造一个删除记录的 SQL DELETE 语句

      编辑缓冲区中的当前记录不会像 AddNewEdit 中那样存储。

    3. Delete 提交删除 - 执行 DELETE 语句。 记录在数据源上标记为已删除,如果记录是快照,则在 ODBC 中标记为已删除。

    4. 已删除记录的值仍位于记录集的字段数据成员中,但字段数据成员标记为 Null,并且记录集的 IsDeleted 成员函数返回非零值。

    注意

    删除记录后,应滚动到另一条记录以使用新记录的数据重新填充编辑缓冲区。 再次调用 Delete 或调用 Edit 会出错。

有关更新操作中使用的 SQL 语句的信息,请参阅 SQL

另请参阅

记录集 (ODBC)
记录集:有关更新的更多信息 (ODBC)
记录字段交换 (RFX)