免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5451 | 回复: 1
打印 上一主题 下一主题

用sqlplus查看新导入的数据全部是乱码 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-19 16:31 |只看该作者 |倒序浏览
好友的客户碰到了这样一个问题----通过前台导入数据后发现前台显示这些导入的数据正常,但是用sqlplus看这些新导入的数据全部是乱码。



后来被我发现导致这种现象的原因是前台导入的时候错误的选择了Unicode字符集对源数据的GBK编码做了转换,且NLS_LANG和数据库的NLS_CHARACTERSET一致(都是ZHS16GBK)。而且更要命的是朋友客户刚刚改过NLS_LANG(以前的NLS_LANG设的是AL32UTF8),这直接导致了数据库中有部分数据是GBK编码,而另外一部分数据则是Unicode编码。



Oracle里的字符集的正确理解涉及到NLS_LANG,NLS_CHARACTERSET和客户端OS的字符集这三方面,任何一个不对,都会导致乱码的出现。



我们来看一个实际的例子,我现在库的NLS_CHARACTERSET是ZHS16GBK,我首先想办法以Unicode编码(AL32UTF8)插入字符'美好 ',同时再以GBK编码(ZHS16GBK)也同时插入字符'美好 ':

SQL_testdb>select name,dump(name,16) from t_c;



NAME                                     DUMP(NAME,16)

----------------------------------------               -----------------------------------------------------

缇庡ソ                                   Typ=1 Len=7: e7,be,8e,e5,a5,bd,20

美好                                     Typ=1 Len=5: c3,c0,ba,c3,20



这里就构造出了朋友客户那边的实际情况,NLS_CHARACTERSET为ZHS16GBK的库,但是库里的数据却同时有Unicode和GBK两种编码。



朋友问我----有没有办法让库里已经存在的Unicode编码的数据在sqlplus中正常的显示?

这里是没有办法的,即使把NLS_LANG设置成了AL32UTF8,或者说除非你能找到一个OS是Unicode编码的客户端。这是因为NLS_CHARACTERSET始终都是ZHS16GBK,当你把NLS_LANG设置成了AL32UTF8后,oracle会把已经是Unicode编码的字符'美好 '再次以oracle内置的字符集转换规则从GBK编码转换为Unicode编码:

[P550_04_LAracle@:/dras20/testdb]#export NLS_LANG=AMERICAN_AMERICA.AL32UTF8



SQL_testdb>select name,dump(name,16) from t_c;



NAME                 DUMP(NAME,16)

--------------------       --------------------------------------------------------

缂囧骸銈?              Typ=1 Len=7: e7,be,8e,e5,a5,bd,20

缇庡ソ                 Typ=1 Len=5: c3,c0,ba,c3,20

从结果里我们可以看到,现在显示结果更乱了:)



但其实还是有办法让Unicode编码的字符'美好 '正常显示的,只不过这种方法没有实际意义。

我们现在来让Unicode编码的字符'美好 '在sqlplus中恢复正常显示:

[P550_04_LAracle@:/dras20/testdb]#export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK



[P550_04_LAracle@:/dras20/testdb]#sqlplus '/ as sysdba';



SQL*Plus: Release 9.2.0.6.0 - Production on Wed Nov 17 08:44:42 2010



Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.





Connected to:

Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production

With the Partitioning, OLAP and Oracle Data Mining options

JServer Release 9.2.0.6.0 - Production



SQL_testdb>update props$ set value$='AL32UTF8' where name='NLS_CHARACTERSET';



1 row updated.



SQL_testdb>commit;



Commit complete.



SQL_testdb>select name,value$ from props$ where name='NLS_CHARACTERSET';



NAME                 VALUE$

--------------------         -----------------------------------------------------------------------------

NLS_CHARACTERSET     AL32UTF8



SQL_testdb>shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.



SQL_testdb>startup pfile=/dras20/testdb/inittestdb.ora

ORACLE instance started.



Total System Global Area  504858456 bytes

Fixed Size                   743256 bytes

Variable Size             285212672 bytes

Database Buffers          218103808 bytes

Redo Buffers                 798720 bytes

Database mounted.

Database opened.



SQL> select name,dump(name,16) from t_c;



NAME                                     DUMP(NAME,16)

---------------------------------------- -----------------------------------------------------------

美好                                     Typ=1 Len=7: e7,be,8e,e5,a5,bd,20

???                                    Typ=1 Len=5: c3,c0,ba,c3,20

这里的原理就是利用了Oracle只会根据NLS_LANG和数据库的NLS_CHARACTERSET来做字符集的转换,当我把NLS_LANG设为ZHS16GBK,NLS_CHARACTERSET修改为AL32UTF8后,Oracle此时就会把字符'美好 '的Unicode编码07,e7,be,8e,e5,a5,bd,20转换为GBK编码05,c3,c0,ba,c3,20,同时又因为我的客户端OS的字符集编码就是GBK,所以这里我就能正确的看到字符'美好 '了。



有朋友看到这里可能会问:你只修改了props$,但是控制文件里记录的数据库字符集还是ZHS16GBK,你这里已经不一致了。

没关系的,oracle不会允许这种不一致存在,如下是alert log里的相关内容:

Wed Nov 17 10:17:53 2010

SMON: enabling tx recovery

Wed Nov 17 10:17:53 2010

Updating character set in controlfile to AL32UTF8

这跟数据库在open的时候oracle会根据file$的内容去修改控制文件(如果需要的话)多么的相似!

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
2 [报告]
发表于 2010-11-19 21:32 |只看该作者
发代码时最好用[code]标签给括起来。这样不会出现表情符号。还不错。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP