MySQL: странное поведение LENGTH() в строке utf8
Я выполняю модульные тесты на генераторах запросов, и у меня возникают проблемы с функцией LENGTH
.
У меня есть 2 запроса, которые следуют друг за другом:
SHOW VARIABLES LIKE '%character%'
Возвращает следующий результат:
array(8) {
[0] =>
array(2) {
'Variable_name' =>
string(20) "character_set_client"
'Value' =>
string(4) "utf8"
}
[1] =>
array(2) {
'Variable_name' =>
string(24) "character_set_connection"
'Value' =>
string(4) "utf8"
}
[2] =>
array(2) {
'Variable_name' =>
string(22) "character_set_database"
'Value' =>
string(6) "latin1"
}
[3] =>
array(2) {
'Variable_name' =>
string(24) "character_set_filesystem"
'Value' =>
string(6) "binary"
}
[4] =>
array(2) {
'Variable_name' =>
string(21) "character_set_results"
'Value' =>
string(4) "utf8"
}
[5] =>
array(2) {
'Variable_name' =>
string(20) "character_set_server"
'Value' =>
string(4) "utf8"
}
[6] =>
array(2) {
'Variable_name' =>
string(20) "character_set_system"
'Value' =>
string(4) "utf8"
}
[7] =>
array(2) {
'Variable_name' =>
string(18) "character_sets_dir"
'Value' =>
string(26) "/usr/share/mysql/charsets/"
}
}
Мой второй запрос:
SELECT LENGTH('重庆') as len
Он возвращает 6 вместо 2.
Что здесь не так? Мои параметры кодировки выглядят хорошо.
Ответы
Ответ 1
Я нашел ответ в документации MySQL:
Функция LENGTH
подсчитывает байты:
mysql> SELECT LENGTH('重庆') ;
+------------------+
| LENGTH('重庆') |
+------------------+
| 6 |
+------------------+
1 row in set (0.00 sec)
Функция CHAR_LENGTH
считает символы:
mysql> SELECT CHAR_LENGTH('重庆') ;
+-----------------------+
| CHAR_LENGTH('重庆') |
+-----------------------+
| 2 |
+-----------------------+
1 row in set (0.00 sec)
Ответ 2
Оба они работают совершенно по-другому:
Как только LENGTH() всегда возвращает длину строки по байтам. CHAR_LENGTH() возвращает длину строки символами.
Как только вы используете Unicode, в котором большинство символов закодированы в два байта, всегда будет отличаться. Или даже когда мы говорим о UTF-8, где количество байтов меняется все время.
например:.
SELECT LENGTH('重庆'), CHAR_LENGTH('重庆');
--> 6, 2