用外键替换 LongText 字段以节省空间会导致错误:无法执行连接、分组、排序或索引限制

问题描述

我有一个名为 JobQueue 的表,其中包含一个 LongText 类型的名为 Command 的字段。

由于许多行包含相同的 Command 值(通常长约 2000 个字符),我想用一个名为 idCommand 的外键替换 JobQueue 表中的 Command 字段,该外键引用表 Text_1G 中的 id 字段。因此,与其一遍又一遍地存储相同的 2000 个字符串,我只需在 idCommand 中存储一个整数(一遍又一遍)以指向 2000 个(或更多)字符命令的单个副本。

所以我

CREATE TABLE Text_1G (id AUTOINCREMENT PRIMARY KEY,[text] LONGTEXT) 
CREATE UNIQUE INDEX idxText_1G ON Text_1G ([text] ASC)

所以我能够成功地将一行插入到 Text_1G 中,但是当我尝试通过外键 idCommand(左)加入 JobQueue 和 Text_1G 时,我收到此错误

System.Data.OleDb.OleDbException: Cannot perform join,group,sort,or indexed restriction. A value being searched or sorted on is too long

这个左连接似乎适用于较短的字符串,但不适用于长字符串...

糟糕……这个问题有解决方法吗?

我使用的是 Access 版本 16.0.13801.20240。

解决方法

并非如此,Access 无法加入长文本(备注)字段。

一个常见的解决方法是在加入之前截断字段,例如ON LEFT(LongTextField,255) = LEFT(ForeignLongTextField,255)。但是,这可能会导致意外匹配,尤其是在使用代码作为键时,因为可能存在超出前 255 个字符的差异。

一个更困难但更合适的解决方案是使用散列作为连接键,并在散列上连接,例如

ON SHA1(LongTextField) = SHA1(ForeignLongTextField)

但是,这要求您可以使用散列函数,而 Access 没有内置的散列支持。由于您似乎使用.Net,您可以在应用程序层进行散列,将散列存储在数据库中,然后使用散列进行连接。如果您使用 Access 本身,您可以在 VBA 中执行散列,并在查询中使用它,但是,这会带来很大的性能损失,并且需要您实现快速散列。

请注意,由于散列不是用于安全性而是用于散列,因此我通常更喜欢使用结果较小的散列高于提供良好安全性的散列,因此我倾向于使用 MD5 或 SHA1。