影响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. 写入中文
- 插件中文INSERT INTO mysql_test_10 VALUES (2, '中国');中文是UTF-8编码。
- 读取中文select * from mysql_test_10,发现显示乱码。
- 检查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