【问题标题】:How to MySQL work "case insensitive" and "accent insensitive" in UTF-8MySQL 如何在 UTF-8 中“区分大小写”和“不区分重音”
【发布时间】:2012-06-05 13:28:15
【问题描述】:

我在“utf8 -- UTF-8 Unicode”中有一个模式作为字符集和“utf8_spanish_ci”的排序规则。

所有内部表都是 InnoDB,具有相同的字符集和排序规则。

问题来了:

使用类似的查询

SELECT *
FROM people p
WHERE p.NAME LIKE '%jose%';

我得到 83 个结果行。我应该有 84 个结果,因为我知道。

更改位置:

WHERE p.NAME LIKE '%JOSE%';

我得到完全相同的 83 行。 使用 JoSe、Jose、JOSe 等组合。报告所有相同的 83 行。

当重音在游戏中出现时,问题就出现了。如果这样做:

WHERE p.NAME LIKE '%josé%';

我没有得到任何结果。 0 行。

但如果我这样做:

WHERE p.NAME LIKE '%JOSÉ%';

我只得到一个结果行,所以 1 行。这是唯一带有重音“jose”并大写的行。

我尝试过使用 josÉ 或 JoSÉ 或我所做的任何组合,只要重音字母是否保持大写,因为它确实存储在数据库中并且它仍然返回唯一的行。如果我突然用 JOSE 中的大写字母组合将“É”更改为“é”,它不会返回任何行。

所以结论:

  • 如果游戏中没有拉丁字符,则不区分大小写。
  • 如果出现拉丁字符,则区分大小写。
  • 重音敏感,就像我搜索 JOSE 或 jose 一样,我只得到 83 行,而不是我需要的 84 行。

我想要什么?

  • 要搜索“jose”、“JOSE”、“José”、“JOSÉ”、“JÒSE”、“jöse”、“JoSÈ”……必须返回我知道存在的 84 行。我如何将我的搜索变成不区分大小写和不区分“拉丁”的。

LIKE 上的 COLLATION 之类的解决方案对我不起作用,不知道为什么...

我能做什么?

编辑:

如果我这样做:

WHERE p.NAME LIKE '%jose%' COLLATE utf8_general_ci;

我得到错误:

COLLATION 'utf8_general_ci' 对 CHARACTER SET 'latin1' 无效

我也更改了列上所有可能的排序规则!

如果我这样做:

WHERE p.NAME LIKE _utf8 '%jose%' COLLATE utf8_general_ci;

同样的83行报出来,好像我什么都没做……

【问题讨论】:

  • 您找到解决方案了吗?我在使用字符“ã”和“Ô的数据库中遇到同样的问题。如果我搜索“joao”,它将检索“joao”和“Joao”,这意味着它会找到具有不同大小写的单词,但不会找到带有重音的单词。如果我搜索“João”,它不会检索 A 大写为“JOÃO”的记录。我什至尝试创建一个包含 4 个字段和 4 个不同排序规则(ut8_general_ci、utf8_unicode_ci、utf8_bin 和 latin1_general_ci)的表来插入相同的项目并尝试使用每一列进行搜索,但还没有找到解决方案......跨度>

标签: mysql utf-8 case-insensitive non-ascii-characters


【解决方案1】:

您已经尝试使用不区分重音的排序规则进行搜索和排序。

http://dev.mysql.com/doc/refman/5.0/en/charset-collation-implementations.html

问题是,您的 NAME 列似乎存储在 latin1(8 位)字符集中。这就是为什么 mySQL 会这样对你发牢骚:

  COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1'

如果你尝试,你可能会得到你想要的结果

 WHERE CONVERT(p.NAME USING utf8) LIKE _utf8 '%jose%' COLLATE utf8_general_ci;

但是,要小心!

当您在 WHERE 语句中的列上使用任何类型的函数(在此示例中为 CONVERT)时,您会挫败 MySQL 使用索引优化搜索的尝试。如果这个项目变得很大(也就是说,如果您的表中有很多行),您需要以 utf8 格式存储数据,而不是 latin1。 (您可能已经知道您的LIKE '%whatever%' 搜索词也会破坏 MySQL 的索引。)

【讨论】:

  • 谢谢,但它不起作用。我现在的架构在 utf8_general_ci 中。连接也是 UTF8 格式的。表在 utf8_general_ci 中,表中的所有列都在相同的字符集和排序规则上。每一点都没有被声明为 Latin1。问题是,我已经尝试了连接、模式、表和列之间的字符集和排序规则之间的所有可能组合,但没有任何变化。使用您的解决方案,如果我写 "jose"/"josé"/"JOSE"/"JOSÉ"/"JOSÈ"/... 总是返回 83 行!所以它真的变得不区分重音和大小写,但它不会返回真正的重音行!
  • 好的。故障排除的下一步:您的数据是否有可能以 UTF8 以外的方式编码?尝试执行SELECT NAME, LENGTH(NAME) from p where p.name like '%jos%' 并查看“José”是否包含您期望的字符数。还可以尝试不同的 MySQL 客户端程序。特别是如果您使用的是 phpmyadmin 之类的 Web 客户端程序,则您的数据库可能在该 NAME 列中有 HTML 实体,例如 & 和磅符号 x e 9 分号。这将完全使口音不敏感。
  • 谢谢!你救了我。
  • 对于未来的搜索者,您可以将CONVERT 应用于值(在本例中为'%jose%')而不是列(p.name),然后您将可以使用您的索引。
【解决方案2】:

以防万一其他人偶然发现这个问题,我已经找到了解决问题的方法,至少对我来说是这样。

我正在使用 PHP 从数据库中插入和检索记录。尽管我的数据库、表和列是 utf8 以及 PHP 文件的编码,但事实是 PHP 和 MySQL 之间的连接中使用的编码是使用 latin1 进行的。我设法找到了这个使用

$mysqli->character_set_name();

$mysqli 是你的对象。

为了让搜索按预期开始工作,返回不区分重音和不区分大小写的记录,我必须明确设置连接的字符集。

为此,您只需执行以下操作:

$mysqli->set_charset('utf8');

其中 $mysqli 是您的 mysqli 对象。如果您有一个包装数据库功能的数据库管理类,那么这很容易应用于完整的应用程序。如果没有,您必须在打开连接的任何地方都明确设置。

我希望这对某人有所帮助,因为我已经对此感到害怕了!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 2013-03-06
    • 2014-07-19
    • 2015-03-10
    相关资源
    最近更新 更多