为啥 MySQL 将 é 视为与 e 相同?

Posted

技术标签:

【中文标题】为啥 MySQL 将 é 视为与 e 相同?【英文标题】:Why is MySQL treating é the same as e?为什么 MySQL 将 é 视为与 e 相同? 【发布时间】:2011-10-18 16:38:28 【问题描述】:

我正在使用 Django Web 应用程序将 Unicode 字符串存储在 mysql 数据库中。我可以很好地存储 Unicode 数据,但是在查询时,我发现 ée 被视为同一个字符:

In [1]: User.objects.filter(last_name='Jildén')
Out[1]: [<User: Anders Jildén>]

In [2]: User.objects.filter(last_name='Jilden')
Out[2]: [<User: Anders Jildén>]

直接使用MySQL shell时也是这样:

mysql> select last_name from auth_user where last_name = 'Jildén';
+-----------+
| last_name |
+-----------+
| Jildén   |
+-----------+
1 row in set (0.00 sec)

mysql> select last_name from auth_user where last_name = 'Jilden';
+-----------+
| last_name |
+-----------+
| Jildén   |
+-----------+
1 row in set (0.01 sec)

这里是数据库字符集设置:

mysql> SHOW variables LIKE '%character_set%';
+--------------------------+------------------------------------------------------+
| Variable_name            | Value                                                |
+--------------------------+------------------------------------------------------+
| character_set_client     | latin1                                               |
| character_set_connection | latin1                                               |
| character_set_database   | utf8                                                 |
| character_set_filesystem | binary                                               |
| character_set_results    | latin1                                               |
| character_set_server     | latin1                                               |
| character_set_system     | utf8                                                 |
| character_sets_dir       | /usr/local/Cellar/mysql/5.1.54/share/mysql/charsets/ |
+--------------------------+------------------------------------------------------+

这是表架构:

CREATE TABLE `auth_user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(30) CHARACTER SET utf8 NOT NULL,
    `first_name` varchar(30) CHARACTER SET utf8 NOT NULL,
    `last_name` varchar(30) CHARACTER SET utf8 NOT NULL,
    `email` varchar(200) CHARACTER SET utf8 NOT NULL,
    `password` varchar(128) CHARACTER SET utf8 NOT NULL,
    `is_staff` tinyint(1) NOT NULL,
    `is_active` tinyint(1) NOT NULL,
    `is_superuser` tinyint(1) NOT NULL,
    `last_login` datetime NOT NULL,
    `date_joined` datetime NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=7952 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

这是我通过 Django 的 DATABASES 设置传递的选项:

DATABASES = 
    'default': 
        # ...
        'OPTIONS': 
            'charset': 'utf8',
            'init_command': 'SET storage_engine=INNODB;',
        ,
    ,

请注意,我已尝试将表排序规则设置为utf8_bin,但没有任何效果:

mysql> alter table auth_user collate utf8_bin;

mysql> select last_name from auth_user where last_name = 'Jilden';
+-----------+
| last_name |
+-----------+
| Jildén   |
+-----------+
1 row in set (0.00 sec)

如何让 MySQL 将它们视为不同的字符?

【问题讨论】:

请发布SHOW CREATE TABLE tablename的输出,其中tablename是包含相关列的表的名称。 我已编辑问题以包含表架构。谢谢。 【参考方案1】:

当您更改表格排序规则时,您已经快到了,但并不完全。在 MySQL 中,表中的每一列都有自己的字符集和排序规则。该表有自己的字符集和排序规则,但这不会覆盖列排序规则;它仅确定您未指定排序规则的新列的排序规则。所以您没有更改您感兴趣的列的排序规则。

ALTER TABLE tablename MODIFY columnname
    varchar(???) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL

【讨论】:

【参考方案2】:

您需要设置一个将变音符号视为重要的排序规则。尝试使用utf8_bin

【讨论】:

我尝试将表排序规则设置为utf8_bin,但这似乎没有帮助。除了ALTER TABLE auth_user COLLATE utf8_bin,我还需要做些什么吗? @claymation: ALTER TABLE … COLLATE 实际上是 ALTER TABLE … DEFAULT COLLATE 只会影响新添加的列。你需要运行ALTER TABLE auth_user CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin【参考方案3】:

我认为了解表的字符集和您要查询的字段非常重要。

您的问题的答案可以在这里找到http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

您查询的字段可能具有 utf8_general_ci 字符集。 要获得您想要的内容,您应该将该字段的字符集设置为 utf8_unicode_ci

请记住,正如手册所述,对 utf8_unicode_ci 字符集字段的查询比对 utf8_general_ci 字段的查询慢

【讨论】:

以上是关于为啥 MySQL 将 é 视为与 e 相同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 SQL Server 2000 将 SELECT test.* 和 SELECT t.est.* 视为相同?

为啥具有相同名称但不同签名的多个继承函数不会被视为重载函数?

为啥在构造函数内部声明和初始化的变量已经在外部以相同的名称声明时被视为不同的变量?

字符串格式-方法

可以将派生类对象视为与基类相同类型吗? <noobieQ/>

MySQL中的UTF8字符串比较