背景
在一次上线时,将建表语句发给了领导,领导对我的语句进行了一些修改,让我测试一下给他发个最终版上线,对比发现领导主要对我的语句做了以下修改:
- insert 时的语句创建时间和修改时间去掉了(并告诉我如果能确定自增id没有依赖,也应该去掉自增id)
- 自增id中的长度去掉了(例如:id int(11)改成了id int,并且说对于int类型来说长度用缺省值就好)
- 创建表时的设置字符集去掉了我的utf8mb4(用默认的)。
用新语句执行
将领导给的建表语句执行完之后,what??一脸懵逼,中文为什么变成乱码了,首先查询系统编码
show variables like 'character%';
这几个变量的默认值一般都是latin1,解释一下这几个变量的意思
- character_set_client、character_set_connection、character_set_results 这三个变量是指客户端连接的字符集,我们在终端set names utf8mb4。这样设置其实就是设置来这三个变量的值为utf8mb4编码。
- character_set_database 这个指的是数据库的字符集。CREATE DATABASE kenny CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 这里的character set utf8mb4 就会把变量character_set_database设置为utf8mb4。
- character_set_system 这个是指数据库服务的字符集。修改他的方式一般有两种,1.修改my.cnf
[mysqld]
character-set-server = utf8mb4
2.在终端直接set character_set_server=utf8mb4。第二种在服务重启之后就会消失。
解决乱码问题
其实我们在数据库中看到乱码问题根本原因就是写入时的编码和查询时的编码不一致导致的,其实只要我们将查时和数据库写入时的编码设置成一样的就ok。我们查询的编码默认都是utf8,而数据库写入时的编码默认是latin1,一般我们是将数据库写入时的编码改为utf8(当然你也可以将查询的设置为latin1,这就意味你每个查询的地方都要设置为latin1,所以一般不采用这种方式),数据库写入时的编码最终是可以由好几个地方控制,但是他们是有优先级的。优先级从高到低为
字段字符集>表字符集>数据库字符集(character_set_database)>服务字符集(character_set_server)
这里的character_set_database就是指数据库创建时的字符集,如果数据库创建时没有设置,则默认等于character_set_server。
领导修改的几个问题隐含的东西
- insert去掉创建时间和更新时间,这样便于查问题,没有依赖的id去掉这样会使系统更加灵活
- int去掉长度,因为int的长度其实没有任何意义参考https://blog.csdn.net/allenjay11/article/details/76549503
和https://blog.csdn.net/Lin_Xioaxin/article/details/77891170 - 创建表时,几乎所有的表都用utf8mb4,那就应该在创建数据库的时候直接指定对于没有中文纯字符型的可以考虑使用ascii编码。