这几天在工作中碰到一个字符乱码的问题,发现在cmd窗口的sqlplus中直接update一个中文和使用@调用一个文件作同样更新的时候,存储的结果 竟不一样。一时比较迷惑,对Oracle如何处理各个字符集的问题不是很清楚。特此通过一些资料和实验总结,系统学习一下Oracle中字符集的相关知 识。

一. 字符集的基础知识:
在网络上已有不少网友对字符集进行了研究,个人觉得有几个不错的网站可以参考
http://blog.csdn.net/tianlesoftware/article/details/4915223
http://www.itstreets.com/post/34.html
http://www.oraclefans.cn/forum/showblog.jsp?rootid=3303

二. Oracle字符集的转换

以下用几个实验来学习一下Oracle对各种字符集的处理
此处涉及3个概念:数据库服务端的字符集,客户端的字符集和操作系统的字符集
实验环境中:数据库服务端的字符集是AL32UTF8

1. 客户端和服务器端的字符集一致的时候
实验一:客户端字符集也是AL32UTF8, 操作系统的字符集是GB2312
CTBLAZER@106orcl>update c_language set languagename='中国' where id = 'zh-CN';

1 row updated.

CTBLAZER@106orcl>commit ;

Commit complete.

CTBLAZER@106orcl>select dump(languagename, 1016) from c_language where id = 'zh-CN';

DUMP(LANGUAGENAME,1016)
-----------------------------------------------------------------------------------------

Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa

CTBLAZER@106orcl>

使用dump函数以16进制查看在数据库中的存储,可以看出“中国”这2个字,在数据库中的存储编码是:d6,d0,b9,fa

先建一个文件t1.txt,写上“中国”这2个字,以GB2312(codepage 为936)的格式保存。
在cmd窗口使用type命令查看,可以看到此时在cmd窗口能正确显示文本。

V:\>chcp
Active code page: 936

V:\>type e:\t1.txt
中国
V:\>

再用winhex工具查看t1.txt文本,可以看到其16进制编码为:D6,D0,B9,FA

实验二:在sqlplus环境中使用@来调用一个sql文件,文件的内容是和实验一同样的一句sql,文件格式为UTF8
服务器和客户端的字符集依然是AL32UTF8, 操作系统的codepage为936

CTBLAZER@106orcl>select dump(languagename, 1016) from c_language where id = 'zh-CN';

DUMP(LANGUAGENAME,1016)
---------------------------------------------------------------------------------------

Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd

CTBLAZER@106orcl>

同样建一个文本文件t2.txt,以UTF8的格式保存。再使用WinHex查看, 可以看到其16进制编码为:E4, B8, AD, E5, 9B, BD

通过这2个实验,可以清楚的看出,在客户端和数据库服务端的字符集一致的时候,Oracle并不进行存储转换。如在cmd窗口之中,
以操作系统默认的GB2312编码的“中国”,和以文件方式按UFT8编码格式的“中国”,都会直接存储到Oracle服务器上。

但是我们会发现,按UTF8格式编码的存储,在cmd里面查询的结果会是乱码。如下:

CTBLAZER@106orcl>host chcp
Active code page: 936

CTBLAZER@106orcl>col languagename format A30
CTBLAZER@106orcl>select * from c_language where id='zh-CN';

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                涓浗
CTBLAZER@106orcl>

这是因为我机器cmd窗口的codepage 默认是936,而客户端和服务器端的字符集都一样,Oracle会不做任何转换的把保存的字符编码
直接返回回来,但是数据库里面的编码是按UTF8的存储的,而cmd窗口的字符编码为GB2312,故而是显示的乱码。

我们可以将cmd窗口的codepage先改为UTF8(codepage为65001)格式的,则可以看到正常的显示“中国”这2个字了。如下:
(如何修改codepage,可以参考:http://xiangqinghu1988.blog.163.com/blog/static/58822991201222232456746/)

Active code page: 65001

CTBLAZER@106orcl>select * from c_language where id = 'zh-CN';

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                中国

CTBLAZER@106orcl>


此,在Oracle没有施行字符转换的时候,即(客户端和服务器端的字符集是一致的时候),如果出现乱码,那么则是表明客户端的环境编码(如cmd窗口的
编码)和Oracle数据库存储的字符编码(cmd窗口直接用sqlplus更新和调用一个UTF8文件格式的更新)不一致。如果要查看,需要修改客户端
的环境编码。比如修改cmd的codepage。

2. 客户端和服务器端的字符集不一致的时候
实验三:将客户端的字符集设置为ZHS16GBK,在sqlplus里面直接更新记录如下:

V:\>set NLS_LANG=American_America.ZHS16GBK

V:\>sqlplus ctblazer@106orcl

SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 22 15:29:43 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Enter password:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

CTBLAZER@106orcl>Update c_language set languagename='中国' where id = 'zh-CN';

1 row updated.

CTBLAZER@106orcl>commit;

Commit complete.

CTBLAZER@106orcl>col languagename format A30
CTBLAZER@106orcl>select * from c_language where id = 'zh-CN';

ID                                       LANGUAGENAME
---------------------------------------- ------------------------------
zh-CN                                    中国

CTBLAZER@106orcl>select dump(languagename, 1016) from c_language where id = 'zh-CN';

DUMP(LANGUAGENAME,1016)
-----------------------------------------------------------------------------------------

Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd

CTBLAZER@106orcl>

结果很有意思,数据库中存储的不再是像实验一中的d6,d0,b9,fa, 而是很巧的变成了UTF8格式的存储了。如果我们开另外一个
sqlplus窗口,其客户端字符集为AL32UTF8,这时来查看一下这条记录如下,发现乱码了

V:\>sqlplus ctblazer@106orcl

SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 22 15:36:56 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Enter password:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

CTBLAZER@106orcl>col languagename format A30
CTBLAZER@106orcl>select * from c_language where id = 'zh-CN';

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                涓浗

CTBLAZER@106orcl>

如果我们把cmd的codepage设置为UTF8格式的,我们就可以看到是正常的显示了(这时还是要求客户端与服务器端的字符集一致)

Active code page: 65001
CTBLAZER@106orcl>select * from c_language where id = 'zh-CN';

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                中国

CTBLAZER@106orcl>

注意,这个实验的结果比较巧合,如果将sqlplus客户端的字符集不是设置ZHS16GBK,而是设为其他的字符集,那么Oracle中存储的就不一定是UTF8的编码了。
实际上,如果客户端和服务端的字符集不一致,Oracle底层会对字符编码进行转换,具体如何转换我也还不清楚,望有高手深入研究。

总的来说,在实际中如果碰到乱码情况,需要知晓Oracle客户端字符集,服务器端字符集以及操作系统字符集这几个之间的关系。
1. 如果客户端和服务器端的字符集一致,Oracle不会进行编码转换。直接按存储操作系统相关的编码格式存储。在查询的时候,也不会转换,而是直接返回数据库中存储的编码
2. 如果客户端和服务器端的字符集不一致,Oracle会在底层对存储的字符进行编码转换。在查询返回的时候,同样会转换一次。

Oracle字符集转换的更多相关文章

  1. oracle 字符集转换:AL32UTF8->ZHS16GBK

    select userenv('language') from dual; --修改Oracle数据库字符集为ZHS16GBK : SQL>conn / as sysdba; SQL>sh ...

  2. oracle 字符集导入、导出 、转换

    导入导出及转换 导入导出是我们常用的一个数据迁移及转化工具,因其导出文件具有平台无关性,所以在跨平台迁移中,最为常用. 在导出操作时,非常重要的是客户端的字符集设置,也就是客户端的NLS_LANG设置 ...

  3. 部署OGG时字符集转换问题--oracle to oracle已验证,其他异构环境应当也适用

    之前在安装OGG总是遇到字符集问题,尤其是多源端对一个目标端时,源端字符集不同,导致出现字符集问题 无法同步数据,查阅了大量的园子资料,都说要设置复制或抽取进程中SETENV (NLS_LANG=AM ...

  4. ORACLE字符集基础知识

    概念描叙    ORACLE数据库有国家字符集(national character set)与数据库字符集(database character set)之分.两者都是在创建数据库时需要设置的.国家 ...

  5. oracle字符集相关问题

    整理自网络+实验 字符集介绍 影响Oracle数据库字符集最重要的参数是NLS_LANG参数. 它的格式如下: NLS_LANG = language_territory.charset  NLS_L ...

  6. Oracle字符集的查看查询和Oracle字符集的设置修改

    本文主要讨论以下几个部分:如何查看查询oracle字符集. 修改设置字符集以及常见的oracle utf8字符集和oracle exp 字符集问题. 一.什么是Oracle字符集 Oracle字符集是 ...

  7. 如何修改Oracle字符集

    一.什么是Oracle字符集 Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系.ORACLE 支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据.它使数据库 ...

  8. 转Oracle字符集问题总结

    Oracle字符集问题总结 分类: Oracle2006-06-04 13:48 1298人阅读 评论(3) 收藏 举报 oracle数据库sqlcharacter存储insert 作者: vston ...

  9. (转)oracle字符集与汉字

    Oracle与汉字问题与字符集 分类: oracle 2012-10-29 17:31 425人阅读 评论(0) 收藏 举报 Oracle字符集引起的几个问题,常见的就是汉字占多少个字节,其次就是字符 ...

随机推荐

  1. iOS 打开系统设置

    NSURL*url=[NSURL URLWithString:@"prefs:root=WIFI"]; [[UIApplication sharedApplication] ope ...

  2. iOS7、iOS8推送通知的区别

    iOS8版本以后的推送通知代码[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificati ...

  3. Python框架

     Django.Pylons & TurboGears & repoze.bfg.Tornado & web.py.Bottle & Flask.Quixote(豆瓣用 ...

  4. hadoop笔记之MapReduce的应用案例(WordCount单词计数)

    MapReduce的应用案例(WordCount单词计数) MapReduce的应用案例(WordCount单词计数) 1. WordCount单词计数 作用: 计算文件中出现每个单词的频数 输入结果 ...

  5. 移动web开发

    在现代网页开发中,新增了一个移动设备网页开发,在这样的需求下,你需要考虑如何将移动web和pc web同步处理 /* * 浏览器如何识别移动设备 * */ var ua = navigator.use ...

  6. 用JavaScript获取地址栏参数的方法

    /** * 获取地址栏参数 * * @example GetUrlString('id') * * @desc 调用时加上判断,保证程序不会出错 * var myurl = GetUrlString( ...

  7. php 异步处理的gearman

    1. php 是进程处理,单线程到的,没有异步机制,在一些处理花费时间较多的情况导致用户体验较差.可以使用gearman 进行异步处理. 2. gearman 是一个异步处理的socket架构. 需要 ...

  8. ios字符串计算高度总结

    1.用xib的话,设置约束的时候 不设置lable的高度即可,高度返回的就是最优高度. 2.用lable代码计算高度 CGFloat getHeightForLableString(NSString ...

  9. Python核心编程笔记--随机数

    #第一步引入模块 import random #第二步生成随机数 print random.randint(1,3);#[1,2,3]注意这里是闭区间.

  10. JQ中$(document.ready())

    js中window.onload与jquery中$(document.ready())的区别 <html> <head> <script type='text/javas ...