#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