这几天在工作中碰到一个字符乱码的问题,发现在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. java 线程之间通信以及notify与notifyAll区别。

    jvm多个线程间的通信是通过 线程的锁.条件语句.以及wait().notify()/notifyAll组成. 下面来实现一个启用多个线程来循环的输出两个不同的语句. package com.app. ...

  2. [C++空间分配]new运算符、operator new、placement new的区别于联系

    先科普一下: 1. new的执行过程: (1)通过operator new申请内存 (2)使用placement new调用构造函数(内置类型忽略此步) (3)返回内存指针 2. new和malloc ...

  3. leetcode 4sum python

    class Solution(object): def fourSum(self, nums, target): """ :type nums: List[int] :t ...

  4. [置顶] woff格式字体怎么打开和编辑?

    如题! woff百度百科:http://baike.baidu.com/link?url=toS7yqpN9VlEcO2GOEp5JEA9-TeaZgIdVqTOv7iHshsNvk-V8HtxEY0 ...

  5. jQuery中的.live()与die()

    翻译原文地址:http://www.alfajango.com/blog/exploring-jquery-live-and-die/ 很多开发者都知道jQuery的.live()方法,他们大部分知道 ...

  6. inline-block代替浮动布局float:left列表布局最佳方案

    基于各位前辈的辛勤劳动,下面得出使用inline-block替换float:left;的最佳方案. html代码 <div class="list"> <ul&g ...

  7. 你的阅读造就了你 You are what you read

    在豆瓣上看到的一篇很有思想和正能量的文章,在这里请允许我用原创的方式来呈现给大家.如果你是在校的大学生或者研究生博士生,这篇文章会让你有很多的共鸣.如果你已真正的踏入这个社会,也将受益匪浅.   电脑 ...

  8. vijos 1067 Warcraft III 守望者的烦恼 矩阵

    题目链接 我们可以很容易的推出dp的式子, dp[i] = sigma(j : 1 to k) dp[i-j]. 但是n太大了, 没有办法直接算, 所以我们构造一个矩阵, 然后快速幂就好了. 就像这样 ...

  9. 帝国cms留言表模板修改

    <form action="../../enews/index.php" method="post" name="form1" id= ...

  10. CF卡是什么

    CF卡(Compact Flash)最初是一种用于便携式电子设备的数据存储设备.作为一种存储设备,它革命性的使用了闪存,于1994年首次由SanDisk公司生产并制定了相关规范.当前,它的物理格式已经 ...