mysql не поддерживает все символы из диапазона U 0000..U FFFF

#mysql #unicode #utf-8

#mysql #unicode #utf-8

Вопрос:

Рассмотрим следующую таблицу:

 CREATE TABLE t1 (f1 VARCHAR(255));
  

Тогда, будь ruby :

 #!/usr/bin/env ruby
require 'json'
require 'sequel'
require 'mysql2'
DB = Sequel.connect(
    :adapter => 'mysql2',
    :database => 'd1',
    :user => '<user>',
    :password => '<password>',
    :encoding => 'utf8')
v1 = '{"a":"bud83cudf4ec"}'
v2 = JSON.parse(v1)
p v2['a']
DB[:t1].truncate
DB[:t1].insert(f1: v2['a']);
p DB[:t1].first[:f1]
  

или php :

 #!/usr/bin/env php
<?php
$dbh = new PDO('mysql:dbname=d1', '<user>', '<password>', [
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$dbh->exec('TRUNCATE TABLE t1');
$v1 = '{"a":"bud83cudf4ec"}';
$v2 = json_decode($v1);
var_dump($v2->a);
$sth = $dbh->prepare("INSERT INTO t1 VALUES (?)");
$sth->execute([$v2->a]);
$sth = $dbh->query("SELECT * FROM t1");
var_dump($sth->fetch()['f1']);
  

что попадает в базу данных, так это b . Я запускаю mysql-5.1 , и в документации говорится:

MySQL 5.1 поддерживает два набора символов для хранения данных Unicode:

  • ucs2 кодировка UCS-2 набора символов Unicode с использованием 16 бит на символ.

  • utf8 кодировка UTF-8 набора символов Unicode с использованием от одного до трех байтов на символ.

Эти два набора символов поддерживают символы из базовой многоязычной плоскости (BMP) Unicode версии 3.0. Символы BMP имеют следующие характеристики:

  • Их кодовые значения находятся в диапазоне от 0 до 65535 (или U 0000 .. U FFFF ).

Что я делаю не так?

UPD

 $ mysql -BNe 'SHOW CREATE TABLE t1' d1
t1  CREATE TABLE `t1` (n  `f1` varchar(255) DEFAULT NULLn) ENGINE=InnoDB DEFAULT CHARSET=utf8
  

Комментарии:

1. можете ли вы проверить свою таблицу COLLATION ? это должно быть utf8_unicode_ci или utf8_general_ci . При создании таблицы она использовала параметры сортировки MySQL по умолчанию, которые обычно latin1

Ответ №1:

Похоже, что эти две escape-последовательности представляют только один символ: КРАСНОЕ ЯБЛОКО (U 1F34E). Первый из них является суррогатом. И суррогаты:

UCS использует суррогаты для обращения к символам за пределами начальной базовой многоязычной плоскости, не прибегая к более чем 16-битным байтовым представлениям.

Так что, должно быть, так и есть, результирующий символ находится за пределами BMP . И не поддерживается mysql utf8 набором символов как таковым.

Ответ №2:

в моем MySQL 5.1 (из debian) выполнение

 CREATE TABLE t1 (f1 VARCHAR(255));
  

эффективно создает таблицу LATIN1 :

 mysql> show CREATE TABLE t1 ;
 ------- --------------------------------------------------------------------------------------------- 
| Table | Create Table                                                                                |
 ------- --------------------------------------------------------------------------------------------- 
| t1    | CREATE TABLE `t1` (
  `f1` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
 ------- --------------------------------------------------------------------------------------------- 
  

Поэтому, пожалуйста, сначала проверьте, действительно ли ваш MySQL по умолчанию использует UTF-8.

Известно, что MySQL НЕ может хранить все символы из таблицы BMP. Я не нахожу ссылок на это, но видел это ранее.

Настолько, что из mysql 5.5.3 появился новый набор символов с полной поддержкой utf8mb4 с поддержкой unicode в качестве statu, как указано здесь : https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-upgrading.html

Наконец, даже если BMP говорит, что они находятся между 0 и 0xFFFF, это не означает, что они используют все это пространство, как указано здесь : https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane

Комментарии:

1. Поле utf8 введено, пожалуйста, посмотрите мой обновленный ответ.

2. указаны ли ваши символы выше в используемых частях BMP? Если они являются неиспользуемыми символами или находятся за пределами BMP, MySQL будет молча игнорировать их (и остальную часть строки тоже …) см. Мои заметки по использованию MySQL-5.5 и utf8mb4