afterupdate在主键中留下空白

时间:2013-10-02 16:23:19

标签: vba ms-access access-vba ms-access-2010

我正在开发一个访问数据库,其中包含一些仅用于数据输入的表单。问题是,当我打开任何这些表单时,访问会在基础表中创建一个新条目,包括递增基础表的自动编号主键,并且即使用户选择不创建记录,自动编号也会保持递增数据库。这意味着由于用户在不提交更改的情况下打开和关闭表单的所有时间,实际表中的自动编号序列存在间隙。

我在beforeupdate方法中使用以下代码来允许用户丢弃错误数据:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    'Provide the user with the option to save/undo
    'changes made to the record in the form
    If MsgBox("Data has been entered into this form." _
        & vbCrLf & vbCrLf & "Do you want to save this data?" _
        , vbYesNo, "Changes Made...") = vbYes Then
            DoCmd.Save
    Else
        DoCmd.RunCommand acCmdUndo
    End If
End Sub  

我原本想过使用beforeinsert事件,但是在使用beforeinsert时打开表单时遇到了问题。

有人可以告诉我如何进行设置,以便不会在自动编号值的序列中创建这些间隙吗?这个数据库可能会被10个并发用户使用。

3 个答案:

答案 0 :(得分:6)

您不应该为自动编号字段的值赋值。自动编号允许您为每一行定义唯一值,并且这样做不保证它们是顺序的。我强烈建议您仅使用自动编号字段来识别唯一记录,而不是某种计数器或人类可读的值。

现在,除此之外,如果您需要每个记录确实具有顺序值,那么您需要做的是

  1. 创建一个单独的表,该表只有一行,一列保存序列中的下一个值。
  2. 每当从数据输入表单保存记录时,您将独占锁定该计数器表,防止任何其他用户读取或写入该表。
  3. 从计数器表中检索当前值,并在新的dataentry记录中使用它。
  4. 更新计数器表中的值以增加到下一个值。
  5. Microsoft提供了一个可以轻松独占锁定表的函数:DAOOpenTableExclusive(),可以找到here

    您可以使用找到的代码here来创建计数器表。

答案 1 :(得分:2)

如果您拥有表单集的记录源,则任何绑定控件的条目都将导致填充任何AutoNumber字段。如果用户放弃或未输入所有必需信息,则跳过该自动编号。

为避免这种情况,您可以自己保存记录。假设您已定义以下表格:

enter image description here

创建以下表单:

enter image description here

后面的代码如下:

Private Sub cmdClose_Click()
  DoCmd.Close
End Sub


Private Sub cmdSave_Click()
  DoCmd.SetWarnings False
  DoCmd.RunSQL "INSERT INTO z_TestTable (DueDate, " & _
                                        "DateReceived, " & _
                                        "Terms, " & _
                                        "ECOFee, " & _
                                        "Classification) " & _
                               "VALUES (#" & txtDueDate & "#, " & _
                                       "#" & txtDateReceived & "#, " & _
                                       "'" & txtTerms & "', " & _
                                       txtECOFee & ", " & _
                                       "'" & txtClassification & "')"
  MsgBox ("RECORD SAVED")
End Sub

Private Sub txtClassification_AfterUpdate()
  funCheckForRequiredFields
End Sub


Private Sub txtDateReceived_AfterUpdate()
  funCheckForRequiredFields
End Sub


Private Sub txtDueDate_AfterUpdate()
  funCheckForRequiredFields
End Sub


Private Sub txtECOFee_AfterUpdate()
  funCheckForRequiredFields
End Sub


Private Sub txtTerms_AfterUpdate()
  funCheckForRequiredFields
End Sub


Function funCheckForRequiredFields()
  Dim NotComplete As Boolean
  NotComplete = False

  If (IsNull(txtDueDate)) Then NotComplete = True
  If (IsNull(txtDateReceived)) Then NotComplete = True
  If (IsNull(txtECOFee)) Then NotComplete = True
  If (IsNull(txtClassification)) Then NotComplete = True
  If (IsNull(txtTerms)) Then NotComplete = True

  If (NotComplete) Then _
    cmdSave.Enabled = False Else _
    cmdSave.Enabled = True
End Function

表单将打开,并禁用保存记录按钮。只有在输入所有字段后才会启用保存记录按钮。按保存记录时,记录将通过DoCmd.RunSQL命令保存。

我在表单上设置控件的格式以与所需的数据相对应。这可确保检查输入的数据的有效性。

通过使用此方法,如果INSERT SQL无效,则使用自动编号字段并且没有保存记录的唯一方法。由于事先进行了检查,因此不应该发生这种情况。

答案 2 :(得分:2)

您可以使用max函数来确定表格中列的最大值,只需在保存之前添加一个。

编辑: 要让它在多用户环境中工作,请将字段“索引”设置为“是(无重复)”。