全面认识Oracle数据库字符集


    什么是Oracle字符集
    Oracle字符集是一个字节数据解释的符号 集中,有大小之分,有 彼此的 包容关系 。
    Oracle 支撑国家语言的体系 构造同意你 使用当地化语言来存储, 解决,检索数据 。它使数据库工具, 舛误 信息,排序 秩序,日期, 工夫,货币,数字和日历自动适 该当地化语言和平台 。
    影响oracle数据库字符集最主要的参数是NLS_LANG参数 。它的 格局如下:
    NLS_LANG = language_territory.charset
    它有三个构成 部分(语言、地区和字符集),每个成分操纵了NLS子集的 特点 。其中:
    Language指定服务器 信息的语言,territory指定服务器的日期和数字 格局,charset指定字符集 。如:AMERICAN _ AMERICA. ZHS16GBK 。
    从NLS_LANG的构成我们 可以看出,真正影响数据库字符集的其实是第三 部分 。所以两个数据库中间的字符集 惟独第三 部分一样就 可以 彼此导入导出数据,前面影响的只不过 揭示信息是中文还是英文 。
    如何 查问Oracle的字符集
    众多人都碰到过由于字符集不同而使数据导入失败的状况 。这 波及三方面的字符集,一是Oracel server端的字符集,二是oracle client端的字符集;三是dmp文件的字符集 。在做数据导入的时候,需求这三个字符集都 统一 威力正确导入 。
    1、 查问Oracle Server端的字符集
    有众多种 步骤 可以查出oracle server端的字符集, 比较直观的 查问 步骤是以下这种:
    SQL>select userenv(‘language’) from dual;
    后果 类似如下:AMERICAN _ AMERICA. ZHS16GBK.
    2、如何 查问dmp文件的字符集
    用Oracle的exp工具导出的dmp文件也包括了字符集信息,dmp文件的第2和第3个字节记录了dmp文件的字符集 。假如dmp文件不大, 比方惟独几M或几十M, 可以用UltraEdit 打开(16进制 模式),看第2第3个字节的内容,如0354, 而后用以下SQL查出它对应的字符集:
    SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;  ZHS16GBK
    假如dmp文件很大, 比方有2G以上(这也是最常见的状况),用文本编辑器 打开很慢或者 彻底打不开, 可以用以下命令(在unix主机上):
    cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6
    而后用上述SQL也 可以得到它对应的字符集 。
    3、 查问Oracle client端的字符集
    这个 比较 方便 。在Windows平台下,便是注册表里面相应OracleHome的NLS_LANG.还 可以在Dos窗口里面自己设置, 比方:
    set nls_lang=AMERICAN_AMERICA.ZHS16GBK
    这样就只影响这个窗口里面的环境变量 。在Unix平台下,便是环境变量NLS_LANG.
    $echo $NLS_LANG AMERICAN_AMERICA.ZHS16GBK
    假如 审查的 后果发现Server端与Client端字符集不 统一,请统一 批改为同Server端 雷同的字符集 。
    批改Oracle的字符集
    上文说过,oracle的字符集有 彼此的 包容关系 。
    如us7ascii便是zhs16gbk的子集,从us7ascii到zhs16gbk不会有数据解释上的问题,不会有数据 迷失 。在全部的字符集中utf8应该是最大,由于它基于unicode,双字节 保留字符(也 因此在存储空间上占用更多) 。
    一旦数据库 缔造后,数据库的字符集 实际上讲是不能转变的 。 因此,在设计和安装之初考量 使用哪一种字符集非常主要 。依据Oracle的官方 注明,字符集的转换是从子集到超集受 支撑,反之不行 。假如两种字符集中间 根本没有子集和超集的关系,那么字符集的转换是不受oracle 支撑的 。对数据库server而言, 舛误的 批改字符集将会招致众多不可测的 后果,可能会严峻影响数据库的 畸形运行,所以在 批改之前 定然要确认两种字符集是不是存在子集和超集的关系 。普通来说,除非万不得已,我们不 提议 批改oracle数据库server端的字符集 。特殊 注明,我们最常用的两种字符集ZHS16GBK和ZHS16CGB231280中间不存在子集和超集关系, 因此 实际上讲这两种字符集中间的 彼此转换不受 支撑 。
    批改Server端字符集(不 提议 使用):
    在Oracle 8之前, 可以用直接 批改数据字典表props$来转变数据库的字符集 。但Oracle8之后,至少有三张系统表记录了数据库字符集的信息,只改props$表并不 彻底,可能引起严峻的 后果 。正确的 批改 步骤如下:
    $sqlplus /nolog SQL>conn / as sysdba;
    若此时数据库服务器已启动,则先执行SHUTDOWN IMMEDIATE命令关闭数据库服务器, 而后执行以下命令:
    SQL>STARTUP MOUNT;
    SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
    SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
    SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
    SQL>ALTER DATABASE OPEN;
    SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
    SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
    SQL>SHUTDOWN IMMEDIATE; SQL>STARTUP
    批改dmp文件字符集:
    上文说过,dmp文件的第2第3字节记录了字符集信息, 因此直接 批改dmp文件的第2第3字节的内容就 可以‘骗’过oracle的 审查 。这样做 实际上也仅是从子集到超集 可以 批改,但众多状况下在没有子集和超集关系的状况下也 可以 批改,我们常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK 根本都 可以改 。由于改的只不过dmp文件,所以影响不大 。
    具体的 批改 步骤 比较多,最 方便的便是直接用UltraEdit 批改dmp文件的第2和第3个字节 。 比方想将dmp文件的字符集改为ZHS16GBK, 可以用以下SQL查出该种字符集对应的16进制代码:
    SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual; 0354
    而后将dmp文件的2、3字节 批改为0354即可 。
    假如dmp文件很大,用ue 无奈 打开,就需求用程序的 步骤了 。网上有人用java存储过程写了转换的程序(用java存储过程的 好处是通用性教好,缺陷是 比较麻烦) 。我在Windows下测试通过 。但要求Oracle数据库 定然要安装JVM选项 。