这几天在工作中碰到一个字符乱码的问题,发现在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. su 切换用户

    大部分Linux发行版的默认账户是普通账户,而更改系统文件或者执行某些命令,需要root身份才能进行,这就需要从当前用户切换到root用户,Linux中切换用户的命令是su或su - 前者只是切换ro ...

  2. Java 工厂模式学习

    工厂模式分三种:简单工厂.工厂方法.抽象工厂.其中抽象工厂是用于多个产品族的情况.所谓产品族就是不同产品组成的有机整体,各不同产品之间相互依赖.打个比方,一台电脑有CPU.主板.内存和硬盘等,这些不同 ...

  3. mysql登录错误或者密码错误

    一.mysql登录错误 mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user 'root ...

  4. HTML豆ちしき

    HTML文档里所有的空白符(空格,Tab,换行,回车)会被浏览器忽略,唯一的例外是空格,对空格的处理方式是所有连续的空格被当成一个空格,不管有一个,还是两个,还是100个.之所以有这样的规则是因为忽略 ...

  5. 自学HTML5第二节(标签篇---新增标签详解)

    HTML5新增标签: <article> 标签 规定独立的自包含内容.一篇文章应有其自身的意义,应该有可能独立于站点的其余部分对其进行分发. <article> 元素的潜在来源 ...

  6. Linux宕机最安全的重启方法(你肯定不知道)

    Linux 内核虽然号称“不死族”,几乎不会崩溃或者死机,但是特殊情况下,还是有一定几率会宕机的.因为 Linux 广泛用于生产环境,所以每一次宕机都会引起相当大的损失.本文介绍在它死机至后,一种温柔 ...

  7. NOI2011 Day2

    NOI2011 Day2 道路修建 题目描述:给出一棵树,求每条边的两边的端点数的差乘边权之和. solution: 题目可能描述得不太清楚,如图: 对于虚边,如果边权为10,两边的端点数之差为2,这 ...

  8. python 类型转换函数

    python提供了一些可将某个值从一种类型转换为另一种类型的内置函数. 1. int函数可以把任何可以转换为整型的值转换为整型.int可以将浮点数转换为整数,但不会做四舍五入操作,而是直接丢弃小数部分 ...

  9. Dreamweaver中打开CodeSmith文件

    电脑环境:Windows2008+Dreamweaver 8英文版本 问题描述:Dreamweaver中默认打开文档时不支持打开CodeSmith模板文件对应的.cst后缀名文件,截图如下: 解决步骤 ...

  10. ZOJ1100 状压DP +深搜

    记得做过类似于这类题目是能够用组合数学方法来解决的,可惜淡忘了,也找不到了,看了网上的也有人提到过能够用组合公式解决,但是没人做,都是用了状压DP的方法,这个状压非常难讲清楚吧,推荐两篇 第一遍大体看 ...