• mysql学习笔记2:如何避免数据库乱码


    一、三个重要的数据库参数

    character_set_client:客户端发送的sql语句编码字符集。它的作用就是告诉mysql服务器,本地客户端采用了什么编码环境。insert into t values(‘吴’); 服务器知道这条sql是以character_set_client指定的字符集所编码的,'吴’将被转化为指定的编码格式,比如它的utf8编码为E590B4,最终以0101…发送到server。

    character_set_connection:服务器将接收到的character_set_client指定编码的sql语句翻译成character_set_connection指定编码的sql。

    character_set_results:指示了服务器将查询结果返回给客户端的字符集。服务器检索库表之后,需根据该变量的值将查询结果的字符集转化为character_set_results所指定的字符集。

    每个客户端或者终端在连接上server之后,都有自己特定的系统变量,服务器默认采用客户端的本地化参数初始化系统变量的值,并且在本次会话中可以动态改变其值。Linux下的shell和win下的dos在连接到server之后,本地化参数可能存在差异(编码格式:linux默认一般是utf8,win下一般是gbk),上面三个变量在不同终端下值的不同就是最好的验证,下面的例子连接的是都是相同的数据库。

    在mysql workbench下的三个参数:
    在这里插入图片描述
    在navicat下的三个参数:
    在这里插入图片描述
    Windows cmd下的三个参数:
    在这里插入图片描述
    由上面三个图可知,对于不同的客户端,连上数据库之后,会根据本地化参数修改上述的三个参数。

    二、mysql客户端和服务器端编码解码过程

    在这里插入图片描述
    在这里插入图片描述
    在客户端连接数据库服务器的过程中,三个变量都是session级别的,可以随时通过客户端进行设置,当然一般这三个值都是设置成一样的,而且要确保DB的字符集要包含或者和三个参数设置的字符集一样才能保证不出现乱码。如下面的例子:
    DB的字符集:latin1
    character_set_client字符集:utf8
    character_set_connection字符集:utf8
    character_set_results字符集:utf8
    因为latin1是1个字节用来存储字符,而utf8如果存储中文用的是3个字节存储一个字符,如果在linux客户端(客户端的编码是utf8)插入中文字符‘吴’他的utf8编码为‘E590B4 ’,那么在步骤(2)插入到数据库中肯定就是乱码。而且插入的时候,还会抛出如下告警(修改数据库sql_mode为非严整模式可插入,但抛出警告):

    | Warning | 1366 | Incorrect string value: '\xE5\x90\xB4' for column 't' at row 1 |
    
    • 1

    这种是属于有损转换,数据库字符是latin1是单字节字符,无法解析utf8的3字节字符,最终会用乱码代替,之后也是无法复原。
    如果把:
    character_set_client字符集:utf8
    character_set_connection字符集:utf8
    character_set_results字符集:utf8
    数据库的表的字符集编码设置为:utf8

    此时通过linux客户端插入中文字符‘吴’,此时是可以正常插入,没有任何问题,但如果在查询的时候,设置了character_set_results=gbk,这个时候查询出来的肯定是乱码,因为‘吴’这个中文字符的编码在gbk里面是找不到对应字符的,所以解码出库时就会显示乱码,这个时候,存入的数据是utf8编码,只要把character_set_results这个变量改为utf8,那么就能正常显示中文了,这种情况是属于无损编码转换,只要设置正确的编码就能还原。

    三、如何避免乱码

    保证character_set_client,character_set_connection,character_set_results三个的编码一致,并保证数据库的库,表,相应字段字符集编码设置与这三个变量相同或者是他们的超集就可以完全避免中文乱码。在实际实践中,设置客户端(包含app,客户端,数据库jdbc驱动)字符集编码为utf8mb4,数据库相应的库,表,字段都设置为utf8mb4,可以显示所有的字符(包含表情)而不产生乱码。

  • 相关阅读:
    算法训练Day27 | LeetCode39. 组合总和 (元素可重复,数组长度不限);40. 组合总和III(去重);131.分割回文串
    为何抢跑了成长型企业SaaS赛道?先看看用友YonSuite有多了解企业
    android 创建桌面快捷方式 ShortCut
    EasyExcel知识【Java程序进行读写生成Excel操作】
    【API接口功能】以图搜款,最快1秒助您找到想要的商品!
    springboot中使用redis管理session
    使用Java继承UDF类或GenericUDF类给Hive3.1.2编写UDF实现编码解码加密解密并运行在USDP大数据集群
    基于C#的软件加密、授权与注册
    forward 函数在深度神经网络程序中确实用于表示程序逻辑,特别是网络的前向传播过程。它描述了输入数据如何通过网络的每一层,并最终得到输出预测值的流程
    【快速上手ESP32(基于ESP-IDF&VSCode)】07-I2C(附BH1750实战代码)
  • 原文地址:https://blog.csdn.net/hon_vin/article/details/127546842