2

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

我在 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 个并发用户使用。

4

3 回答 3

6

您不应该为自动编号字段的值分配任何意义。自动编号允许您为每一行定义唯一值,这样做不保证它们是连续的。我强烈建议您只使用自动编号字段来识别唯一记录,而不是作为某种计数器或人类可读的值。

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

  1. 创建一个单独的表,其中只有一行,一列保存序列中的下一个值。
  2. 每当从数据输入表单中保存记录时,您就可以独占锁定该计数器表,以防止任何其他用户对其进行读取或写入。
  3. 从计数器表中检索当前值并在新的数据条目记录中使用它。
  4. 更新计数器表中的值以递增到下一个值。

Microsoft 提供了一个可以轻松独占锁定表的功能:DAOOpenTableExclusive(),可以在此处找到。

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

于 2013-10-02T17:13:45.910 回答
2

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

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

在此处输入图像描述

并创建了以下表单:

在此处输入图像描述

后面有以下代码:

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 无效。由于事先已对其进行检查,因此永远不会发生这种情况。

于 2013-10-02T18:47:57.913 回答
2

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

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

于 2013-10-04T05:49:19.747 回答