我有一些带有'title'列的MySQL表,其类型为varchar(255)
,字符集为utf8mb4,collation为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,所以当我在查询参数中使用“ż”时,只会返回“ż”实际存在的行。
提前感谢您的帮助。
答案 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)