如何在 MySQL 中控制 UTF-8 排序?
Posted
技术标签:
【中文标题】如何在 MySQL 中控制 UTF-8 排序?【英文标题】:How can I control UTF-8 ordering in MySQL? 【发布时间】:2012-05-13 21:03:42 【问题描述】:例如,这是标准“按名称排序”查询返回的顺序:
name
------
Cebbb
Čebbc
Cebbd
我想按名称排序并得到重音字符first,与其他重音字符分组,例如
name
------
Čebbc
Cebbb
Cebbd
默认情况下,mysql 将Č
视为C
,以进行排序,并按显示的顺序进行排序。
或者,在 php 中是否有一种方法可以将Č
“转换”为C
,以便进行比较?
【问题讨论】:
【参考方案1】:你可以add a COLLATE
expression to your ORDER BY
clause:
SELECT k
FROM t1
ORDER BY k COLLATE utf8_spanish_ci;
然后,将使用正确的排序规则对列进行排序,并且列定义可以保持不变。
【讨论】:
我认为最初的问题令人困惑;我已经更新澄清。 Yogu 的解决方案似乎可以回答您的问题。使用正确的排序规则,SQL 将按照该语言的正确顺序对字符进行排序。【参考方案2】:最简单的方法是对列本身应用适当的排序规则,例如:
CREATE TABLE foo (
foo_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL COLLATE 'utf8_spanish_ci',
PRIMARY KEY (`foo_id`)
)
COLLATE='utf8_spanish_ci'
ENGINE=InnoDB;
更新:
Č 不是西班牙字母:
在克罗地亚语、斯洛文尼亚语、波斯尼亚语、Skolt Sami 和 Lakota 字母表中,它 是字母表中的第四个字母。在捷克语、北萨米语字母表中 和波罗的海语言立陶宛语和拉脱维亚语,这封信是 第五名。在斯洛伐克语中,它是字母表中的第六个字母。也是 用于普什图语(相当于 چ)和 Saanich。
与数字不同,字母没有固定的绝对顺序。字母顺序的整个概念是相对的——你必须首先选择一个规则集。运行此 SQL 查询以了解您的 MySQL 服务器中有哪些可用:
SHOW CHARACTER SET
...并选择更符合您期望的那个。手册中有brief description。
【讨论】:
当您说“正确”时,是否包括 utf8_general_ci?这就是表和列已经指定的内容,并且更改它不会非常容易,因为数据库不是“我的”(它是 joomla 提供的) “正确”取决于语言。排序文本时有不同的规则。如果utf8_spanish_ci
是您当前的排序规则,那么您的确切问题是什么?你不想要现代西班牙规则,或者你没有得到它们?
啊——我明白了。你是说Č是西班牙文吗?在这种情况下,它实际上不是(或没有在西班牙语中使用),但是 - 我希望 - 这不相关。将会有来自多种语言的一大堆字符。如果尝试将 Č 视为 C 是荒谬的,那么我很高兴 not 这样做,但这又回到了 MySQL 将它们视为平等的原始问题。跨度>
@BobbyJack 然后使用utf8_bin
。它通过 Unicode 代码点比较字符,这意味着没有重音或大小写折叠。【参考方案3】:
要将带有重音或变音符号的特殊字符替换为普通的拉丁字符,可以使用php函数iconv
:
iconv("UTF-8", "ASCII//TRANSLIT", $text)
这会将变量$text
转换为纯ASCII 字符。例如,müßig 会被转换成 muessig,而 caffée 会被转换成 caffee。
【讨论】:
虽然我不知道 alternative 解决方案与您的主要问题有什么关系 另一种解决方案允许我在 PHP 中将这两个字符视为相同,从而使我能够将它们分组到一个公共标题下。我从数据库中获取行,然后在初始字符更改时输出“标题” - 就像书中的索引列表一样。目前,我得到一个“C”名称列表,后跟一个“Č”名称,然后是另一个“C”名称列表。 嗯,好吧,那么 php 解决方案似乎更好,因为您肯定不希望每个特殊字符都有一个部分。 这绝对是最接近的解决方案。由于本地环境问题(即 iconv 和 MAMP 的问题),我实际上无法立即使用此解决方案,但 iconv() 绝对解决了比较问题。 MySql SORT BY 修复会更好,但与此同时我会投票给你。 特殊字符是例外,因此每个特殊字符的部分实际上是可以的。【参考方案4】:好的,这是我的解决方案,诚然,这是一个非常特殊的情况:
ORDER BY SUBSTRING(name, 1, 1),
BINARY SUBSTRING(name, 1, 1),
name
这当然不是最有效的查询——不过,在这种情况下,这并不是什么大问题——但它确实通过以下方式解决了我的问题:
-
按初始字符排序(MySql 会将
Č
和C
视为相同)
然后 按初始字符的二进制值排序,这将区分Č
和C
然后按全名排序,这实际上将按字符串的其余部分排序。
这将在第一个字符之后进行非最佳排序,但这不是问题。
【讨论】:
以上是关于如何在 MySQL 中控制 UTF-8 排序?的主要内容,如果未能解决你的问题,请参考以下文章
如何将整个 MySQL 数据库字符集和排序规则转换为 UTF-8?