1

我在 MS Access 2013 中创建了一个表,其中只有一列“长文本”类型(之前称为备忘录),并将其作为表的主键。我存储了一个包含 255 个以上字符的长字符串,然后我尝试存储另一个字符串,其前 255 个字符与之前存储的字符串相同,但前 255 个字符之后的所有其他字符都不同,并且 MS Access 给出了“重复数据”错误。在新字符串中,我使用不同的字符组合更改了第 255 位之后的字符,但都给出了错误。但是当我在第 255 个位置之前更改任何字符时,它不会给出任何错误。因此,我得出结论,MS Access 仅检查“长文本”数据类型的前 255 个字符以检查该列中的重复项。是这样吗?还有什么理由?

存储 256 个字符的字符串: Lorem Ipsumiss 印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是该行业的标准虚拟文本,当时一位未知的印刷商使用了打字机并进行了编辑以制作类型样本书

字符串出现错误:Lorem Ipsumiss 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟文本,当时一位未知的印刷商进行了打字并进行了编辑以制作类型样本书它不仅幸存了五个世纪,而且还幸存了 1

字符串给出错误:Lorem Ipsumiss 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟文本,当时一位未知的印刷商进行了打字机并进行了编辑以制作类型样本书它不仅幸存了五个世纪,而且还幸存了下来2

字符串出现错误:Lorem Ipsumiss 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟文本,当时一位未知的印刷商进行了打字并进行了编辑以制作类型样本书,它不仅存在五个世纪,而且还幸存了 123

不给出错误:Lorem Ipsumiss 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是该行业的标准虚拟文本,当时一位未知的印刷商进行了打字并进行了编辑以制作类型样本书它不仅存在五个世纪,而且还存在于 lepintoelec1

不给出错误:Lorem Ipsum 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是该行业的标准虚拟文本,当时一位未知的印刷商在打字机上进行了打字并进行编辑以制作类型样本书,它不仅存在五个世纪,而且还存在于 lepintoelec2

不给出错误:Lorem Ipsumiss 暗示印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟文本,当时一位未知的印刷商在打字机上进行了打字并进行编辑以制作类型样本书,它不仅存在五个世纪,而且还存在于 lepintoelec3

请注意上述示例最后几个字符的不同。第一个存储的字符串有 256 个字符。即使该列不是主键,如果在该列的表设计中将“Indexed: Yes (no-duplicates) allowed”值设置为 true,问题仍然存在。

4

1 回答 1

5

正如评论中的@HansUp 所述,Access(特别是 Jet/ACE db 引擎)仅使用备注/长文本字段的前 255 个字符来创建其索引。因此,它仅使用前 255 个字符来强制执行无重复。

@HansUp 建议使用不同的数据库引擎,为长字符串和全文搜索提供更好的支持,这可能是最好的方法,但我知道通常有其他考虑因素可能会限制您在 Access 中解决问题。

因此,这是解决您的问题的仅限访问的方法。这假设您在评论中列出的要求是有效的;即,您需要存储 400 到 1000 个字符之间的唯一字符串。


备选方案 1

  1. 保留您的初始备忘录/长文本字段:注释
  2. 创建最多 250 个字符的四个文本字段(不是备忘录/长文本):Notes1、Notes2、Notes3、Notes4
  3. 设置所有四个文本字段:必填 -> 真和允许零长度 -> 真(这是确保对少于 751 个字符的字符串强制执行唯一索引所必需的)
  4. 创建唯一索引并将所有四个文本字段添加到该索引
  5. 不要忽略索引中的空值
  6. 存储值时,您需要将它们存储在 Notes 字段中,并将字符串拆分到四个较小的 NotesX 字段中

备选方案 2:

保留您当前的设置并在代码级别强制执行唯一性。每次更新或插入注释时,搜索与前 255 个字符匹配的所有注释,读取值并在代码中执行比较。


备选方案 3(感谢 @HansUp 在评论中提出这一建议):

  1. 保留您的初始备忘录/长文本字段:注释
  2. 创建一个 16 或 32 字符的文本字段来存储长文本的 256 位或 512 位哈希:NotesHash
  3. 向 NotesHash 字段添加唯一索引
  4. 每次更改 memo 字段时,重新计算哈希值并尝试将其存储在表中

此方法的注意事项

  • 正如鸽巢原理很容易证明的那样,两个不同的字符串有可能生成相同的哈希(冲突)。但是,使用好的散列算法会使实际概率接近于零。
  • 站点提供了各种散列算法的一些 VB6/VBA/VBScript 实现。我不能保证他们的正确性,但他们为我通过了视力测试。使用风险自负,但这至少是一个很好的起点。
  • 实际上,您可以使用任何确定性函数,该函数在给定任意大输入的情况下返回 255 个或更少字符的字符串。蹩脚的散列算法和好的散列算法之间的区别在于它如何最大限度地减少冲突。因此,我建议您使用基于流行标准的标准。

是的,我仍然强烈推荐@HansUp 的解决方案来简单地使用不同的数据库引擎。

于 2013-08-29T20:40:48.400 回答