我有一些 MySQL 表,其中“title”列的类型为 varchar(255)
,字符集为 utf8mb4,排序规则为 utf8mb4_general_ci。
假设我有一些带有标题的记录,并且这些标题包含(或不包含)变音符号:
id | title
-----------
1 | zolc
2 | żółć
3 | żołc
4 | zólć
我可以正确插入这些变音符号,并且在选择表格时它们也会正确显示。但是当我尝试这样的事情时:
SELECT *
FROM my_table
WHERE title LIKE "%zolc%";
我得到了:
id | title
-----------
1 | zolc
4 | zólć
如您所见,我要求提供没有任何变音符号的版本,但也得到了 id 为 4 的行。选择 żółć
返回 id 为 2(如预期)和 3 的行。查询 zołć
返回第 2 行和第 3 行,我预计不会返回任何内容。像这样的组合有很多,查询后会返回一些“错误”的行(我也尝试过使用 ą
和 ę
,它们也表现得很奇怪)。
起初我认为这是我的技术堆栈(Spring Boot之上的Java Web应用程序)的配置问题,但是当我在Windows机器上的本地数据库上从MySQL Workbench执行查询并通过执行查询时得到了完全相同的结果通过 ssh 到 Ubuntu 机器上运行的远程数据库。使用 title LIKE "value"
或使用 WHERE title = "value"
进行查询也没有区别。
我找不到对此的解释 - 请注意,这并不简单地返回“匹配”查询参数但不包含特殊字符的所有行。我正在努力启用按标题搜索,但我希望它是 1:1,因此当我在查询参数中使用“ż”时,只会返回实际存在“ż”的行。
预先感谢您的帮助。
最佳答案
您的查询将使用表/列排序规则,并且由于该排序规则将所有这些字符视为等效,因此您实际上并不需要您认为的值。您的选择是使用适当的文化设置(例如 utf8mb4_polish_ci
)或不使用(例如 utf8mb4_bin
)。选择哪个选项取决于您的用例,但两者都可能比仅使用某些任意设置更好:utf8mb4_general_ci
是一种一刀切的排序规则,旨在提高速度而不是正确性。
MySQL 允许在不同级别设置排序规则也是毫无值(value)的:
- 表格
- 列
- 特定字符串
再说一次,选择哪一个将取决于您的具体需求。这是最后一种情况的一个小例子(其他情况很简单):
SELECT
CASE WHEN 'zolc' COLLATE utf8mb4_general_ci ='zólć' THEN 'equal' ELSE 'different' END AS General,
CASE WHEN 'zolc' COLLATE utf8mb4_unicode_ci ='zólć' THEN 'equal' ELSE 'different' END AS Unicode,
CASE WHEN 'zolc' COLLATE utf8mb4_polish_ci ='zólć' THEN 'equal' ELSE 'different' END AS Polish,
CASE WHEN 'zolc' COLLATE utf8mb4_bin ='zólć' THEN 'equal' ELSE 'different' END AS BinaryCollation,
CASE WHEN BINARY 'zolc'='zólć' THEN 'equal' ELSE 'different' END AS BinaryOperator;
General | Unicode | Polish | BinaryCollation | BinaryOperator
------- | ------- | --------- | --------------- | --------------
equal | equal | different | different | different
(我假设文本是波兰语,如果不是,抱歉。)
关于当列包含 utf-8 字符时 MySQL 查询返回错误数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41245761/