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.

Что здесь не так? Мои параметры кодировки выглядят хорошо.


person Alain Tiemblo    schedule 29.04.2013    source источник


Ответы (2)


Я нашел свой ответ в документации 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)
person Alain Tiemblo    schedule 29.04.2013
comment
В частности, LENGTH() возвращает длину своего аргумента в байтах, тогда как CHAR_LENGTH() возвращает длину своего аргумента в символах. - person eggyal; 29.04.2013

Они оба работают совершенно по-разному:

После того, как LENGTH() всегда возвращает длину строки в байтах. CHAR_LENGTH() возвращает длину строки по символам.

Когда вы используете Юникод, в котором большинство символов закодировано двумя байтами, он всегда будет другим. Или даже когда речь идет о UTF-8, где количество байт все время меняется.

e.g.:

SELECT LENGTH('重庆'), CHAR_LENGTH('重庆');
-->   6,  2  
person medina    schedule 29.04.2013
comment
ваш комментарий неверен, Юникод не кодирует в два байта, потому что это просто не кодировка. Возможно, вы говорите о UTF-16. Юникод - это только спецификация кодовых точек. - person Johnny; 24.09.2017