彻底解决Oracle中文乱码

影响Oracle编码的配置有3处:

服务端字符集 操作系统字符集 NLS_LANG字符集
SELECT * FROM NLS_DATABASE_PARAMETERS locale export
american_america.AL32UTF8 en_US.UTF-8 AMERICAN_AMERICA.ZHS16GBK

问题复现:

1. 创建表

CREATE TABLE "CY_BIF_DEV"."MYSQL_TEST_10" 
    (    "ID" NUMBER(7,0) NOT NULL ENABLE, 
    "STRING_VALUE_NOT_NULL" VARCHAR2(100) NOT NULL ENABLE
   );
  
select * from mysql_test_10;
delete from mysql_test_10;
select dump(STRING_VALUE_NOT_NULL, 1016) from mysql_test_10;

2. 检查编码配置

服务端字符集,NLS_CHARACTERSET: ZHS16GBK。
客户端os locale:LANG="en_US.UTF-8”。
环境变量NLS_LANG 没有配置。

3. 写入中文

  1. 插件中文INSERT INTO mysql_test_10 VALUES (2, '中国');中文是UTF-8编码。
  2. 读取中文select * from mysql_test_10,发现显示乱码。
  3. 检查oracle存储的编码,发现存储编码错误。
select dump(STRING_VALUE_NOT_NULL, 1016) from mysql_test_10。
Typ=1 Len=6 CharacterSet=ZHS16GBK: 3f,3f,3f,3f,3f,3f 

正确的UTF编码(中国e4,b8,ad,e5,9b,bd)GBK编码(d6,d0,b9,fa)

问题修正

  • 设置NLS_LANG与客户端os字符集相同。
  • NLS_LANG=american_america.AL32UTF8;

问题分析

  • client端使用UTF8编码,发送到Oracle server端后,server端读取NLS_LANG是空后,直接用GBK编码了数据,于是存储时,字符就错乱了,大小6字节。
  • 设置NLS_LANG=american_america.AL32UTF8后,server端会先到UTF8编码表中查询,翻译后以GBK编码存储,大小4字节。

问题总结

  • NLS_LANG 与客户端os字符集要保持一致。
  • 为了减少翻译开销,最好“服务端字符集”,“客户端os字符集”和NLS_LANG,3者保持一致。

欢迎加入橙鹰数据, 575834439@qq.com

https://www.cnblogs.com/xdouby/p/5666624.html
https://www.cnblogs.com/bingo1717/p/7803359.html

上一篇:《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一2.5.7 使用目录流


下一篇:Java循环练习:打印图案-5