zoukankan      html  css  js  c++  java
  • oracle字符集与乱码(转)

    作者:hcling97    http://blog.sina.com.cn/hcling97

    2013年5月15日

    转载请注明出处 

    字符集问题一直叫人头疼,究其原因还是不能完全明白其运作原理。

    在整个运行环节中,字符集在3个环节中发挥作用:

    1.软件在操作系统上运作时的对用户的显示,此时采用操作系统定义的字符集进行显示。我们在系统I/O编程的时候经常要指定字符集,C#中的Text.Encoding=Encoding.Default实际上就是告诉编译器,文本使用系统定义的默认字符集进行编码。sqlplus也是运行在操作系统上的软件,当然要使用系统所指定的字符集对外显示内容。

    2.数据向oracle服务端传送前的通告。也就是sqlplus告诉服务器现在使用的字符集是什么。

    3.数据流到达服务器后,按照服务器所使用的字符集自动翻译客户端的数据,然后存储进系统。

    在客户端sqlplus和服务端传送数据,数据会按照服务端字符集进行翻译,这个过程是自动完成的不需要人工干预。任何时候,oracle服务端总是按照自己的字符集设置来存取数据,客户端要想正确显示从服务端读取到的数据,也需要按照本地的字符集设置进行翻译,这个过程也是自动的。

    服务器端需要采用合适的字符集进行数据存储,这个很容易理解,ASCII字符集没办法用来存储中文汉字,因为它根本没有描述汉字所需要的编码空间。

    问题常常存在于客户端与服务端通讯的过程中,sqlplus作为运行在操作系统上的软件,无论是显示还是通讯,必然使用操作系统所使用的字符集设置。无论sqlplus设置的字符集,作用只有一个,那就是通告服务器端,为相互之间的字符集翻译做准备。

    客户端的字符集设置是在NLS_LANG环境变量中设置的,客户读端的字符集可以和oracle客户端设置得不一样(本来人家就是自动翻译的),但是客户端字符集一定要和操作系统设置的字符集相匹配!

    考虑一下,sqlplus使用的是操作系统的字符集定义在显示和发送数据(架设是TYPE_A),却告诉oracle服务器自己使用的字符集是TYPE_B,oracle服务器会怎么办?它会将客户端发送过来的TYPE_A数据当作TYPE_B字符集格式用自身的TYPE_C字符集进行翻译,然后再存储进系统,这就形成了乱码。反向的过程类似,Oracle服务器发出的数据格式没有疑问是TYPE_C,但是客户端软件认为自己使用的编码是TYPE_B并进行了翻译,交给操作系统用TYPE_A字符集总的字符/编码映射关系进行翻译显示,最终导致了无法正确显示。

    一个现实的例子:RHEL5.8操作系统安装了中文支持包以后,所有的语言环境都被设置成了zh_CN.UTF-8(通过LANG环境变量可知,也可通过locale命令查到),数据库服务器所使用的字符集为ZHS16GBK,很明显,这两者不一致,sqlplus在没有设置NLS_LANG环境变量时,与数据库保持一致,此时,从服务端取得的数据不需要翻译,被sqlplus读取并用zh_CN.UTF-8的字符/编码映射关系进行翻译显示,所有的汉字变成了“?”。

    根据上面的分析,要解决这一问题,要把sqlplus的字符集设置成和操作系统一致即可,操作系统设置的是zh_CN.UTF-8,但在.bash_profile里面还不能直接将NLS_LANG设置为zh_CN.UTF-8,因为这个zh_CN.UTF8是字符集的locale ID而不是字符集的名称,真正的名称叫SIMPLIFIED CHINESE_CHINA.AL32UTF8,如果设置成zh_CN.UTF8,oracle会报ORA-12705: Cannot access NLS data files or invalid environment specified错误。在.bash_profile里面加入NLS_LANG="SIMPLIFIED CHINESE_CHINA.AL32UTF8"; export NLS_LANG问题就解决了。

    下表是locale ID与字符集名称的对应关系:

    Language

    Locale ID

    NLS_LANG

    English (American)

    en_US.UTF-8

    AMERICAN_AMERICA.AL32UTF8

    English (American)

    en_US.ISO-8859-1

    AMERICAN_AMERICA.WE8ISO8859P1

    English (American)

    en_US.ISO-8859-15

    AMERICAN_AMERICA.WE8ISO8859P15

    English (Australian)

    en_AU.UTF-8

    ENGLISH_AUSTRALIA.AL32UTF8

    English (Australian)

    en_AU.ISO-8859-1

    ENGLISH_AUSTRALIA.WE8ISO8859P1

    English (Australian)

    en_AU.ISO-8859-15

    ENGLISH_AUSTRALIA.WE8ISO8859P15

    English (British)

    en_GB.UTF-8

    ENGLISH_UNITED KINGDOM.AL32UTF8

    English (British)

    en_GB.ISO-8859-1

    ENGLISH_UNITED KINGDOM.WE8ISO8859P1

    English (British)

    en_GB.ISO-8859-15

    ENGLISH_UNITED KINGDOM.WE8ISO8859P15

    English (Ireland)

    en_IE.UTF-8

    ENGLISH_IRELAND.AL32UTF8

    English (Ireland)

    en_IE.ISO-8859-1

    ENGLISH_IRELAND.WE8ISO8859P1

    English (Ireland)

    en_IE.ISO-8859-15

    ENGLISH_IRELAND.WE8ISO8859P15

    German

    de_DE.UTF-8

    GERMAN_GERMANY.AL32UTF8

    German

    de_DE.ISO-8859-1

    GERMAN_GERMANY.WE8ISO8859P1

    German

    de_DE.ISO-8859-15

    GERMAN_GERMANY.WE8ISO8859P15

    French

    fr_FR.UTF-8

    FRENCH_FRANCE.AL32UTF8

    French

    fr_FR.ISO-8859-1

    FRENCH_FRANCE.WE8ISO8859P1

    French

    fr_FR.ISO-8859-15

    FRENCH_FRANCE.WE8ISO8859P15

    Italian

    it_IT.UTF-8

    ITALIAN_ITALY.AL32UTF8

    Italian

    it_IT.ISO-8859-1

    ITALIAN_ITALY.WE8ISO8859P1

    Italian

    it_IT.ISO-8859-15

    ITALIAN_ITALY.WE8ISO8859P15

    Spanish

    es_ES.UTF-8

    SPANISH_SPAIN.AL32UTF8

    Spanish

    es_ES.ISO-8859-1

    SPANISH_SPAIN.WE8ISO8859P1

    Spanish

    es_ES.ISO-8859-15

    SPANISH_SPAIN.WE8ISO8859P15

    Spanish (Mexico)

    es_MX.UTF-8

    MEXICAN SPANISH_MEXICO.AL32UTF8

    Spanish (Mexico)

    es_MX.ISO-8859-1

    MEXICAN SPANISH_MEXICO.WE8ISO8859P1

    Spanish (Mexico)

    es_MX.ISO-8859-15

    MEXICAN SPANISH_MEXICO.WE8ISO8859P15

    Portuguese (Brazilian)

    pt_BR.UTF-8

    BRAZILIAN PORTUGUESE_BRAZIL.AL32UTF8

    Portuguese (Brazilian)

    pt_BR.ISO-8859-1

    BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1

    Portuguese (Brazilian)

    pt_BR.ISO-8859-15

    BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P15

    Japanese

    ja_JP.EUC-JP

    JAPANESE_JAPAN.JA16EUC

    Japanese

    ja_JP.UTF-8

    JAPANESE_JAPAN.AL32UTF8

    Korean

    ko_KR.EUC-KR

    KOREAN_KOREA.KO16KSC5601

    Korean

    ko_KR.UTF-8

    KOREAN_KOREA.AL32UTF8

    Chinese (simplified)

    zh_CN.GB18030

    SIMPLIFIED CHINESE_CHINA.ZHS32GB18030

    Chinese (simplified)

    zh_CN.UTF-8

    SIMPLIFIED CHINESE_CHINA.AL32UTF8

    Chinese (traditional)

    zh_TW.BIG5

    TRADITIONAL CHINESE_TAIWAN.ZHT16BIG5

    Chinese (traditional)

    zh_TW.UTF-8

    TRADITIONAL CHINESE_TAIWAN

    步骤可以归纳为:1.找到操作系统使用的字符集,并按上表找到对应的字符集名称。2.修改客户端软件的字符集NLS_LANG环境变量设置。

    不同平台的一些细节:

    Windows( 如简体系统为:ZHS16GBK,繁体系统为:MSWIN950 )

    1、设置session变量


    # 常用中文字符集
    set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

    # 常用unicode字符集
    set NLS_LANG=american_america.AL32UTF8

    2、可以通过修改注册表键值永久设置
    HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/HOMExx/NLS_LANG

    3、设置环境变量
    NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
    NLS_LANG=american_america.AL32UTF8


    Unix/Linus:

    1、设置session变量

    # 常用unicode字符集
    export NLS_LANG=american_america.AL32UTF8

    # 常用中文字符集
    export NLS_LANG="Simplified Chinese_china".ZHS16GBK

    3、设置环境变量
    可以编辑 bash_profile文件进行永久设置
    # vi .bash_profile
    NLS_LANG="Simplified Chinese_china".ZHS16GBK
    export NLS_LANG
    # 使 bash_profile 设置生效
    source .bash_profile

    其他:

    1、查看sqlplus客户编码:
    $ echo $NLS_LANG

    2、查看系统编码:
    $ locale

    3、查看数据库字符集,执行如下查询:
    select userenv('language') from dual;

  • 相关阅读:
    LeetCode153 Find Minimum in Rotated Sorted Array. LeetCode162 Find Peak Element
    LeetCode208 Implement Trie (Prefix Tree). LeetCode211 Add and Search Word
    LeetCode172 Factorial Trailing Zeroes. LeetCode258 Add Digits. LeetCode268 Missing Number
    LeetCode191 Number of 1 Bits. LeetCode231 Power of Two. LeetCode342 Power of Four
    LeetCode225 Implement Stack using Queues
    LeetCode150 Evaluate Reverse Polish Notation
    LeetCode125 Valid Palindrome
    LeetCode128 Longest Consecutive Sequence
    LeetCode124 Binary Tree Maximum Path Sum
    LeetCode123 Best Time to Buy and Sell Stock III
  • 原文地址:https://www.cnblogs.com/monkey6/p/12921731.html
Copyright © 2011-2022 走看看