Oracle数据库字符集概念的总结

Oracle数据库字符集概念的总结

此部分整理了oracle数据库中字符集概念相关的知识总结,oracle中字符集的设置是非常重要的一部分,应当在安装的时候就必须明确。如果设置出现问题或者更改编码不正确会导致乱码的出现。在理解oracle字符集之前需要先了解字符集的相关知识。

字符集相关知识(字符、字节、编码)

GBK,ISO-8859-1(ASCII),GB2312的本质区别
编码有几种 ,计算机最初是在美国等国家发明的 所以表示字符只有简单的几个字母只要对字母进行编码就好 我们标准码 iso-8859-1 这就是一个标准。但是后来计算机普及了 于是就中国要使用计算机了 但是机器不认得中文,于是就有了国际码。 gbk gb2312都是这类。两个其实一个,一个是标准(发布的代号),一个是简称。后来多了个阿拉伯语、日语、韩语…所以就出来统一编码UniCode

ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。此字符集主要支持欧洲使用的语言。

GBK: 汉字国标扩展码,基本上采用了原来GB2312-80所有的汉字及码位,并涵盖了原Unicode中所有的汉字20902,总共收录了883个符号, 21003个汉字及提供了1894个造字码位。Windows 95系统就是以GBK为内码,又由于GBK同时也涵盖了Unicode所有CJK汉字,所以也可以和Unicode做一一对应。

GBK就是在保存你的帖子的时候,一个汉字占用两个字节。外国人看会出现乱码,此为我中华为自己汉字编码而形成之解决方案。
UTF8就是在保存你的帖子的时候,一个汉字占用3个字节。但是外国人看的话不会乱码,此为西人为了解决多字节字符而形成之解决方案。

ASCII(ISO-8859-1)是鼻祖,最简单的方式,字节高位为0
GB2312、GBK、GB18030,这几个是中文编码方式,并向下兼容。GB2312包含7000多个汉字和字符,GBK包含21000多个,GB18030更厉害,到了27000多个。他们都是用2个字节来表示一个汉字。跟ascii是怎么区分的呢?如果高字节的高位为1(也就是高字节大于127),就表示是汉字,低字节并无明显特征。

Oracle中的字符编码

ORACLE数据库有国家字符集(national character set)与数据库字符集(database character set)之分。两者都是在创建数据库时需要设置的。国家字符集主要是用于NCHAR、NVARCHAR、NCLOB类型的字段数据,而数据库字符集使用很广泛,它用于:CHAR、VARCHAR、CLOB、LONG类型的字段数据;

ORACLE的字符集名字一般由以下部分组成:语言或区域、表示一个字符的比特位数、标准字符集名称(可选项,S或C,表示服务器或客户端)。ORACLE字符集UTF8与UTFE不符合此规定,其它基本都是这种格式。NLS_LANG = < Language> _< Territory>.< Clients Characterset>

NLS_ LANG参数由以下部分组成:

NLS_ LANG =< Language>_ < Territory>.< Clients Characterset>

NLS_ LANG各部分含义如下:

LANGUAGE指定:

-Oracle消息使用的语言

-日期中月份和日显示

TERRITORY指定

-货币和数字格式

-地区和计算星期及日期的习惯

Language_ Territory.Clientcharacterset
其中,Language显示oracle消息,校验,日期命名,Territory指定默认日期、数字、货币等格式Clientcharacterset指定客户端将使用的字符集。比如NLS_ LANG=AMERICAN_AMERICA.US7ASCII。AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集。在解决客户端和服务端编码不一致问题导致的乱码时,Language和Territory可以不一致,但是Clientcharacterset必须一致。

  1. 查看数据库服务端字符编码

     SQL> col PARAMETER for a25;
     SQL> col VALUE for a30;
     SQL> select * from nls_database_parameters; //查看服务端
     
     PARAMETER                 VALUE
     ------------------------- ------------------------------
     NLS_RDBMS_VERSION         19.0.0.0.0
     NLS_NCHAR_CONV_EXCP       FALSE
     NLS_LENGTH_SEMANTICS      BYTE
     NLS_COMP                  BINARY
     NLS_DUAL_CURRENCY         $
     NLS_TIMESTAMP_TZ_FORMAT   DD-MON-RR HH.MI.SSXFF AM TZR
     NLS_TIME_TZ_FORMAT        HH.MI.SSXFF AM TZR
     NLS_TIMESTAMP_FORMAT      DD-MON-RR HH.MI.SSXFF AM
     NLS_TIME_FORMAT           HH.MI.SSXFF AM
     NLS_SORT                  BINARY
     NLS_DATE_LANGUAGE         AMERICAN
     
     PARAMETER                 VALUE
     ------------------------- ------------------------------
     NLS_DATE_FORMAT           DD-MON-RR
     NLS_CALENDAR              GREGORIAN
     NLS_NUMERIC_CHARACTERS    .,
     NLS_NCHAR_CHARACTERSET    AL16UTF16
     NLS_CHARACTERSET          ZHS16GBK    //这里代表数据库中存储数据库的字符集
     NLS_ISO_CURRENCY          AMERICA
     NLS_CURRENCY              $
     NLS_TERRITORY             AMERICA
     NLS_LANGUAGE              AMERICAN
     
     20 rows selected.
    
  2. 查看数据库客户端的编码

    USERENV、 V$NLS_PARAMETERS表示当前字符集环境。如果你在客户端执行,则表示客户端字符集环境。

     SQL> SELECT * FROM V$NLS_PARAMETERS;
     
     PARAMETER                 VALUE                              CON_ID
     ------------------------- ------------------------------ ----------
     NLS_LANGUAGE              AMERICAN                                0
     NLS_TERRITORY             AMERICA                                 0
     NLS_CURRENCY              $                                       0
     NLS_ISO_CURRENCY          AMERICA                                 0
     NLS_NUMERIC_CHARACTERS    .,                                      0
     NLS_CALENDAR              GREGORIAN                               0
     NLS_DATE_FORMAT           DD-MON-RR                               0
     NLS_DATE_LANGUAGE         AMERICAN                                0
     NLS_CHARACTERSET          ZHS16GBK                                0
     NLS_SORT                  BINARY                                  0
     NLS_TIME_FORMAT           HH.MI.SSXFF AM                          0
     
     PARAMETER                 VALUE                              CON_ID
     ------------------------- ------------------------------ ----------
     NLS_TIMESTAMP_FORMAT      DD-MON-RR HH.MI.SSXFF AM                0
     NLS_TIME_TZ_FORMAT        HH.MI.SSXFF AM TZR                      0
     NLS_TIMESTAMP_TZ_FORMAT   DD-MON-RR HH.MI.SSXFF AM TZR            0
     NLS_DUAL_CURRENCY         $                                       0
     NLS_NCHAR_CHARACTERSET    AL16UTF16                               0
     NLS_COMP                  BINARY                                  0
     NLS_LENGTH_SEMANTICS      BYTE                                    0
     NLS_NCHAR_CONV_EXCP       FALSE                                   0
     
     19 rows selected.
    
    
     SQL> SELECT USERENV('language') FROM DUAL;
     
     USERENV('LANGUAGE')
     ----------------------------------------------------
     AMERICAN_AMERICA.ZHS16GBK
    
  3. 查看数据库会话字符集环境

    它来源于v n l s p a r a m e t e r s , 表 示 会 话 自 己 的 设 置 , 可 能 是 会 话 的 环 境 变 量 或 者 是 A L T E R S E S S I O N 完 成 , 如 果 会 话 没 有 特 殊 的 设 置 , 将 与 V nls_ parameters,表示会话自己的设置,可能是会话的环境变量或者是ALTER SESSION完成,如果会话没有特殊的设置,将与 V nlsparametersALTERSESSIONVNLS_PARAMETERS一致。

     SQL> SELECT * FROM NLS_SESSION_PARAMETERS;
     
     PARAMETER                 VALUE
     ------------------------- ------------------------------
     NLS_LANGUAGE              AMERICAN
     NLS_TERRITORY             AMERICA
     NLS_CURRENCY              $
     NLS_ISO_CURRENCY          AMERICA
     NLS_NUMERIC_CHARACTERS    .,
     NLS_CALENDAR              GREGORIAN
     NLS_DATE_FORMAT           DD-MON-RR
     NLS_DATE_LANGUAGE         AMERICAN
     NLS_SORT                  BINARY
     NLS_TIME_FORMAT           HH.MI.SSXFF AM
     NLS_TIMESTAMP_FORMAT      DD-MON-RR HH.MI.SSXFF AM
     
     PARAMETER                 VALUE
     ------------------------- ------------------------------
     NLS_TIME_TZ_FORMAT        HH.MI.SSXFF AM TZR
     NLS_TIMESTAMP_TZ_FORMAT   DD-MON-RR HH.MI.SSXFF AM TZR
     NLS_DUAL_CURRENCY         $
     NLS_COMP                  BINARY
     NLS_LENGTH_SEMANTICS      BYTE
     NLS_NCHAR_CONV_EXCP       FALSE
     
     17 rows selected.
    
  4. 查看客户端字符集(NLS_LANG) 的方法

    如果系统是LINUX或UNIX平台,则也可以通过下面命令查看(前提是必须设置了NLS_LANG,否则查出来的是空值)

     [oracle@oracle1 ~]$ env | grep NLS_LANG
     NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
     [oracle@oracle1 ~]$ echo $NLS_LANG
     AMERICAN_AMERICA.ZHS16GBK
    

如何选择合适的数据库字符集

  1. 数据库需要存储的数据类型是字符集选择的首要考虑目标

    对于只存储英文信息的数据库等来说,一般采用US7ASCII或WE8ISO8859P1等单字节的字符集就比较合适,在性能和空间上也是最优,同样,存储了中文信息的数据库,如果采用单字节的字符集,也是不合适的。在这种情况下,数据库的字符集虽然是US7ASCII或WE8ISO8859P1 编码,但里面存储的数据编码实际上却是另外的编码格式,这种不一致的情况很容易引起问题,建议不要这样使用。ORACLE提供了很多种类的字符集供客户选 择,就是要满足各种文字不同的编码需要。

  2. 字符集的选择需要优先考虑应用程序的需要

    目前出于国际化的需要,软件需要可以对不同的语言文字进行处理,尤其一个系统中需要容纳多种语言文字的时候,一般都会采用Unicode这样的通用解决方案,即使会有一些空间和运行效率的损失也是值得的。此时数据库字符集建议可以采用AL32UTF8 或UTF8编码,一种比较理想的模式就是由程序负责编码格式的转换,而数据库只提供一个透明的数据存储,
    客户在应用程序中输入数据,此时数据的编码格式是由客户操作系统的区域及语言设置决定的,如在简体中文XP的环境下,输入的中文编码属于GBK编码。在客 户输入结束后,程序首先判断客户的本地环境,并把编码转换成UNICODE,并通过NET传送到服务器端。由于客户端与服务器数据库的字符集均为UTF8 格式,ORACLE在传送过程中不会进行字符转换,直接把数据按UTF8格式存储到数据库中。查询时是一个反向的过程,应用程序从数据库中取出UTF8编 码的数据,再由应用程序根据客户的本地环境,把UTF8编码的数据转换成客户本地的编码格式,最后把结果数据显示给客户。此方案的关键在于应用程序要能很 好的支持UNICODE编码,编码的转换由应用程序来负责,数据库只是提供了一个数据存储功能。
    对于部分程序来说,由于对UNICODE支持不够,没有提供编码的转换功能,则可以使用ORACLE提供的字符集转换功能来实现同样的目的。客户在应用程 序中输入数据,此时数据的编码格式是由客户操作系统的区域及语言设置决定的,如在简体中文XP的环境下,输入的中文编码属于GBK编码。在客户输入结束 后,程序直接把数据并通过NET传送到服务器端。由于客户端与服务器数据库的字符集不一致,因此ORACLE会把客户端的编码转换成UTF8格式,再把数 据按UTF8格式存储到数据库中。这种方案的优点就是程序可以不用支持UNICODE,由ORACLE数据库自动进行转换。由于数据库的字符集为 UTF8,是其它字符集的超集,因此在转换过程中不会发生数据丢失的情况。对于英文的字符符号,在UTF8中使用单字节存储,转换的工作量很小,可以忽 略,而对于一些亚洲字符集,在UTF8中一般需要两到三个字节存储,需要的数据库空间增加,而且转换的工作量也相对大一些,性能会有一些损失。

数据库出现乱码的问题

数据库出现乱码的问题主要和客户的本地化环境,客户端NLS_LANG设置,服务器端的数据库字符集设置这三者有关,如果它们的设置不一致或者某个设置错误,就会很容易出现乱码,下面我们简要介绍以下几种情况:

  1. 数据库字符集设置不当引起的乱码

    例如:一个存储简体中文字符的数据库,它的字符集选用了US7ASCII,当它的客户端NLS_ LANG也选用US7ASCII时,这个系统单独使用是没 有问题的,因为两者设置一致,因此ORACLE不会进行字符集的转换,客户输入的GBK码被直接在数据库中存储起来,当查询数据时,实际客户端取出来的数 据也是GBK的编码,因此显示也是正常的。但当其它的系统需要从这个数据库取数据,或者它的数据要EXP出来,IMP到其它数据库时,问题就会开始出现 了。其它系统的字符集一般是ZHS16GBK,或者其它系统客户端的NLS_LANG设置为ZHS16GBK,此时必然会产生字符集的转换。虽然数据库字 符集设置为US7ASCII,但我们知道,实际存储的数据编码是ZHS16GBK的。可惜ORACLE不会知道,它会把存储的ZHS16GBK编码数据当 作US7ASCII编码的数据,按照US7ASCII转换成ZHS16GBK的转换算法进行转换,可以想象,这种情况下,乱码的产生是必然的。

  2. 数据库字符集与客户端NLS_LANG设置不同引起的乱码

    例如:对于一个需要存储简体文信息的数据库来说,它的字符集设置和客户端NLS_LANG设置一般可以使用ZHS16GBK编码。但是如果数据库字符集选 用了UTF8的话,也是可以的,因为ZHS16GBK编码属于UTF8的子集。ORACLE在数据库与客户端进行数据交换时自动进行编码的转换,在数据库 中实际存储的也是UTF8编码的数据。此时其它数据库和此数据库也可以正常的进行数据交换,因为ORACLE会自动进行数据的转换。在实际使用中,遇到过 繁体XP的字符集ZHT16MSWIN950转换成AL32UTF8 字符集时,一些特殊的字符和个别冷僻的汉字会变成乱码。后来证实是XP需要安装一个字库补丁软件,最后顺利解决此问题。

  3. 客户端NLS_LANG与本地化环境不同引起的乱码

    一般情况下,客户端NLS_ LANG与本地化环境采用了不同的字符集会出现乱码,除非本地化环境的字符集是客户端NLS_ LANG设置字符集的子集。如果 把客户端NLS_LANG设置为UTF8就属于这种情况,由于目前还没有可以直接使用UNICODE字符集的操作系统,因此客户本地化环境使用的字符集只 能是某种语言支持的字符集,它属于UTF8的子集。下面我们就着重讨论这种情况。
    虽然目前WINDOWS的内核是支持UNICODE的,但是WINDOWS并不支持直接显示UNICODE编码的字符,而且它并不知道目前的字符采用了何 种字符集,所以默认情况下,它使用缺省的代码页来解释字符。因此,对于其它类型的编码,需要先进行转换,变成系统目前的缺省代码页支持的字符集才能正常使 用。
    WINDOWS中的缺省代码页是由控制面板设置中的语言及区域的选择所决定的,属于客户本地化的环境设置。简体中文WINDOWS的 字符编码 就 是GBK,它的缺省代码页是936。对于其它非WINDOWS的操作系统,我们可以把它们目前缺省使用的字符集作为用户的本地化环境设置。另外,我们使用 的大部分工具,如写字板,SQL*PLUS等,它们没有提供编码转换功能,因此在客户端直接输入或查询数据往往都会遇到乱码的问题,必须由应用程序或一些 工具去做编码的转换,才能保证正常的使用。

结尾

至此,oracle数据库字符集的相关总结暂时梳理到此环节,后续再接触相关的话会记录在后面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值