设为首页 收藏本站
查看: 745|回复: 0

[经验分享] oracle数据库字符集

[复制链接]

尚未签到

发表于 2018-9-7 10:07:55 | 显示全部楼层 |阅读模式
  我用的数据库是oracle11.2.0.4,数据库字符集是al32utf8。
  客户端就是同一台机器的windows 7
  用window7的客户端连接
  查看windows客户端中文字符
  虚拟机   192.168.10.5    数据库是test1    数据库字符集是al32utf8。
  C:\Users\Administrator>echo %NLS_LANG%             -------查看客户端字符命令
  SIMPLIFIED CHINESE_CHINA.AL32UTF8
  set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK       -----设置客户端字符命令
  数据库是test1   ,数据库字符集是al32utf8。
  --session 1 设置客户端字符集为 zhs16gbk(修改注册表nls_lang项的characterset 为zhs16gbk) 向表中插入两个中文字符。
  C:\Users\Administrator>echo %NLS_LANG%
  SIMPLIFIED CHINESE_CHINA.ZHS16GBK
  C:\Users\Administrator>sqlplus sys/oracle@test1 as sysdba;
  SQL> create table test(col1 number(1),col2 varchar2(10));
  SQL> insert into test values(1,'中国'); --1为session 1的标记
  1 row created.
  SQL> commit;
  Commit complete.
  SQL> create table test(col1 number(1),col2 varchar2(10));
  表已创建。
  SQL>  insert into test values(1,'中国');
  已创建 1 行。
  SQL>
  -session 2 设置客户端字符集 al32utf8(修改注册表nls_lang项的characterset 为al32utf8),与数据库字符集相同。 向表中插入两个和session 1相同的中文字符。
  C:\Users\Administrator>echo %NLS_LANG%
  SIMPLIFIED CHINESE_CHINA.AL32UTF8
  C:\Users\Administrator>sqlplus sys/oracle@test1 as sysdba;

  SQL*Plus:>  Copyright (c) 1982, 2010, Oracle.  All rights reserved.
  杩炴帴鍒?

  Oracle Database 11g Enterprise Edition>  With the Partitioning, OLAP, Data Mining and Real Application Testing options
  SQL>
  SQL> insert into test values(2,'中国'); --2为session 2的标记
  1 row created.
  SQL> commit;
  Commit complete.
  --session 1
  SQL> select * from test;
  COL1 COL2
  ---------- --------------------
  1 中国
  2 ???
  --session 2
  SQL> select * from test;
  COL1 COL2
  ---------- ----------
  1 涓浗
  2 中国
  SQL>
  从session 1和session 2的结果中可以看到,相同的字符(注意,我指的是我们看到的,显示为相同的字符 中国),在不同的字符集输入环境(客户端环境变量)下,显示成了乱码。
  在zhs16gbk字符集的客户端,我们看到了utf8字符集客户端输入的相同的中文变成了乱码-->col1=2的col2字段
  SQL> select * from test;
  COL1 COL2
  ---------- --------------------
  1 中国
  2 ???
  在utf8字符集客户端,我们看到zhs16gbk字符集的客户端输入的中文变成了另外的字符  -->col1=1的col2字段
  SQL> select * from test;
  COL1 COL2
  ---------- ----------
  1 涓浗      -----三个字符
  2 中国
  SQL> select col1,dump(col2,1016) from test;
  COL1
  ----------
  DUMP(COL2,1016)
  -------------------------------------------------------------
  1
  Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd
  2
  Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
  不同的客户端输入的中文字符,在数据库中存储的字符编码不一致。
  session 1 输入的字符"中国" 在数据库中存储的字符编码为”e4,b8,ad,e5,9b,bd".
  session 2 输入的字符"中国" 在数据库中存储的字符编码为”d6,d0,b9,fa".
  会话一、
  中国-------e4,b8,ad,e5,9b,bd     数据库发现客户端16gbk跟数据库端的utf8字符不一致    做了字符转换  首先将客户端 中国 16gbk的(双字节)编码转成utf8(三字节编码) 然后存储下来。
  会话二、
  中国-------d6,d0,b9,fa           数据库发现客户端utf8跟数据库端的utf8字符一致      欺骗了数据库端,不做字符转换,直接以16gbk(双字节)的字符编码存储到数据库(utf8数据库编码为三字节)中。
  session 1 输入的字符"中国" 在数据库中存储的字符编码为”e4,b8,ad,e5,9b,bd"
  session 2 输入的字符"中国" 在数据库中存储的字符编码为”d6,d0,b9,fa"
  数据库看到客户端的字符集和数据库的字符集一致,此时oracle将不会再对字符作转换,因为它认为两边的字符编码是一致的。而此时,
  我们欺骗了数据库,尽管我们将客户端字符集设置为和数据库一致,但是其实我们使用的是zhs16gbk字符集编码(因为此时windows使用的就是这个字符编码),
  对于字符"中国",zhs16gbk字符集里对应的编码为d6,d0,b9,fa。此时,oracle不加理会的直接将这个编码保存到了数据库中。
  客户端的字符集的作用就是告知数据库端传输的字符编码,跟数据库端的字符集一致就直接存储,不一致就字符转换。
  查询是存储的字符转换的逆过程。
  session1查询
  SQL> select * from test;
  COL1 COL2
  ---------- --------------------
  1 中国
  2 ???
  当session 1开始查询时,oracle从表中取出这两个字符,并按照字符集al32utf8和字符集zhs16gbk的编码映射表,将它的转换成zhs16gbk字符编码,对于编码“e4,b8,ad,e5,9b,bd”,
  它对应的zhs16gbk的字符编码为"d6,d0,b9,fa",这个编码对应的字符为”中国“,所以我们看到了这个字符正常显示出来了,
  而对于字符集存储的al32utf8字符编码“d6,d0,b9,fa”,
  由于我们用于显示字符的windows环境使用的是zhs16gbk字符集,而在zhs16gbk字符集里面并没有对应这个编码的字符或者属于无法显示的符号,utf8---16gbk 转换找不到
  于是使用了"?"这样的字符来替换,这就是为什么我们看到session 2输入的字符变成了这样的乱码。
  session2查询
  SQL> select * from test;
  COL1 COL2
  ---------- ----------
  1 涓浗
  2 中国
  SQL>
  当session 2开始查询时,oracle从表中取出这两个字符,由于客户端(nls_lang)和数据库的字符集设置一致,oracle将忽略字符的转换问题,
  于是直接将数据库中存储的字符返回给客户端。对于编码为"d6,d0,b9,fa"的字符,返回给客户端,而客户端显示所用的字符集正好是zhs16gbk,在这个字符集里,########(虽然客户端变成ut8,但是转换回来还是以16gbk的,windows依然是16gbk。)
  这个编码对应的是"中国"两个字符,所以就正常显示出来了。
  对于字符编码“e4,b8,ad,e5,9b,bd”,返回到客户端後,因为在zhs16gbk里采用的是双字节存储字符方式,(虽然客户端变成utf8,但是转换回来还是以16gbk的,windows依然是16gbk。)
  所以这6字节对应了zhs16gbk字符集的3个字符,也就是我们看到的"涓浗"。
  导入导出 exp   imp 客户端对字符的影响实验
  创建两个库
  test1 源数据库 字符集-----------   SIMPLIFIED CHINESE_CHINA.AL32UTF8
  test2 目标数据库 字符集-----------   SIMPLIFIED CHINESE_CHINA.16gbk
  创建用户jiang/oracle  建立test表
  oracle@linux5:/oracle>export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK" ###########环境变量
  SQL>  select col1,dump(col2,1016) from test;
  COL1
  ----------
  DUMP(COL2,1016)
  --------------------------------------------------------------------------------
  2
  Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
  1
  Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd

  Export:>  Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

  连接到: Oracle Database 11g Enterprise Edition>  With the Partitioning, OLAP, Data Mining and Real Application Testing options
  已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
  服务器使用 AL32UTF8 字符集 (可能的字符集转换)
  . 正在导出 pre-schema 过程对象和操作
  . 正在导出用户 JIANG 的外部函数库名
  . 导出 PUBLIC 类型同义词
  . 正在导出专用类型同义词
  . 正在导出用户 JIANG 的对象类型定义
  即将导出 JIANG 的对象...
  . 正在导出数据库链接
  . 正在导出序号
  . 正在导出簇定义
  . 即将导出 JIANG 的表通过常规路径...
  . . 正在导出表                            TEST导出了           2 行
  . 正在导出同义词
  . 正在导出视图
  . 正在导出存储过程
  . 正在导出运算符
  . 正在导出引用完整性约束条件
  . 正在导出触发器
  . 正在导出索引类型
  . 正在导出位图, 功能性索引和可扩展索引
  . 正在导出后期表活动
  . 正在导出实体化视图
  . 正在导出快照日志
  . 正在导出作业队列
  . 正在导出刷新组和子组
  . 正在导出维
  . 正在导出 post-schema 过程对象和操作
  . 正在导出统计信息
  成功终止导出, 没有出现警告。
  导入到test2 ,目标数据库字符集为16gbk
  oracle@linux5:/oracle>imp jiang/oracle@test2 fromuser=jiang touser=jiang file=/backup/test1.dmp log=/backup/testimp.log

  Import:>  Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

  连接到: Oracle Database 11g Enterprise Edition>  With the Partitioning, OLAP, Data Mining and Real Application Testing options
  经由常规路径由 EXPORT:V11.02.00 创建的导出文件
  已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
  . . 正在导入表                          "TEST"导入了           2 行
  成功终止导入, 没有出现警告。
  oracle@linux5:/oracle>
  SQL> select * from test;
  COL1 COL2
  ---------- ----------
  2 ???
  1 中国
  SQL>  select col1,dump(col2,1016) from test;
  COL1
  ----------
  DUMP(COL2,1016)
  --------------------------------------------------------------------------------
  2
  Typ=1 Len=4 CharacterSet=ZHS16GBK: a3,bf,3f,3f
  1
  Typ=1 Len=4 CharacterSet=ZHS16GBK: d6,d0,b9,fa          ------------2个字节一个汉字, 16gbk编码存储 数据库做了数字编码转换工作。
  SQL>
  参考   http://blog.csdn.net/wuweilong/article/details/39694531
  源端数据库test1 (1)字符集为utf8 →EXP客户端(2)→IMP客户端(3)→目标数据库(4) test2字符集为16gbk,
  数据在迁移过程中要经历如上的4个点,数据在流动过程中(如上的3个箭头)需要依次比较箭头两端的字符集,
  如果相同则不转换,如果不同则进行转换。如果相邻的两个点之间设置的字符集均不相同,则需要转换3次。
  最好的设置方式是,因为(1)(4)数据库的字符集是固定的,则设置客户端的字符集(2)(3)均与(1)相同,
  这样最多只在(3)→(4)的过程中发生一次字符集的转换。但是前提是(4)的字符集必须是(1)的的字符集的超集。客户端字符集是通过环境变量NLS_LANG来设置。
  写入数据----字符转换过程
  数据库端通过简单的判断跟 客户端环境变量的字符集  是否一致进行字符转换   一致则不转换,直接存储到数据库中,不一致则字符转换。
  客户端的字符集的作用就是告知数据库端传输的字符编码
  数据库看到客户端的字符集和数据库的字符集一致,此时oracle将不会再对字符作转换,因为它认为两边的字符编码是一致的。而此时,
  我们欺骗了数据库,尽管我们将客户端字符集设置为和数据库一致,但是其实我们使用的windows7是zhs16gbk字符集编码(因为此时windows使用的就是这个字符编码),
  对于字符"中国",zhs16gbk字符集里对应的编码为d6,d0,b9,fa。此时,oracle不加理会的直接将这个编码保存到了数据库中。
  查找数据----字符转换过程(win7  16gbk一定)
  当session 1开始查询时,oracle从表中取出这两个字符,并按照字符集al32utf8和字符集zhs16gbk的编码映射表,将它的转换成zhs16gbk字符编码,对于编码“e4,b8,ad,e5,9b,bd”,
  它对应的zhs16gbk的字符编码为"d6,d0,b9,fa",这个编码对应的字符为”中国“,所以我们看到了这个字符正常显示出来了,3---2
  而对于字符集存储的al32utf8字符编码“d6,d0,b9,fa”,
  由于我们用于显示字符的windows环境使用的是zhs16gbk字符集,而在zhs16gbk字符集里面并没有对应这个编码的字符或者属于无法显示的符号,utf8---16gbk 转换找不到
  于是使用了"?"这样的字符来替换,这就是为什么我们看到session 2输入的字符变成了这样的乱码。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-565694-1-1.html 上篇帖子: Linux Centos 6.6安装Oracle 11g-12259248 下篇帖子: ORACLE使用数据泵定时执行备份与问题总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表