【问题标题】:Truncates Long Text/Memo string to 255 characters when it is a primary key field or "Indexed: Yes (no-duplicates) allowed"当它是主键字段或“索引:是(无重复)允许”时,将长文本/备忘录字符串截断为 255 个字符
【发布时间】:2013-08-29 17:59:54
【问题描述】:

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

String 存储 256 个字符: Lorem Ipsumiss 只是印刷和排版行业的虚拟文本 Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟文本,当时一位不知名的印刷商使用打字机并对其进行编辑以制作类型样本书,它不仅幸存了五个世纪,而且还幸存了下来

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

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

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

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

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

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

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

【问题讨论】:

  • 附带问题:为什么要将 long text 字段设为主键?为什么不只使用自动编号字段?你真的要加入这个领域,还是试图将其限制为唯一的文本?
  • @LittleBobbyTables 是的,它是唯一的文本。即使它不是主键,如果在表设计中为该列设置了不允许重复的值,问题仍然存在。
  • 索引备忘录字段是一个不稳定的提议。索引键仅使用备注字段值的前 255 个字符。
  • @HansUp 有什么解决办法吗?我正在存储 400-1000 个字符的长字符串唯一值。
  • 抱歉,MS Access 对您来说没有好消息。如果我想膨胀 db 文件大小,我只会索引一个备忘录字段。 ;-) 我认为您真的想要一个能够正确支持全文搜索的数据库。访问只是没有削减它。

标签: ms-access ms-access-2013


【解决方案1】:

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

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

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


备选方案 1

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

备选方案 2:

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


备选方案 3(感谢 @HansUp 在 cmets 中提出的建议):

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

此方法的注意事项

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

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

【讨论】:

  • +1 我喜欢。计算备忘录文本的哈希值,将哈希值存储在文本字段中,并(间接)通过哈希字段上的唯一索引强制备忘录字段的唯一性如何?至少索引的大小可以合理,并且您可以避免冗余存储备忘录“块”。这肯定是漫长的过程......但我们同意这不是 Access 非常适合的任务。 :-)
  • @HansUp:好主意,不知道为什么我没有想到。特别是因为我最近一直在讨论在不同项目中使用散列。虽然它不适用于我们的项目,但我们实际上是在讨论如何使用散列来加速搜索和识别任意大项目的重复项。正是 OP 在这里处理的问题!
  • 我非常感谢您描述哈希方法的方式。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 1970-01-01
  • 2017-09-14
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多