当列包含utf-8字符时,MySQL查询返回错误的数据

时间:2016-12-20 15:24:32

标签: mysql sql

我有一些带有'title'列的MySQL表,其类型为varchar(255),字符集为utf8mb4,collat​​ion为utf8mb4_general_ci。

假设我的标题记录很少,而且这些标题包含(或不包含)diactrics:

id | title
-----------
1  | zolc
2  | żółć
3  | żołc
4  | zólć

我可以正确插入那些diactrics,并且在选择表格时也能正确显示它们。但是当我尝试这样的事情时:

SELECT * 
FROM my_table 
WHERE title LIKE "%zolc%";

我得到了:

id | title
-----------
1  | zolc
4  | zólć

如你所见,我要求没有任何diactricts的版本,但也获得了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,所以当我在查询参数中使用“ż”时,只会返回“ż”实际存在的行。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您的查询将使用表/列排序规则,因为排序规则会考虑所有相同的字符,因此您不会真正询问您认为的值。您的选择是使用适当的文化设置(例如utf8mb4_polish_ci)或使用无(例如utf8mb4_bin)。选择哪个选项取决于您的使用案例,但两者都可能比仅使用一些任意设置更好:utf8mb4_general_ci是一种适合速度而非正确性的一种尺寸适合所有整理。

MySQL也允许在不同级别设置整理:

  • 特定字符串

再一次,选择哪一个取决于您的具体需求。这是最后一个案例的一个小例子(其他案例很简单):

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

(我认为文字是波兰语,对不起,如果不是。)

答案 1 :(得分:0)

utf8mb4_general_ci无法实现所有Unicode排序规则,这会在某些情况下导致不合理的排序,例如使用特定语言或字符时。

尝试更改" utf8mb4_general_ci"的排序规则to" utf8_bin"。 (Reference