MySQL8.0学习记录11 - 连接中的字符集与校对规则

连接中的字符集注意有一下几个部分组成:

  1. 表示连接中服务器端的字符集character_set_connection和校对规则collation_connection
  2. 表示连接中客户端的字符集character_set_client
  3. 表示连接中返回给客户端的数据的字符集character_set_results ,包括结果数据,以及列名、报错信息等元数据

其中,collation_connection 主要对字符串字面量有效,对列值不生效,因为字符列有自己的校对规则。

客户端发送语句到服务端执行的时候,服务器端会将语句从字符集 character_set_client 转成character_set_connection。返回数据的时候,会将字符集转成character_set_results变量表示的字符集。

character_set_results

默认情况下,character_set_results 是没有值的,这个时候返回元数据信息的字符集看的是变量character_set_system。

用一个utf8mb3不能表示的中文字来看character_set_results 的作用:

create table t_character_set_result(
	a varchar(30) character set utf8mb4
);

insert into t_character_set_result values('𢓭');

以utf8mb3字符集查看插入的值:

set character_set_results = 'utf8mb3';
select * from t_character_set_result;
a|
-+
?|

这时候单独改变character_set_client 为utf8mb4,并不会正常显示,说明返回数据的字符集的确看的是character_set_results 。

set  character_set_client = 'utf8mb4';
select * from t_character_set_result;

接着将character_set_results改为null或者utf8mb4就可以正常显示

set character_set_results = null;
select * from t_character_set_result;

将character_set_results设为gb18030字符集,依然可以正常显示,这是因为正确发生了转换。同理也可以想象character_set_client 与character_set_connection之间的转换。重要的是转换的前后的字符集都可以表示对应的数据。

character_set_client

看一个例子:

connection.prepareStatement("set character_set_client = gb18030;").execute();
PreparedStatement preparedStatement = connection.prepareStatement("select '茶馆','风华'");

ResultSet resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
System.out.print(metaData.getColumnName(1));
System.out.print(",");
System.out.println( new String(metaData.getColumnName(1).getBytes("gb18030"), "utf-8"));
System.out.println("================");

while (resultSet.next()) {
    String string = resultSet.getString(1);
    System.out.print(string);
    System.out.print(",");
    System.out.println(new String(string.getBytes("gb18030"), "utf-8"));
}
鑼堕,茶馆
================
鑼堕,茶馆

这里指定的客户端的字符集是gb18030,而Java的默认字符集是UTF-8。需要转换一下。

元数据与值的字符集处理不完全相同,如果在上面的例子中一开始再加一句:

connection.prepareStatement("set character_set_results = gb18030;").execute();

结果变了,元数据已经是正确的UTF-8字符集:

茶馆,���
================
鑼堕,茶馆

另外一个注意的是,SQL中的字符串字面量因为需要从客户端的发到服务器,再发回来。但是数据库表里面的值不同,不需要多余转换:

connection.prepareStatement("set character_set_results = gb18030;")
        .execute();
connection.prepareStatement("set character_set_client = gb18030;")
        .execute();
PreparedStatement preparedStatement = connection.prepareStatement("select * from t_character_set_result;");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
    String string = resultSet.getString(1);
    System.out.print(string);
    System.out.print(",");
    System.out.println(new String(string.getBytes("gb18030"), "utf-8"));
}
𢓭,�9�9
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值