Sql 防止重复记录,在创建新记录之前进行查询

Sql 防止重复记录,在创建新记录之前进行查询,sql,database,ms-access,duplicate-removal,Sql,Database,Ms Access,Duplicate Removal,设置:我正在创建一个ms access数据库来记录我和其他人将要完成的实验结果。我已经创建了一个表单和一个子表单;主窗体包含有关设备设置的字段,子窗体包含该设备设置的实验。链接主节点和链接子节点是设置ID 问题:尽管主[设置]表单中的字段仅限于组合框选择,但仍有许多设置组合。因此,当用户在表单中输入信息时,他们可能没有意识到具有相同设置的记录已经存在,并且由于SettingID是一个自动编号,因此它看起来是一个唯一的记录,而实际上它不是 问题:在创建此记录之前,我想对BeforeInsert事件

设置:我正在创建一个ms access数据库来记录我和其他人将要完成的实验结果。我已经创建了一个表单和一个子表单;主窗体包含有关设备设置的字段,子窗体包含该设备设置的实验。链接主节点和链接子节点是设置ID

问题:尽管主[设置]表单中的字段仅限于组合框选择,但仍有许多设置组合。因此,当用户在表单中输入信息时,他们可能没有意识到具有相同设置的记录已经存在,并且由于SettingID是一个自动编号,因此它看起来是一个唯一的记录,而实际上它不是


问题:在创建此记录之前,我想对BeforeInsert事件运行查询,以检查是否存在具有相同设置的记录。如果记录不存在,则按正常进行;如果确实存在,则提醒用户并将其带到该记录。我不知道如何做到这一点。到目前为止,我试图做的事情并不值得一提,但我仍在继续努力,直到有人回答这篇文章

我相信你会想要两样东西,这取决于你对界面的友好程度

唯一索引 在设置表中的列上添加多列唯一索引,在这些列中,您永远不希望在另一行中复制它们的值组合。您可以在KFleschner在您的原始帖子评论中提供的链接中阅读,或者查看此问题的第二个答案,该答案有一个屏幕截图,可以按照以下步骤进行操作:。这将禁止设置表中的重复项

例如,如果您的设置和实验是针对计算机装备的,并且您有一个包含以下列的设置表:

设置ID、RAM_GB、CPU_GHz

然后您的主键将是(SettingID),多列唯一索引将是on(RAM_GB,CPU_GHz),因为您只需要一条具有相同RAM容量和CPU速度的记录

在数据库语言中,您的主键SettingID将是一个已知的。新的多列唯一索引将被称为。两者都可用于标识唯一的行,但主键(代理键)是在任何关系中使用的键,例如实验表中的SettingID

这本身将防止重复问题,因为它将在数据库级别强制执行。但是,它不会自动使表单跳转到具有匹配自然键的记录。相反,Access会向用户发出一条消息,提示您输入了违反索引的记录。但没别的了。用户将不得不取消新记录,自己去找匹配的记录

更新事件之前 插入前事件在新记录输入的第一个字符时触发。有关详细信息,请参阅。这太早了,您需要更新前事件。并向事件添加如下代码:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    Set rst = Me.RecordsetClone
    rst.FindFirst "[SettingID] <> " & Me.SettingID & " AND [RAM_GB] = " & Me.RAM_GB & " AND [CPU_GHz] = " & Me.CPU_GHz
    If Not rst.NoMatch Then
        Cancel = True
        If MsgBox("Setting already exist; goto existing record?", vbYesNo) = vbYes Then
            Me.Undo
            DoCmd.SearchForRecord , , acFirst, "[SettingID] = " & rst("SettingID")
        End If
    End If
    rst.Close
End Sub
Private子表单\u更新前(取消为整数)
Set rst=Me.RecordsetClone
rst.FindFirst“[SettingID]”和[Me.SettingID&”和[RAM_GB]=“&Me.RAM_GB&”和[CPU_GHz]=”&Me.CPU_GHz
如果不是rst.NoMatch,那么
取消=真
如果MsgBox(“设置已存在;转到现有记录?”,vbYesNo)=vbYes,则
我,解开
DoCmd.SearchForRecord,acFirst,“[SettingID]=”&rst(“SettingID”)
如果结束
如果结束
rst.关闭
端接头
此代码假定了以下几点:

  • [RAM_GB]
    [CPU_GHz]
    是多列唯一索引的列
  • [SettingID]
    是主键中的列

  • 根据您的需要调整列名等,然后您还可以提示并自动导航到现有记录。

    您是否为组合设置字段(列)添加了唯一索引?我不确定是否理解此问题。但是,我唯一的索引字段是主键。在主窗体中,我的设置ID(也是子窗体和主窗体之间的链接)是索引主键,在子窗体中,实验ID是索引主键。由于有这么多不同的设置组合,很难仅通过一个数字来识别特定的设置**顺便说一句,我不熟悉ms access。@Remou指的是使用索引来施加您要查找的唯一值。索引不必是表键。请参阅并特别是关于多列索引的部分。谢谢Sybeus。我想我不可能得到一个更直接、更清楚的答案。我唯一关心的是,对于BeforeUpdate方法,我的理解是,每次更改控件(以及字段)和更新记录时,它都会触发,但我只希望在更新记录时,此代码运行一次。我也不知道为什么需要我。撤销。忽略我在上面评论中的第三句话。BeforeUpdate事件是为表单设置的,duh!无需担心。me.Undo将取消新记录并丢弃用户填写的所有表单数据,或撤销对现有记录编辑的挂起更改,具体取决于触发事件的原因。如果您没有,那么表单将不会处于准备执行搜索的状态,并且将在DoCmd.SearchForRecord.Ah上失败,我将它与Cancel=True混淆。“Cancel=True”似乎只是阻止记录更新,而“Me.Undo”则通过取消记录来实现。再次感谢。