关键字: 字符集,utf8mb4,emoj
众所周知,mysql的utf8是假的utf8,没法存emoj等字符。要设置为utf8mb4...
问题
同事给了一段Update语句,更新某张表id=xxx的某个字段;
sql
CREATE TABLE `table_name` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`xxx_id` int(11) NOT NULL,
`description` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`end_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`max_xxx` int(11) NOT NULL DEFAULT '0',
`max_xxx` int(11) NOT NULL DEFAULT '0',
`xxx_generate_method` tinyint(4) NOT NULL,
`xxx_generate_method` tinyint(4) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_table_name_xxx_id` (`xxx_id`),
KEY `idx_table_name_end_time` (`end_time`),
KEY `idx_table_name_start_time` (`start_time`)
) ENGINE=InnoDB AUTO_INCREMENT=5822 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
登陆跳板机,连接远程数据库后,执行sql,报错: ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x93\xA3Ev...'
\xF0\x9F\x93\xA3恰好是转义之后的emoj
这张表所在的库的字符集是utf8,但是表指定了是utf8mb4,字段没有指定,仅指定了排序方式为utf8mb4_unicode_ci
据说,字符集规则会按照 字段设置>表设置>库设置的顺序。
此处 这个字段没有设置字符集,那应该用表的字符集即*DEFAULT CHARSET=utf8mb4 *
(且经过试验,如果COLLATE=utf8mb4_unicode_ci,那字符集不可能是utf8,只可能是utf8mb4,不然报错时会直接报错)
下面补充一些mysql字符集的知识
查看库级别的 字符集和编码设置
sql
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
sql
Variable_name
character_set_client
character_set_connection
character_set_database
character_set_filesystem
character_set_results
character_set_server
character_set_system
character_sets_dir
这都是干啥的?
这些变量是 MySQL 中与字符集相关的变量,用于控制不同环境中的字符集设置。以下是对每个变量的简要说明:
character_set_client
: 客户端连接到 MySQL 服务器时所使用的字符集。character_set_connection
: 当前连接的默认字符集。它可以在客户端连接时通过SET NAMES
命令来设置。character_set_database
: 默认数据库的字符集。在创建数据库时设置,新创建的表将继承该字符集。character_set_filesystem
: 文件系统的默认字符集。用于存储文件名和路径的字符集。character_set_results
: 返回给客户端的结果集的字符集。character_set_server
: MySQL 服务器的默认字符集。用于新建数据库、表和列的默认字符集。character_set_system
: MySQL 系统数据字典和内部字符串的字符集。character_sets_dir
: MySQL 字符集定义文件的目录路径。
这些变量的设置是相互关联的,通过调整它们的值可以控制 MySQL 在不同环境中的字符集行为。确保这些变量的值一致并与你的应用程序和数据的字符集一致,可以确保正确地存储、传输和显示数据。
注意:在修改这些字符集相关的变量之前,请确保了解其含义和影响,并在备份数据的情况下谨慎操作。修改字符集设置可能会对现有数据和应用程序产生影响。
一般说的字符集和排序规则,应该主要看
sql
SHOW VARIABLES LIKE 'character_set_database';
SHOW VARIABLES LIKE 'collation_database';
查看表级别的字符集和编码设置
sql
SHOW CREATE TABLE `your_table_name`;
能得到建表语句,看最后的DEFAULT CHARSET
具体到table的column的字符集如何查看?
sql
SHOW FULL COLUMNS FROM your_table_name;
在查询结果中,查找 "Collation" 列。该列显示每个列(字段)的字符集和排序规则。
请注意,"Collation" 列中的值表示字符集和排序规则的组合。常见的字符集包括 UTF-8(如 utf8mb4)和 Latin1(如 latin1)。
Collation 本意是校勘,校对 之意,在数据库中 是排序规则
这个字段的第一部分,其实已经指明了字符集 ...所以SHOW FULL COLUMNS没有必要再多一个字符集列
那么,问题何在呢?
起初搜到,需要在连接时指定为utf8mb4才可以
即 mysql --default-character-set=utf8mb4 -u root -h xxx.xxx.xx.xx -p密码
但还是不行...
最后发现执行 SET NAMES utf8mb4
后再执行更新语句,成功!
根据报错信息,看起来在尝试更新xxxxx
表中的xxxxxxx
字段时遇到了错误。报错信息是ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x93\xA3Ev...' for column 'xxxxxxx' at row 1
,这表明在该字段中插入了无效的字符。
尽管您已经将该字段的字符集设置为utf8mb4
,支持存储四字节的UTF-8字符,但有可能连接或会话的字符集设置仍然不兼容。为了确保字符集一致,您可以尝试执行以下操作:
- 在更新语句之前,执行以下SQL语句设置会话字符集为
utf8mb4
:
sql
SET NAMES utf8mb4;
- 然后,再执行更新语句:
sql
UPDATE `xxxxx` SET `xxxxxxx` = '...' WHERE (`id` = 5136);
通过这样的设置,会话的字符集将与字段的字符集一致,可以正常存储包含四字节UTF-8字符的字符串。
如果问题仍然存在,请确保数据库连接和客户端工具的字符集设置与字段的字符集设置一致。另外,您还可以检查MySQL服务器的全局字符集设置,以确保它也是utf8mb4
。
SET NAMES utf8mb4什么?
"SET NAMES utf8mb4" 是一个MySQL命令,用于设置数据库连接的字符集编码为utf8mb4。在MySQL中,字符集决定了数据库如何存储和处理数据。
utf8mb4是一种字符集编码,支持Unicode字符集的全部字符,包括一些较早版本的utf8字符集无法表示的一些字符。utf8mb4编码可以处理各种语言的文字和符号,包括一些较为特殊的字符,如表情符号和特殊符号等。
通过将数据库连接的字符集编码设置为utf8mb4,可以确保数据库可以正确地存储、检索和显示各种字符,避免出现乱码或字符丢失的问题。这在处理多语言或包含特殊字符的应用程序中特别重要。
只对当前连接有效吗?
是的,"SET NAMES utf8mb4" 命令只对当前数据库连接有效。这意味着只有在执行该命令后建立的数据库连接会使用 utf8mb4 字符集编码。
如果你在程序中使用了多个数据库连接,每个连接都需要单独执行 "SET NAMES utf8mb4" 命令来设置字符集编码。
另外,如果你希望永久地将数据库的字符集编码设置为 utf8mb4,你需要修改数据库的默认字符集配置。这样,在新建的数据库连接中不需要再手动执行 "SET NAMES utf8mb4" 命令,因为连接会默认使用数据库的字符集配置。请注意,在修改数据库的默认字符集之前,请确保备份数据和相应的预防措施。
结论
可能是:数据库是utf8,即便我在连接时指定--default-character-set=utf8mb4
,依然会用utf8,必须要通过SET NAMES utf8mb4
再设置一次
为了验证,通过 mysql --default-character-set=utf8mb4 -u root -h xxx.xxx.xx.xx -p密码
连接mysql,select 刚才更新成功的那条记录,发现emoj无法正常显示; 执行SET NAMES utf8mb4
后,再select能正常看到emoj
设置mysql数据库的字符集和编码设置(谨慎操作,一般不要乱改)
要设置 MySQL 数据库的字符集和编码设置,你可以采取以下步骤:
-
登录到 MySQL 数据库服务器,可以使用以下命令: mysql -u your_username -p 替换
your_username
为你的数据库用户名。 -
在登录后,可以执行以下命令来查看当前的字符集和编码设置:
sqlSHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';
这将显示当前的字符集和编码设置。
-
若要修改数据库的字符集和编码设置,可以执行以下命令(以utf8mb4为例):
sqlALTER DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
替换
your_database_name
为你要修改的数据库名称。 -
如果需要修改特定表的字符集和编码设置,可以执行以下命令(以utf8mb4为例):
sqlALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
替换
your_table_name
为你要修改的表名称。 -
如果你希望新创建的表默认采用特定的字符集和编码,可以在创建表时指定:
sqlCREATE TABLE your_table_name ( ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
替换
your_table_name
为你要创建的表名称,并根据需要修改其他表的列和选项。 -
重启 MySQL 服务以使更改生效,具体的重启方式取决于你的操作系统和安装方式。
请注意,修改字符集和编码设置可能会影响现有数据和应用程序,因此在进行任何更改之前,请确保备份数据库并谨慎操作。
如何 修改数据库的默认字符集配置
要修改数据库的默认字符集配置,你需要执行以下步骤:
- 登录到你的MySQL数据库服务器。
- 执行以下命令来打开MySQL的配置文件(通常是my.cnf或my.ini): sudo nano /etc/mysql/my.cnf 如果你使用的是Windows系统,则路径可能是
C:\ProgramData\MySQL\MySQL Server X.X\my.ini
,其中X.X代表你的MySQL版本号。 - 在配置文件中找到
[mysqld]
部分。 - 添加或修改以下两行来设置默认字符集编码为 utf8mb4: [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci 上述配置将字符集设置为 utf8mb4,同时使用了
utf8mb4_unicode_ci
校对规则。你也可以选择其他适合你的校对规则。 - 保存并关闭配置文件。
- 重新启动MySQL服务以使配置生效,可以使用适合你的操作系统的命令,例如:
- 在Linux上使用: sudo systemctl restart mysql
- 在Windows上使用: net stop MySQL net start MySQL
- 现在,新建的数据库连接将默认使用 utf8mb4 字符集编码。
请注意,修改数据库的默认字符集可能会对现有的数据库和数据产生影响。在执行这些步骤之前,请确保备份数据并采取相应的预防措施。