仅当 Access 2007 中不存在时才添加记录
Posted
技术标签:
【中文标题】仅当 Access 2007 中不存在时才添加记录【英文标题】:Add record only if doesn't exist in Access 2007 【发布时间】:2009-10-07 15:39:18 【问题描述】:我有一个表,假设它存储员工姓名(这不是确切的情况,但概念是相同的),并且主键设置为自动编号。添加新员工时,我想在添加之前检查该名称是否存在于数据库中,如果它已经存在,则可能会出错。如何从表格的正常添加表单中执行此操作?
我尝试为它创建一个查询,但这不起作用,因为表单是基于表的,并且不能使用查询作为控制源。我在网上看到一些例子说如何用 VB 代码做这样的事情,但我无法让它工作,因为它不是一个简单的例子,而且有些行被遗漏了。
有没有什么简单的方法可以做到这一点?
【问题讨论】:
【参考方案1】:在表格设计视图中,您可以将 Name 列设为 Indexed with No Duplicates
然后 Access 本身将拒绝该条目。但是,我认为它会在拒绝输入之前用完一个自动编号。
【讨论】:
如果您愿意,您可以捕获错误(忘记实际错误号)并显示自定义消息 如果您使用这种技术,您将需要在构成用户名的所有列中创建一个多列索引。这种方法的问题在于它是绝对的——你永远不可能有两个同名的用户。在给定的示例中,这是不可取的。 这也会导致锁定问题。最好编写你的 SQL,这样你就不要尝试附加已经存在的值——即,首先防止错误发生,而不是依赖数据库引擎来拯救你自己。【参考方案2】:您正在处理在将记录插入数据库之前对其进行资格预审的问题。您将永远违反的简单而绝对的规则(例如从不,永远,永远允许具有相同名称的记录)可以通过数据库约束来处理 - 在这种情况下,在相关列上创建索引AllowDuplicates 设置为 No。
但是,在现实世界中,资格预审通常更为复杂。您可能需要简单地警告可能重复的用户,但无论如何都允许他们添加记录。并且您可能需要检查其他表格的某些条件或一次收集多个表格的信息。
在这些情况下,您需要编写接口,使其不直接绑定到表(在 Access 术语中,创建一个记录源为空的表单),在各种控件中收集信息,在代码中执行检查(通常使用 DCOUNT 和 DLOOKUP),然后使用 DoCmd.RunSQL 在代码中发出一系列 INSERT 和 UPDATE 语句。
您偶尔可以使用一些技巧来避免在前端对此进行编码,但迟早您会遇到需要这种级别编码的情况。
【讨论】:
DoCmd.RunSQL 的问题在于它忽略了任何错误。以下任何一项都将显示查询收到的任何错误消息。如果使用 DAO,请使用 Currentdb.Execute strSQL,dbfailonerror.。对于 ADO,请使用 CurrentProject.Connection.Execute strCommand, lngRecordsAffected, adCmdText 然后您可以删除 docmd.setwarnings 行。如果您要使用 docmd.setwarnings ,请确保您也将 True 语句放入任何错误处理代码中。否则以后可能会发生奇怪的事情,尤其是在您开发应用程序时。 我写了一个函数,SQLRun(),作为 DoCmd.RunSQL 的替代品。我还在各种版本中广泛发布了它(有些版本比其他版本好!)。它只是 CurrentDB.Execute 的一个包装器,带有错误处理。【参考方案3】:我将投票支持使用未绑定的表单来收集必填字段并显示可能的重复项。以下是最近应用的示例:
(来源:dfenton.com)
(我编辑了真人的名字并放入了假的东西,我的图形程序的抗锯齿与 ClearType 的不同,因此很奇怪)
这里的想法是用户将数据放入四个字段中的任何一个(不需要所有字段),然后单击添加按钮。第一次,它填充可能的匹配项。然后用户必须决定其中一个匹配项是否是预期的人,然后再次单击添加(添加它,即使它是重复的),或者单击底部的按钮转到所选客户。
彩色指示器旨在传达比赛的接近程度。在这种情况下,输入的电子邮件地址与列出的第一个人完全匹配,电子邮件上的完全匹配本身被认为是完全匹配。此外,在这个特定的应用程序中,客户希望尽量减少多人进入同一公司(这是他们的业务性质),因此组织上的完全匹配被视为部分匹配。
除此之外,还有使用 Soundex、Soundex2 和 Simil 的匹配,以及与 Soundex/Soundex2/Simil 组合的子字符串和子字符串。在这种情况下,第二个条目是重复的,但 Soundex 和 Soundex2 没有捕捉到它,而 Simil 返回 67% 的相似度,并且我已将灵敏度设置为大于 50%,因此“Wightman”显示为关闭与“怀特曼”相匹配。最后一个。我不确定为什么最后两个在列表中,但显然有一些原因(可能是 Simil 和首字母)。
我通过评分例程运行姓名、公司和电子邮件,然后使用组合来计算最终分数。我将 Soundex 和 Soundex2 值存储在每个人的记录中。当然,Simil 必须即时计算,但它运行良好,因为 Jet/ACE 查询优化器知道限制其他字段,因此调用 Simil 以获得大大减少的数据集(这实际上是第一个应用程序我用过 Simil,到目前为止效果很好)。
加载可能的匹配项需要稍作停顿,但速度并不慢(该版本的应用程序有大约 8K 条现有记录正在测试中)。我为一个在 person 表中有 250K 记录的应用程序创建了这个设计,当后端仍然是 Jet 时它运行良好,并且在几年前将后端升级到 SQL Server 后仍然运行良好。
【讨论】:
【参考方案4】:最好的解决方案是让用户输入名字和姓氏的几个字符,并根据这些搜索条件显示所有个人的连续形式。还显示相关信息,例如中间名、电话号码和地址(如果有),以清除潜在的重复项。然后,如果没有找到重复项,则他们可以添加此人。
每个城镇总会有两个 John Smith's 或 Jane Jones。
我读到过这样一种情况,两名妇女的名字、中间名和姓氏以及出生日期都相同,他们在 saem tiem 的一家医院里。真的很可怕。
【讨论】:
【参考方案5】:感谢您提供的所有信息。这是很好的信息,我会使用它,因为我是自学成才的。
我发现这里提到的最简单的方法是在我想要的所有字段上使用索引(没有重复)。这里的技巧实际上是使用多个索引(这基本上允许使用复合索引,或由多个字段组成的“虚拟”索引)。
方法可以在这里找到:http://en.allexperts.com/q/Using-MS-Access-1440/Creating-Unique-Value-check.htm,但如果链接被删除,我会重复它。
从访问帮助: 防止在字段组合中输入重复值
使用要禁止重复值的字段创建多字段索引。完成索引定义后,让“索引”窗口保持打开状态。
怎么做?
-
在设计视图中打开表格。
单击工具栏上的索引。
在索引的第一个空白行中
名称列,输入名称
指数。您可以将索引命名为
索引字段之一,或使用
另一个名字。
在“字段名称”列中,单击
箭头并选择第一个字段
索引。
在字段名称的下一行
列,选择第二个字段
索引。 (留下索引名称
该行中的列空白。)重复
这一步直到你选择了
您要包含的所有字段
在这个索引中。默认排序顺序是
上升。在中选择降序
索引的排序顺序列
窗口对相应的进行排序
字段的数据按降序排列。
在索引的上部
窗口中,点击新的索引名称。
在索引的下部
窗口中,单击唯一属性
框,然后单击是。
您现在应该能够不输入在索引中具有相同值的记录。如果其中一个索引字段有空格,我仍然可以输入值(设置索引时可以选择检查/忽略空值),但它对我不起作用,但解决方案有效,因为反正我不会有空值。
【讨论】:
【参考方案6】:这在 SQL 世界中称为“UPSERT
”。 ISO/ANSI SQL-99 标准定义了一个MERGE
语法,该语法最近被添加到 SQL Server 2008 中,并对该标准进行了专有扩展。令人高兴的是,这就是 SQL 世界的发展方向,追随 mysql 开辟的道路。
遗憾的是,Access 数据库引擎是一个完全不同的故事。即使是简单的UPDATE
也不支持 SQL-92 标量子查询语法,而是有它自己的专有的任意(不可预测?肯定没有记录)结果。 Windows 团队破坏了 SQL Server 在 Jet 4.0 中修复此问题的尝试。即使现在 Access 团队有自己的 ACE 格式,他们似乎也对更改 SQL 语法不感兴趣。因此,他们产品采用标准 SQL-99 甚至是他们自己的替代方案的机会非常遥远 :(
假设性能不是问题(一如既往,需要测试),一个明显的解决方法是执行INSERT
,忽略任何关键故障错误,然后立即执行UPDATE
。即使您是(IMO 高度怀疑的)“每张桌子上的自动编号 PK”的说服力,您的自然键上也应该有一个唯一的键,所以一切都应该没问题。
【讨论】:
以上是关于仅当 Access 2007 中不存在时才添加记录的主要内容,如果未能解决你的问题,请参考以下文章
仅当 Firebase Firestore 中不存在文档时才创建文档