虽然排序规则是utf8mb4_unicode_ci,但SQL并没有区分你和ü

Jak*_*kob 8 mysql sql utf-8 utf utf8mb4

在表格中x,有一列包含值uü.

SELECT * FROM x WHERE column='u'.

这会返回uAND ü,虽然我只是在寻找u.

表的整理是utf8mb4_unicode_ci.无论我在哪里阅读类似的问题,每个人都建议使用这种整理,因为他们说这utf8mb4真的涵盖了所有字符.通过这种整理,应该解决所有字符集和整理问题.

我可以插入ü,è,é,à,Chinese characters,等等.当我做SELECT *,他们也检索和正确显示.

只有当我按照上面的例子(SELECT WHERE)或者在UNIQUE INDEX列上使用a 来比较两个字符串时,才会出现此问题.当我使用时UNIQUE INDEX,"ü"当我已经"u"在列中时,没有插入a .因此,当SQL进行比较u并且ü为了确定ü是否是唯一的时,它认为它是相同的u并且不插入ü.

我改变了一切,utf8mb4因为我不想再担心字符集和整理了.但是,utf8mb4当涉及到比较字符串时,它似乎不是解决方案.

我也试过这个: SELECT * FROM x WHERE _utf8mb4 'ü' COLLATE utf8mb4_unicode_ci = column.
此代码是可执行的(看起来非常复杂).但是,它也会返回üAND u.

我已经和印度的一些人和中国的人谈过这个问题.我们还没有找到解决方案.

如果有人能解开这个谜团,那真的很棒.

Add_On:阅读下面的所有答案和评论后,这里有一个代码示例解决了这个问题:

SELECT*FROM xWHERE 'U' COLLATE utf8mb4_bin =column

通过在SELECT查询中添加"COLLATE utf8mb4_bin",SQL会在查看列中的字符时将"二进制眼镜"(结束_bin)置于其上.在打开二进制眼镜的情况下,SQL现在可以看到列中的二进制代码.并且二进制代码对于每个可以想到的字母和字符以及表情符号都是不同的.所以,SQL现在也可以看到u和ü之间的区别.因此,现在它只在SELECT查询查找ü时返回ü,并且不返回u.

通过这种方式,可以保留所有内容(数据库排序规则,表格排序规则)相同,但只在需要精确区分时才将"COLLATE utf8mb4_bin"添加到查询中.

(实际上,SQL会关闭所有其他眼镜(utf8mb4_german_ci,_general_ci,_unicode_ci等),并且只会在不强制执行任何其他操作时执行它的操作.它只是查看二进制代码并且不会将其搜索调整为任何特殊的文化背景.)

感谢大家的支持,尤其是对Pred的支持.

Pre*_*red 8

整理和字符集是两个不同的东西.

字符集只是一个"无序"字符列表及其表示. utf8mb4是一个字符集,涵盖了很多字符.

排序规则定义字符的顺序(例如,确定顺序的最终结果)并定义其他规则(例如应将哪些字符或字符组合视为相同).排序是从字符集派生的,对于同一字符集可以有多个排序规则.(它是字符集的扩展 - sorta)

utf8mb4_unicode_ci所有(大多数?)重音字符被视为相同的字符,这就是为什么你得到uü.简而言之,这种整理是一种强调不敏感的整理.

这类似于德国校对对待ssß同样的事实.

utf8mb4_bin是另一种排序规则,它将所有字符视为不同的字符.您可能希望也可能不希望将其用作默认设置,这取决于您和您的业务规则.

您还可以在查询中转换排序规则,但请注意,这样做会阻止MySQL使用索引.

这是一个使用相似但可能更熟悉的排序规则部分的示例:

所述ci在排序规则的装置端Case Insensitive,几乎所有的归类与ci具有一对与结束cs,意义Case Sensitive.

当你的列不区分大小写时,where条件column = 'foo'会找到所有这些:foo Foo FOo FoO FOo FoO fOO,FOO.

现在,如果您尝试将排序规则设置为区分大小写(utf8mb4_unicode_cs例如),则所有上述值都将被视为不同的值.

本地化的排序规则(如德语,英国,美国,匈牙利语等)遵循命名语言的规则.在德国ss并且ß是相同的,这在德语规则中有说明.当德国用户搜索的值Straße,他们会期望一个软件(支持德语或写入德国)将同时返回StraßeStrasse.

更进一步,当涉及到排序时,两个词是相同的,它们是相同的,它们的意思是相同的,所以没有特定的顺序.

不要忘记,UNIQUE约束只是排序/过滤值的一种方式.所以,如果有与德国排序列定义的唯一钥匙,它不会允许同时插入StraßeStrasse,由于语言的规则,他们应该被平等对待.

现在让我们看看我们的原始排序规则:utf8mb4_unicode_ci,这是一个'通用'排序规则,这意味着它会尝试简化所有内容,因为ü它不是一个非常常见的字符,并且大多数用户不知道如何输入它,这种排序规则使其相同到u.这是为了支持大多数语言的简化,但正如您所知,这些简化会产生一些副作用.(如在排序,过滤,使用唯一约束等).

utf8mb4_bin是频谱的另一端.这种整理设计尽可能严格.为此,它实际上使用字符代码来区分字符.这意味着,角色的每种形式都是不同的,这种整理是隐含的区分大小写和区分重音.

这两者都有缺点:本地化和通用排序规则是针对一种特定语言设计的,或者是提供一种通用解决方案.(utf8mb4_unicode_ci是旧utf8_general_ci排序规则的'扩展' )

二进制文件在用户交互方面需要格外小心.既然它是CS,AS它可以混淆用户在寻找值'foo'时获得值'Foo'的用户.此外,作为开发人员,在连接和其他功能方面,您必须格外小心.INNER JOIN'foo'='Foo'将不返回任何内容,因为'foo'不等于'Foo'.

我希望这些例子和解释有所帮助.


小智 0

您可以尝试 utf8_bin 排序规则,您不应该遇到此问题,但它会区分大小写。bin 排序规则进行严格比较,仅根据所选编码将字符分开,完成后,比较将在二进制基础上完成,就像许多编程语言比较字符串一样。