【问题标题】:mysql doesn't support all symbols from range U+0000..U+FFFFmysql 不支持 U+0000..U+FFFF 范围内的所有符号
【发布时间】:2014-06-27 14:12:17
【问题描述】:

考虑下表:

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":"b\ud83c\udf4ec"}'
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":"b\ud83c\udf4ec"}';
$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 和文档says

MySQL 5.1 支持两种字符集来存储 Unicode 数据:

  • ucs2,Unicode 字符集的 UCS-2 编码,每个字符使用 16 位。

  • utf8,Unicode 字符集的 UTF-8 编码,每个字符使用一到三个字节。

这两个字符集支持来自 Unicode 3.0 版基本多语言平面 (BMP) 的字符。 BMP 字符具有以下特点:

  • 它们的代码值介于 0 和 65535(或 U+0000 .. U+FFFF)之间。

我做错了什么?

UPD

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

【问题讨论】:

  • 你能检查一下你的桌子COLLATION吗?它应该是utf8_unicode_ciutf8_general_ci。当您创建表时,它使用 MySQL 默认排序规则,通常是 latin1

标签: mysql unicode utf-8


【解决方案1】:

这两个转义序列似乎只代表一个字符:RED APPLE (U+1F34E)。第一个是代理。还有surrogates are

UCS 使用代理来处理初始基本多语言平面之外的字符,而不使用超过 16 位字节的表示。

所以一定是这样,结果字符在BMP 之外。并且不受 mysqlutf8 字符集支持。

【讨论】:

    【解决方案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 支持字符集作为状态如下所述:https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-upgrading.html

    最后,即使 BMP 它们在 0 和 0xFFFF 之间,这并不意味着它们正在使用 all 这个空间,如下所述:https://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane

    【讨论】:

    • 该字段在utf8,请查看我的更新答案。
    • 你的字符是否在BMP的使用部分?如果它们是未使用的字符或在 BMP 之外,MySQL 将默默地忽略它们(以及字符串的其余部分......)请参阅我关于使用 MySQL-5.5 和 utf8mb4 的说明
    猜你喜欢
    • 2018-02-20
    • 1970-01-01
    • 2018-10-18
    • 2019-02-16
    • 1970-01-01
    • 2012-10-28
    • 2017-10-20
    • 1970-01-01
    • 2018-11-03
    相关资源
    最近更新 更多