我想对
LONGBLOB
包含阿拉伯文本数据的字段执行搜索。例如,如何搜索“هذه «الأولويات الدواوينية» ف”?表字段的值如下
3313537353B2623313630363B2623313631303B202623313630343B2623313537353B2623313630363B202623313539303B2623313538313B2623313537353B2623313631303B2623313537353B2623313630373B2623313630353B2026
;但是,如果我检索阿拉伯文本值并显示在网页上,它会显示正确的阿拉伯字符。如果我将字段的数据类型从 更改
LONGBLOB
为LONGTEXT
,是否会影响我存储的阿拉伯语内容文本?我在该表中有近 1500 条记录。
2 回答
了解字符及其编码之间的区别很重要。例如,字符
ن
将根据其编码以非常不同的字节存储。例如,0xcc
如果使用 IBM1097 代码页编码,它将由单字节表示,但0xfefffee5
如果使用 UTF-16 编码,它将由四字节序列表示。更糟糕的是,有时相同的字符可以在相同的编码中以多种方式表示。除非 MySQL 知道使用了哪种编码,否则它将无法执行您需要的排序的文本比较(虽然它可以执行二进制比较来搜索相同的字节序列,但这不会应用您想要的排序规则 - 即字符串如何比较,例如不区分大小写,或表示相同字符的不同字节序列)。
因此,您必须在执行搜索时向 MySQL 提供编码信息,或者让 MySQL 从它第一次接收数据的那一刻起跟踪它(即通过将数据存储在字符串类型的列中,而不是二进制类型的列中) )。
将文本数据存储在字符串类型的列中更为常见(实际上我强烈建议您)。
LONGTEXT
是一种可能性,但对于您的需求可能有点过分:它可以存储多达 4GiB 的数据!也许TEXT
或VARCHAR
(最多可容纳 64KiB)或MEDIUMTEXT
(最多 16MiB)会更合适?一旦被理解为字符数据,MySQL 就可以使用其字符串比较函数或正则表达式来简单地搜索文本。例如:
SELECT * FROM mytable WHERE textcolumn LIKE '%هذه «الأولويات الدواوينية» ف%';
这将搜索
mytable
其textcolumn
字段包含(根据其排序规则)其中任何位置的指定字符串的任何记录。您必须首先了解现有数据以什么编码存储在
LONGBLOB
列中(这将是原始客户端在插入/更新数据时使用的任何编码)。然后,您可以毫无问题地将其转换为字符串类型列 - 尽管请注意,如果记录之间存在差异,您将必须根据具体情况管理每条记录的转换(但您也会面临同样的问题无论如何检索当前数据时)。例如,如果数据使用 UTF-8 编码,则可以将列转换
TEXT
为:ALTER TABLE mytable MODIFY textcolumn TEXT CHARACTER SET utf8;
请注意,您必须确保为您的客户端正确配置了连接字符集,以确保在发送/检索字符串数据时发生任何必要的转换。
以下是我认为您的两个选项的可能解决方案:
保留 longblob:如果您想搜索文本的全部内容,您总是可以在 longblob 上执行 MD5 总和(或任何其他散列算法......无论对您有用)并搜索它。您还可以索引此 MD5 列,以便在将其设为 longint 或其他内容时进行超快速搜索。
这种方法的一个问题是您必须知道整个文本内容才能找到记录。一个可能的解决方案是提供链接到表中记录的主题标记,您可以将其存储在单独的表中并进行搜索。然后,您可以从 longblob 表中返回与标记匹配的行。一个例子是,如果你有一些关于电影、剧院、评论家和演员的文本,你将为“电影”、“剧院”、“评论家”和“演员”创建标记,将这些标记存储在标记表中包含该文章的 longblob 表条目的外键,然后当用户搜索“movie”和/或“critic”和/或等时,您将返回 longblob 表中的该行,因为它与那些特定的标记匹配。
更改为长文本:如果您转换为使用长文本,它将为您提供更好的搜索功能(但速度较慢),因为您将能够在内部进行搜索。如果是我,我会创建一个长文本作为主字段类型的新表,并编写一个脚本,从 blob 中读取阿拉伯数据,然后将其作为文本写入新表。如果您确保您的格式等是正确的,它不应该损坏您的数据。我不确定只是简单地转换它是否会损坏它......你总是可以做一个测试用例,用一个longblob制作一个表格,用一些阿拉伯文本填充它,然后将该列转换为一个长文本和走着瞧吧。