第08期:有关 MySQL 字符集的注意事项

   
一、数据库和字符集1. 建库时指定
创建数据库时 , 显式指定字符集和排序规则 , 同时 , 当切换到当前数据库后 , 参数 character_set_database , collation_database 分别被覆盖为当前显式指定的字符集和排序规则 。举个简单例子 , 创建数据库 ytt_new2 , 显式指定字符集为 latin1 , 同时排序规则为 latin1_bin 。之后在切换到数据库 ytt_new2 后 , 对应的系统参数也被修改 。
MySQL> create database ytt_new2 default character set latin1 collate latin1_bin;Query OK, 1 row affected (0.03 sec)mysql> use ytt_new2Database changedmysql> select @@character_set_database,@@collation_database;+--------------------------+----------------------+| @@character_set_database | @@collation_database |+--------------------------+----------------------+| latin1| latin1_bin|+--------------------------+----------------------+1 row in set (0.00 sec)2. 改库时指定
改库类似建库 , 效果一样 。但需要注意的一点是 , 修改库字符集与排序规则后 , 之前基于这个库创建的各种对象 , 还是沿用老的字符集与排序规则 。
举个例子 , 对存储过程的影响:
-- 简单写个存储过程DELIMITER $$USE `ytt_new2`$$DROP PROCEDURE IF EXISTS `sp_demo`$$CREATE DEFINER=`root`@`%` PROCEDURE `sp_demo`(IN f1 VARCHAR(10),IN f2 VARCHAR(10))BEGINDECLARE v1 VARCHAR(20);SET v1 = CONCAT(f1,f2);SELECT v1 AS result;END$$DELIMITER ;查看这个存储过程的字符集 , 这里看到排序规则是 latin1_bin , 对应的字符集是 latin1 , 和数据库 ytt_new2 一致 。
mysql> show create procedure sp_demoG*************************** 1. row ***************************Procedure: sp_demo...Database Collation: latin1_bin1 row in set (0.00 sec)-- 那接下来改掉数据库的字符集为 UTF8mysql> alter database ytt_new2 character set utf8 collate utf8_general_ci;Query OK, 1 row affected, 2 warning (0.02 sec)mysql> select @@character_set_database,@@collation_database;+--------------------------+----------------------+| @@character_set_database | @@collation_database |+--------------------------+----------------------+| utf8| utf8_general_ci|+--------------------------+----------------------+1 row in set (0.00 sec)-- 再查看存储过程 sp_demo 的字符集 , 还是之前的 。mysql> show create procedure sp_demoG*************************** 1. row ***************************Procedure: sp_demo...Database Collation: latin1_bin1 row in set (0.00 sec)-- 此时 , 调用存储过程 , 字符集不对 , 报编码错误 。mysql> call sp_demo('我','你');ERROR 1366 (HY000): Incorrect string value: '\xE6\x88\x91' for column 'f1' at row 1-- 改变存储过程字符集只能删除重建 , 重新执行下之前的存储过程代码 , 再次调用 , 结果就正常了 。mysql> call sp_demo('我','你');+--------+| result |+--------+| 我你|+--------+1 row in set (0.00 sec)Query OK, 0 rows affected, 2 warnings (0.01 sec)3. 参数的指定
参数 character_set_database 和 collation_database 如果没有指定 , 默认继承服务器端对应参数 character_set_server 和 collation_server 。
mysql> select @@character_set_server charset,@@collation_server collation-> union all-> select @@character_set_database,@@collation_database;+---------+--------------------+| charset | collation|+---------+--------------------+| utf8mb4 | utf8mb4_0900_ai_ci || utf8mb4 | utf8mb4_0900_ai_ci |+---------+--------------------+2 rows in set (0.00 sec)那这种情况下 , 建库或者改库时不指定具体的字符集和排序规则 , 默认继承这两个参数:
mysql> show create database ytt_new3G*************************** 1. row ***************************Database: ytt_new3Create Database: CREATE DATABASE `ytt_new3` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */1 row in set (0.00 sec)二、表和字符集1. 建表时指定(显式设置)
同建库一样 , 显式指定字符集和排序规则 , 优先级最高 , 以指定的值为准 。
-- 创建新库 ytt_new4mysql> create database ytt_new4;Query OK, 1 row affected (0.02 sec)mysql> use ytt_new4;Database changed-- 创建新表 t1, 字符集 latin1, 排序规则 latin1_binmysql> create table t1(a1 int) charset latin1 collate latin1_bin;Query OK, 0 rows affected (0.05 sec)mysql> show create table t1G*************************** 1. row ***************************Table: t1Create Table: CREATE TABLE `t1` (`a1` int DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin1 row in set (0.00 sec)


推荐阅读