如何让 MySQL 正确处理 UTF-8

Posted

技术标签:

【中文标题】如何让 MySQL 正确处理 UTF-8【英文标题】:How to make MySQL handle UTF-8 properly 【发布时间】:2010-09-17 03:54:13 【问题描述】:

对a question I asked yesterday 的回复之一建议我应该确保我的数据库能够正确处理 UTF-8 字符。我如何使用 mysql 做到这一点?

【问题讨论】:

真心希望我们能得到一个全面的答复,涵盖各种MySQL版本、不兼容等问题。 另见***.com/questions/2344118/utf-8-general-bin-unicode @EdwardZ.Yang -- MySQL 4.1 引入CHARACTER SETs; 5.1.24 弄乱了德语 Sharp-s (ß) 的排序规则,通过在 5.1.62 中添加另一个排序规则进行了纠正(可以说让事情变得更糟); 5.5.3 用新的charset utf8mb4 填写utf8。 这个问题和这个完全一样。请看***.com/questions/3513773/… 值得指出的是,这些答案中的大多数都是完全错误的。不要使用utf8。它只支持最多 3 个字节的字符。您应该在 MySQL 中使用的正确字符集是 utf8mb4 【参考方案1】:

更新:

简答 - 您应该几乎总是使用 utf8mb4 字符集和 utf8mb4_unicode_ci 排序规则。

修改数据库:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

见:

Aaron 对此答案的评论How to make MySQL handle UTF-8 properly

What's the difference between utf8_general_ci and utf8_unicode_ci

转换指南:https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-conversion.html

原答案:

MySQL 4.1 及更高版本的默认字符集为 UTF-8。您可以在您的my.cnf 文件中验证这一点,记得设置两个 客户端和服务器(default-character-setcharacter-set-server)。

如果您有想要转换为 UTF-8 的现有数据,请转储您的数据库,然后将其导入为 UTF-8,确保:

在查询/插入数据库之前使用SET NAMES utf8 创建新表时使用DEFAULT CHARSET=utf8 此时,您的 MySQL 客户端和服务器应该是 UTF-8(请参阅my.cnf)。请记住,您使用的任何语言(例如 php)也必须是 UTF-8。某些版本的 PHP 将使用自己的 MySQL 客户端库,该库可能不支持 UTF-8。

如果您确实要迁移现有数据,请记得先备份!当事情没有按计划进行时,可能会发生大量奇怪的数据截断!

一些资源:

complete UTF-8 migration (cdbaby.com) UTF-8 readiness of php functions 上的文章(请注意其中一些信息已过时)

【讨论】:

我的理解是 MySQL 中的 utf8 仅指完整 Unicode 的一小部分。你应该使用utf8mb4 来强制支持。请参阅mathiasbynens.be/notes/mysql-utf8mb4“很长一段时间以来,我一直在使用 MySQL 的 utf8 字符集来处理数据库、表和列,假设它映射到上述 UTF-8 编码。” MySQL 从来没有默认的 UTF-8 字符集。 4.1 和 5.x 到最新的 5.7 都使用 latin1latin1_swedish_ci 作为默认字符集和排序规则。请参阅 MySQL 手册中的“服务器字符集和排序规则”页面进行确认:dev.mysql.com/doc/refman/5.1/en/charset-server.html @TimTisdall 当大多数文本是 ASCII 时,您不必担心 utf8mb4 会占用额外的存储空间。尽管char 字符串是预先分配的,varchar 字符串不是——请参阅this documentation page 的最后几行。例如,char(10) 将悲观地在 utf8mb4 下保留 40 个字节,但varchar(10) 将分配与可变长度编码保持一致的字节。 @Kevin 我想你误读了。我认为最大行长是 64k。您只能将 utf8mb4 字段设为其中的 1/4,因为它必须保留该空间量。所以,即使是 ASCII 也只能插入 16k 个字符。 @TimTisdall 哦,你说的是上限。是的,这些更低。幸运的是,如果您尝试将varchar(n) 字段更改为大于可行字节大小(同时发出警告),当前版本的mysql 将自动从varchar(n) 升级到text 数据类型。索引也会有一个最坏情况下的上限,这可能会带来其他问题。【参考方案2】:

SET NAMES UTF8

这就是诀窍

【讨论】:

虽然使用SET NAMES UTF8(或UTF8mb4)是正确的,但您没有解释它的作用(用于此连接的字符集)。 “这可以解决问题”听起来可以解决问题(使 MySQL 正确处理 UTF-8),但许多 MySQL 数据库默认设置为 latin1,因此不会使其成为正确的解决方案。我会将change the default charset 和表格字符集设置为utf8mb4。真的,这个答案相当不完整,所以我投了反对票。【参考方案3】:

为了使这个“永久”,在my.cnf

[client]
default-character-set=utf8
[mysqld]
character-set-server = utf8

要检查,请转到客户端并显示一些变量:

SHOW VARIABLES LIKE 'character_set%';

验证它们都是utf8,除了..._filesystem,应该是binary..._dir,它们指向MySQL 安装中的某个位置。

【讨论】:

它在我的情况下不起作用,但我在 /etc 中创建了带有给定内容的文件 my.cf。我用create table my_name(field_name varchar(25) character set utf8); “显示变量,如 'character_set%';”命令向我揭示了我的连接问题。谢谢! 这是不正确的。 MySQL 所称的 utf8 不是“完整”的 UTF-8。 set character_set_client=utf8; 设置新值【参考方案4】:

字符集是数据库(默认)和表的属性。 你可以看看(MySQL命令):

show create database foo; 
> CREATE DATABASE  `foo`.`foo` /*!40100 DEFAULT CHARACTER SET latin1 */

show create table foo.bar;
> lots of stuff ending with
> ) ENGINE=InnoDB AUTO_INCREMENT=252 DEFAULT CHARSET=latin1

换句话说;检查或更改数据库字符集非常容易:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;

【讨论】:

这是不正确的。 MySQL 所称的 utf8 不是“完整”的 UTF-8。【参考方案5】:

我遵循了 Javier 的解决方案,但我在 my.cnf 中添加了一些不同的行:

[myslqd]
skip-character-set-client-handshake
collation_server=utf8_unicode_ci
character_set_server=utf8 

我在这里找到了这个想法:http://dev.mysql.com/doc/refman/5.0/en/charset-server.html 在页面底部的第一个/唯一用户评论中。他提到 skip-character-set-client-handshake 有一定的重要性。

【讨论】:

这个不受欢迎的零投票答案是唯一对我有帮助的东西!所以它得到了我的投票,这是肯定的。 skip-character-set-client-handshake 是关键。【参考方案6】:

将您的数据库连接设置为 UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS))          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  

【讨论】:

如果运行 PHP,请不要使用已弃用的 mysql_* 接口。切换到mysqli_*PDO【参考方案7】:

MySQL 4.1 及更高版本有一个默认字符集,它调用utf8,但它实际上只是 UTF-8 的一个子集(只允许三字节或更小的字符)。

如果您想要“完整”的 UTF-8,请使用 utf8mb4 作为您的字符集。

【讨论】:

绝对同意,这是唯一正确的答案。 utf8 不包括表情符号等字符。 utf8mb4 确实如此。检查此以获取有关如何更新的更多信息:mathiasbynens.be/notes/mysql-utf8mb4 @Basti -- 大部分正确(直到最近,latin1 还是默认设置),但不完整(未讨论正确插入/选择 utf8 编码的数据,也未在 html 中显示)。 尊敬的,@RickJames,Basti 说“到目前为止”——我不记得我发布此消息时看到你的答案。 唉,utf8 问题有大约 5 种明显不同的症状,程序员做错了导致麻烦的事情大约有 4 种。大多数答案只指出一个 可能需要修复的事情。最初的问题是一个宽泛的问题,所以答案需要全部 4 个。也许 Basti 熟悉 一个 症状,而您的一个方面就是解决方案。 顺便说一句,我想暂停一下,给 MySQL 团队一个非常好的、严厉的凝视。 o_o WTF 你们在想什么?您是否意识到通过在您的程序中创建一个名为“utf8”但实际上不是 UTF-8 的代码页造成了多少混乱?该死的混蛋。 【参考方案8】:

能够找到解决方案。按照http://technoguider.com/2015/05/utf8-set-up-in-mysql/的规定运行以下内容@

SET NAMES UTF8;
set collation_server = utf8_general_ci;
set default-character-set = utf8;
set init_connect = ’SET NAMES utf8′;
set character_set_server = utf8;
set character_set_client = utf8;

【讨论】:

最后两行是多余的,因为第一行已经包含:dev.mysql.com/doc/refman/5.0/en/charset-connection.html 也不是一个完整的解决方案。列需要CHARACTER SET utf8root 不会执行最重要的init_connect【参考方案9】:

简短的回答:在 4 个地方使用utf8mb4

您客户端中的字节是 utf8,而不是 latin1/cp1251/等。 SET NAMES utf8mb4 或建立客户端与 MySQL 的连接时的等效项 CHARACTER SET utf8mb4 在所有表/列上 - 除了严格为 ascii/hex/country_code/zip_code/etc 的列。 <meta charset charset=UTF-8> 如果您要输出到 HTML。 (是的,这里的拼写不同。)

More info ;UTF8 all the way

以上链接提供了“解决所有问题需要详细的规范答案”。 -- 本论坛有空间限制。

编辑

除了包含“所有”世界字符的CHARACTER SET utf8mb4 之外,COLLATION utf8mb4_unicode_520_ci 可以说是使用的“最佳全能”排序规则。 (对于那些想要了解这些语言的细微差别的人来说,还有土耳其语、西班牙语等排序规则。)

【讨论】:

我的new link 关于如何从你得到的输出中调试 utf8 问题。 为什么 unicode_520_ci 不是最好的:***.com/a/49982378/62202 @Louis - 正如我所暗示的那样,西班牙语和土耳其语(以及波兰语)用户可能不高兴。 “最好的全能”往往会伤害每个人。 MySQL 8.0 有一个更新的“最佳”排序规则:utf8mb4_0900_ai_ci。唉,又是 L=Ł。【参考方案10】:

您的答案是您可以通过 MySql 设置进行配置。在我的回答中可能有些断章取义,但这也知道对您有帮助。如何配置 Character SetCollation

对于使用默认 MySQL 字符集存储数据的应用程序 和排序规则(latin1, latin1_swedish_ci),无特殊配置 应该是需要的。如果应用程序需要使用 不同的字符集或排序规则,可以配置字符集 信息几种方式:

指定每个数据库的字符设置。 例如,应用程序 使用一个数据库的应用程序可能需要utf8,而使用一个数据库的应用程序可能需要utf8 使用其他数据库可能需要 sjis。 在服务器启动时指定字符设置。 这会导致服务器 将给定的设置用于所有不做其他应用的应用程序 安排。 在配置时指定字符设置,如果你构建 MySQL 从源头。这会导致服务器对所有用户使用给定的设置 应用程序,而无需在服务器启动时指定它们。

此处显示的示例为您的问题设置 utf8 字符集,此处还设置排序规则以获得更多帮助(utf8_general_ci collat​​ion`)。

指定每个数据库的字符设置

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

在服务器启动时指定字符设置

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

在 MySQL 配置时指定字符设置

shell> cmake . -DDEFAULT_CHARSET=utf8 \
           -DDEFAULT_COLLATION=utf8_general_ci

要查看适用于您的连接的字符集和排序规则系统变量的值,请使用以下语句:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

这可能是一个冗长的答案,但有办法,你可以使用。希望我的回答对你有所帮助。更多信息http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html

【讨论】:

【参考方案11】:

要将数据库本身的字符集编码更改为 UTF-8,请在 mysql> 提示符下键入以下命令。 USE ALTER DATABASE.. 将 DBNAME 替换为数据库名称:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

这是这个问题的重复How to convert an entire MySQL database characterset and collation to UTF-8?

【讨论】:

【参考方案12】:

将您的 database collation 设置为 UTF-8 然后将table collation 应用到数据库默认值。

【讨论】:

【参考方案13】:

到 UTF-8 的数据库连接

$connect = mysql_connect('$localhost','$username','$password') or die(mysql_error());
mysql_set_charset('utf8',$connect);
mysql_select_db('$database_name','$connect') or die(mysql_error());

【讨论】:

【参考方案14】:

这对我有用:

mysqli_query($connection, "SET NAMES 'utf8'");

【讨论】:

许多其他答案已经提出了这个解决方案。请确保您在回答旧问题时做出了独特的贡献。

以上是关于如何让 MySQL 正确处理 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

如何在 phpMyAdmin 中显示 UTF-8 字符?

如何使用 PHP&MySQL 正确处理 n:m 关系?

如何正确处理 PHP / MySQL / Apache 中的国际字符

PHP 脚本未正确从 MySQL 数据生成 KML 文件 - 如何正确处理此问题?

如何正确处理信号,让 gperftools CPU profiler 仍然有效?

如何让 Vue (vue cli 3) 正确处理 GraphQL 文件?