mysql - 尽管排序规则为utf8mb4_unicode_ci,但SQL不会区分u和ü

标签 mysql sql utf-8 utf utf8mb4

在表x中,有一列的值为uü
SELECT * FROM x WHERE column='u'

这返回uü,尽管我只是在寻找u

该表的排序规则为utf8mb4_unicode_ci。每当我读到类似问题时,每个人都建议使用此排序规则,因为他们说utf8mb4确实涵盖了所有字符。使用此排序规则,应解决所有字符集和排序规则问题。

我可以插入üèéàChinese characters等。当我制作SELECT *时,它们也会被正确检索和显示。

仅当我比较上述示例中的两个字符串(SELECT WHERE)或在列上使用UNIQUE INDEX时,才会出现此问题。当我使用UNIQUE INDEX时,如果我已经在该列中添加了"ü",则不会插入"u"。因此,当SQL比较uü以确定ü是否唯一时,它认为ü与u相同,因此不插入ü

我将所有内容都更改为utf8mb4,因为我不再担心字符集和排序规则。但是,当谈到COMPARING字符串时,似乎utf8mb4也不是解决方案。

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

我已经与印度和中国的一些人讨论了这个问题。我们尚未找到解决方案。

如果有人能解开这个谜,那真是太好了。

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

SELECT * FROM x在哪里'ü'收集utf8mb4_bin = column
通过将“COLLATE utf8mb4_bin”添加到SELECT查询中,SQL在查看列中的字符时,将被邀请放置“二进制眼镜”(以_bin结尾)。启用二进制文件后,SQL现在会在列中看到二进制代码。而且二进制代码对于每个人可以想到的字母,字符和表情符号都是不同的。因此,SQL现在也可以看到u和ü之间的区别。因此,现在它仅在SELECT查询查找ü时才返回ü,也不会返回u。

这样,就可以使所有内容(数据库排序规则,表排序规则)保持相同,但是仅在需要精确区分时才将“COLLATE utf8mb4_bin”添加到查询中。

(实际上,SQL取消了所有其他功能(utf8mb4_german_ci,_general_ci,_unicode_ci等),并且仅在不强制执行任何其他操作时才执行它的操作。它只是查看二进制代码,而不会将搜索范围调整为任何特殊的文化背景。)

感谢大家的支持,特别是对Pred的支持。

最佳答案

排序规则和字符集是两件事。

字符集只是字符及其表示的“无序”列表。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归类的“扩展名”)

当涉及到用户交互时,二进制文件需要格外小心。由于它是CSAS,因此当他们在寻找值'foo'时习惯于获取值'Foo'的用户会感到困惑。同样作为开发人员,在加入联接和其他功能时,您必须格外谨慎。 INNER JOIN'foo'='Foo'将不返回任何内容,因为'foo'不等于'Foo'。

我希望这些示例和解释能有所帮助。

关于mysql - 尽管排序规则为utf8mb4_unicode_ci,但SQL不会区分u和ü,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41102371/

相关文章:

python - 更正 python 代码以将 NULL 值插入 MySQL

mysql - SQL更新语句

sql - 从 SQL Server 中的子查询值或其他聚合函数获取平均值

c++ - 在 Windows C++ 应用程序中验证输入的 UTF-8 序列

c++ - 在 C++ 中获取正确编码的字符串

php - 无法通过 PDO_ODBC 从 Access 检索 UTF-8 重音字符

mysql - MySQL 中的 REPLACE 不区分大小写?

c# - Entity Framework 和 MySQL 的随机顺序

php - fatal error : Call to a member function num_rows() on a non-object in/home/*/public_html/application/core/MY_Controller. php 第 137 行

mysql - 如何创建MySQL分层递归查询