当它是主键字段或“索引:是(不重复)允许”时,将长文本/备注字符串截断为255个字符

时间:2013-08-29 17:59:55

标签: ms-access ms-access-2013

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

字符串存储256个字符: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelectr

String Gave Error: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelect1

String Gave Error: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelect2

String Gave Error: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelect123

不会出错: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelec1

不会出错: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelec2

不会出错: LoremIpsumissimplydummytextoftheprintingandtypesettingindustryLoremIpsumhasbeentheindustrysstandarddummytexteversincethe1500swhenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbookIthassurvivednotonlyfivecenturiesbutalsotheleapintoelec3

请注意上述样本的最后几个字符的差异。第一个存储的字符串有256个字符。即使列不是主键,如果在该列的表设计中将“索引:是(不重复)允许”值设置为true,问题仍然相同。

1 个答案:

答案 0 :(得分:5)

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

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

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


备选方案1

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

  7. 备选方案2:

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


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

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

      • 正如pigeonhole principle容易证明的那样,两个不同的字符串可能会生成相同的哈希值(碰撞)。但是,使用良好的散列算法会使实际概率逼近零。
      • 这个site提供了各种散列算法的VB6 / VBA / VBScript实现。我不能保证他们的正确性,但是他们通过了眼睛测试。使用风险自负,但这至少是一个很好的起点。
      • 实际上,您可以使用任意deterministic function,在任意大的输入下返回255个字符或更少的字符串。糟糕的哈希算法和好的哈希算法之间的区别在于它最小化冲突的程度。出于这个原因,我建议你使用一个基于流行标准的。

      是的,我仍然强烈建议@ HansUp的解决方案只使用不同的数据库引擎。