PHP - 排序函数 'SORT_LOCALE_STRING' return 不正确的结果
PHP - sort function with 'SORT_LOCALE_STRING' return incorrect result
我有一些 MySQL 类型 VARCHAR 的记录,排序规则是 utf8mb4_unicode_ci:
Tiếng Việt Nam
Tiếng Hoa Kỳ
Tiếng Anh
Tiếng Nhật
Tiếng Hàn Quốc
Tiếng Thái Lan
然后,我使用 PHP 按字母顺序对它们进行排序:
$languages = [
'Tiếng Việt Nam',
'Tiếng Hoa Kỳ',
'Tiếng Anh',
'Tiếng Nhật',
'Tiếng Hàn Quốc',
'Tiếng Thái Lan',
];
setlocale(LC_COLLATE, 'vi');
sort($languages, SORT_LOCALE_STRING);
这样调用var_dump($languages)
时的结果:
array (size=6)
0 => string 'Tiếng Anh' (length=11)
1 => string 'Tiếng Hoa Kỳ' (length=16)
2 => string 'Tiếng Nhật' (length=14)
3 => string 'Tiếng Thái Lan' (length=17)
4 => string 'Tiếng Việt Nam' (length=18)
5 => string 'Tiếng Hàn Quốc' (length=22)
'Tiếng Hàn Quốc'的顺序有些不对,结果应该是这样的:
array (size=6)
0 => string 'Tiếng Anh' (length=11)
1 => string 'Tiếng Hàn Quốc' (length=19)
2 => string 'Tiếng Hoa Kỳ' (length=16)
3 => string 'Tiếng Nhật' (length=14)
4 => string 'Tiếng Thái Lan' (length=17)
5 => string 'Tiếng Việt Nam' (length=18)
然后,我通过直接输入到MySQL(使用 HeidiSQL)。终于得到了预期的结果。
我觉得这里不一样:
string 'Tiếng Hàn Quốc'(length=22)
string 'Tiếng Hàn Quốc'(length=19)
题目是:
问题的根源是什么?
如何在 MySql 或 PHP 代码中解决此问题以获得预期结果而不查找并替换 MySQL 中的所有不正确值?
谢谢。
简答:您需要此整理:utf8mb4_vietnamese_ci
。
长答案:字符串有不同的 UTF-8 十六进制表示:
Tiếng Hàn Quốc (length=20) 54 69 C3AA CC81 6E 67 48 61 CC80 6E 51 75 C3B4 CC81 63
Tiếng Hàn Quốc (length=17) 54 69 E1BABF 6E 67 48 C3A0 6E 51 75 E1BB91 63
但是,有一个潜在的问题:
C3AA 234=x00EA [ê] L LATIN SMALL LETTER E WITH CIRCUMFLEX
CC81 769=x0301 [́] NSM COMBINING ACUTE ACCENT
6E 110=x006E [n] L LATIN SMALL LETTER N
E1BABF 7871=x1EBF [ế] L LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
6E 110=x006E [n] L LATIN SMALL LETTER N
在第一个字符串中,ê 是通过单个 utf8 字符(十六进制 C3AA)呈现的,acute-n 是通过一对 utf8 字符呈现的——非间距重音符号和字母 n。
在第一个字符串中,尖音符是字母 e 的一部分。我对 utf8 中的越南语编码一无所知,但这听起来 'wrong' 如果锐音符真的应该在字母 n 上。
但是,无论如何,这两个字符串比较等于排序规则 utf8mb4_vietnamese_ci(或 utf8_vietnamese_ci)。
我有一些 MySQL 类型 VARCHAR 的记录,排序规则是 utf8mb4_unicode_ci:
Tiếng Việt Nam
Tiếng Hoa Kỳ
Tiếng Anh
Tiếng Nhật
Tiếng Hàn Quốc
Tiếng Thái Lan
然后,我使用 PHP 按字母顺序对它们进行排序:
$languages = [
'Tiếng Việt Nam',
'Tiếng Hoa Kỳ',
'Tiếng Anh',
'Tiếng Nhật',
'Tiếng Hàn Quốc',
'Tiếng Thái Lan',
];
setlocale(LC_COLLATE, 'vi');
sort($languages, SORT_LOCALE_STRING);
这样调用var_dump($languages)
时的结果:
array (size=6)
0 => string 'Tiếng Anh' (length=11)
1 => string 'Tiếng Hoa Kỳ' (length=16)
2 => string 'Tiếng Nhật' (length=14)
3 => string 'Tiếng Thái Lan' (length=17)
4 => string 'Tiếng Việt Nam' (length=18)
5 => string 'Tiếng Hàn Quốc' (length=22)
'Tiếng Hàn Quốc'的顺序有些不对,结果应该是这样的:
array (size=6)
0 => string 'Tiếng Anh' (length=11)
1 => string 'Tiếng Hàn Quốc' (length=19)
2 => string 'Tiếng Hoa Kỳ' (length=16)
3 => string 'Tiếng Nhật' (length=14)
4 => string 'Tiếng Thái Lan' (length=17)
5 => string 'Tiếng Việt Nam' (length=18)
然后,我通过直接输入到MySQL(使用 HeidiSQL)。终于得到了预期的结果。
我觉得这里不一样:
string 'Tiếng Hàn Quốc'(length=22)
string 'Tiếng Hàn Quốc'(length=19)
题目是: 问题的根源是什么? 如何在 MySql 或 PHP 代码中解决此问题以获得预期结果而不查找并替换 MySQL 中的所有不正确值?
谢谢。
简答:您需要此整理:utf8mb4_vietnamese_ci
。
长答案:字符串有不同的 UTF-8 十六进制表示:
Tiếng Hàn Quốc (length=20) 54 69 C3AA CC81 6E 67 48 61 CC80 6E 51 75 C3B4 CC81 63
Tiếng Hàn Quốc (length=17) 54 69 E1BABF 6E 67 48 C3A0 6E 51 75 E1BB91 63
但是,有一个潜在的问题:
C3AA 234=x00EA [ê] L LATIN SMALL LETTER E WITH CIRCUMFLEX
CC81 769=x0301 [́] NSM COMBINING ACUTE ACCENT
6E 110=x006E [n] L LATIN SMALL LETTER N
E1BABF 7871=x1EBF [ế] L LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
6E 110=x006E [n] L LATIN SMALL LETTER N
在第一个字符串中,ê 是通过单个 utf8 字符(十六进制 C3AA)呈现的,acute-n 是通过一对 utf8 字符呈现的——非间距重音符号和字母 n。
在第一个字符串中,尖音符是字母 e 的一部分。我对 utf8 中的越南语编码一无所知,但这听起来 'wrong' 如果锐音符真的应该在字母 n 上。
但是,无论如何,这两个字符串比较等于排序规则 utf8mb4_vietnamese_ci(或 utf8_vietnamese_ci)。