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

[经验分享] Oracle字符集总结归纳

[复制链接]

尚未签到

发表于 2018-9-25 07:13:26 | 显示全部楼层 |阅读模式
使用常用的gbk,utf8以及ascii说明(oracle中对应hs16gbk,al32utf8,us7ascii)。  其中,ascii为经典的单字节编码,采用7位,只能表示128个常用字符以及计算机控制字符,不能显示中文等字符;gbk为中国大陆标准,16位,简体中文字符集标准;utf8为unicode的一种最常用实现,兼容ascii的字符使用1位,其余字符都采用3位,可以表示任何字符。Utf8其实已经可以称为国际标准字符集编码,应首先考虑使用utf8。需要说明的是,虽然gbk跟utf8都能表示中文字符,但每个字符的编码是不一样的,所以不能认为是兼容的。
  其实,oracle的字符系统很简单,主要由3部分组成:
  客户终端字符集nls_lang环境变量字符集数据库使用的字符集。其中,客户终端各种各样,比如windows下cmd,unix/linux下terminal/console,甚至如toad等工具也可以视为一个终端。我们使用windows cmd举例说明,cmd使用了gbk编码(好像不能修改)
  nls_lang环境变量决定了终端与服务器连接时,要不要转换字符集,如果nls_lang和服务器端数据库使用的编码不一样,那就要进行转码;如果设为一样,就不会发生转码。
  比如一个终端cmd查询一张数据库表,而其nls_lang设为american_america.zhs16gbk,而数据库为american_america.al32utf8,则数据库中的数据传到终端时,首先要进行utf8到gbk的转码。
  而转码又有两种情况,a.就是一个字符在两中编码里都有,就是具体的码文不一样;b.转码时发现一个字符在另一种编码里没有,则直接用替代字符代替,而这一般就是‘?’字符了。这里要注意的是,我们一般所说的乱码有2种,一种就是b所说的‘?’,而另一种出现的奇奇怪怪的字符就是由于nls_lang设置等转码原因造成的。
  而数据库使用的字符集就是数据库实际使用的字符集。
  现举例说明:
  先创建Oracle数据库utf8使用al32utf8编码,使用cmd(gbk),分以下几种情况:
  a.    设nls_lang也为zhs16gbk,则insert中文时,服务器发现客户端nls_lang为gbk,则要转换映射。输入“我靠”;因为终端为cmd,所以输入的字符集都是gbk编码的,假设“我靠”的gbk编码为0xaabb,则0xaabb要映射为utf8(假设“我靠”的utf8编码为0xccddee)编码,存入数据库,则数据中保存了utf8编码的“我靠“。然后,再使用cmd进行select查询,数据库发现nls_lang为zhs16gbk,则把”我靠“从utf8码0xccddee转为gbk的0xaabb,然后正常在cmd中显示”我靠“两字。
  b.    设nls_lang也为al32utf8,则从cmd输入“我靠“时,服务器发现客服端nls_lang为utf8,则它不进行转换,直接存0xaabb进数据库;当select时,因为也不要转换,所以直接发0xaabb给终端,而0xaabb在终端cmd(gbk)里显示为“我靠”,也能正常显示。但要注意的是,这时对服务器来说,存在数据库里的内容其实是不正确的,不是正确的“我靠”的utf8编码;而只是存了个“我靠“的gbk编码。
  c.    先设nls_lang为utf8,输入完“我靠“后,改nls_lang为gbk,再做select,发现显示为乱码了。这种就是前面说的因为转码问题造成的乱码。因为数据库一开始存的是”我靠“的gbk码0xaabb;然后做select时,因为使用了改为gbk的nls_lang,则数据库要进行转码了,就是要把utf8中的0xaabb转为gbk码,假设utf8中0xaabb表示的是”B??“,那就是要把”B??“转为gbk码,然后在cmd中用gbk显示了”B??“乱码。
  然后,我们再次创建一个us7ascii码的数据库chr。
  d. 设nls_lang为american_america.us7ascii,输入“我靠“,然后再select,发现竟然能正常显示中文。这是因为由于数据库编码和nls_lang编码一样,所以不进行转码,直接把”我靠“的gbk码0xaabb输入了数据库。而select时,由于也不要转码,所以又直接把0xaabb传了回来,在cmd(gbk)中就显示了”我靠“。
  e. 延续d的情况,再设nls_lang为american_america.zhs16gbk,再做select,发现返回NR??,这种情况还是前面所说的转码造成的乱码,因为gbk是兼容ascii的,只是这里还是进行了错误的转码,因为ascii中的0xaabb转码成gbk显示,就是NR??。
  f. 设nls_lang为american_america.zhs16gbk,输入“我靠“,然后再select,发现返回两个??;这是因为”我靠“的gbk编码要转码到uscii时,因为uscii里没有”我靠“两个字符的编码,所以不兼容,直接用两个?代替;而select时,因为ascii里的?和gbk里的?是兼容的,所以转码后,cmd里也显示两个?。
  综上所述,可以得出如下规范:
  1.        数据库字符应该至少使用gbk,最好是utf8字符集,这样至少基本上不会出现全问号乱码的情况,因为不会出现找不到对应字符,而采用?等字符代替的情况。情况f其实就是这样。
  2.        应该设置nls_lang和终端使用一样的编码,这样数据库也能正确知道终端使用的编码,就能正确得转码,就不大会把错误的编码存进数据库,情况b,c,d,e就是设错了nls_lang才造成了问题。这里面,还有种情况,就是不设nls_lang时,好像oracle默认会把它当作和终端编码一样(需要确认)。
  3.        尽量使得3个编码都一样,这样就能避免编码转换造成的性能损失。
  其实,不仅oracle,别的一些数据库,甚至是一些编程工具,如jsp/servlet等都有类似的编码体制,基本上都是终端(如jsp里为编辑器),环境变量(jsp里为pageencoding指令),服务器端编码(jsp为浏览器等);再比如oracle做imp时,终端编码就为dmp包中的编码(不一定为原数据库编码,因为有可能它在exp时,已经转过码了),环境变量编码还是nls_lang,而服务端就是要实行imp的数据库的编码了。
  有兴趣的话,大家可以研究下mysql的字符集机制,它本质上还是使用三位一体的编码机制,但划分的更细。
  From:http://tanrenjie.spaces.live.com/blog/cns!599006622366184E!343.entry


运维网声明 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-600840-1-1.html 上篇帖子: Oracle数据库SGA_MAX_SIZE参数调整 下篇帖子: Windows下oracle RMAN备份脚本
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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