且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Oracle字符集的简单图解,中文乱码解决

更新时间:2022-08-28 17:49:13

Oracle字符集的简单图解,中文乱码解决

经常碰到SQLPLUS展现乱码的问题,字符集和相关的定义都有说明但是很少有能把这些关系说的很简单易懂的。

在此之前我们需要搞清楚三个概念,操作系统字符集,客户端字符集,Oracle字符集:

操作系统字符集:对应的参数是LANG,这个参数应该是Oracle数据库的超集,如果操作系统不支持,那么我们的数据就会乱码。这里的操作系统指的是客户端的操作系统。服务器端的操作系统不会影响数据的存取。

数据库字符集:NLS_CHARACTERSET,可以在nls_database_parameters中查看当前数据库的字符集,安装数据库的时候选择,一般不修改,不过在新的字符集是现有字符集的严格超集的情况下可以改,其他情况下修改可能导致数据库异常。例如将UTF8字符集修改为AL32UTF8

关于子集超集的映射关系,见如下Oracle官网的文档的Binary Subset-Superset Pairs

http://docs.oracle.com/database/121/NLSPG/applocaledata.htm#NLSPG591 

客户端字符集:对应的参数是NLS_LANG,如果客户端未设置,此时则取的是安装时数据库的默认参数

为了帮助理解,我画了一张图如下,图中标红部分如果一致表示数据的存储方式一致,即如果LANG、NLS_LANG、NLS_CHARACTERSET的编码是一致的如UTF8,那么数据的传输过程中不会异常,字符乱码只是显示问题。

Oracle字符集的简单图解,中文乱码解决


1、操作系统字符集

linux下首先locale 查看字符集


[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@oddpc ~]$ locale  
  2. LANG=en_US.UTF-8  
  3. LC_CTYPE="en_US.UTF-8"  
  4. LC_NUMERIC="en_US.UTF-8"  
  5. LC_TIME="en_US.UTF-8"  
  6. LC_COLLATE="en_US.UTF-8"  
  7. LC_MONETARY="en_US.UTF-8"  
  8. LC_MESSAGES="en_US.UTF-8"  
  9. LC_PAPER="en_US.UTF-8"  
  10. LC_NAME="en_US.UTF-8"  
  11. LC_ADDRESS="en_US.UTF-8"  
  12. LC_TELEPHONE="en_US.UTF-8"  
  13. LC_MEASUREMENT="en_US.UTF-8"  
  14. LC_IDENTIFICATION="en_US.UTF-8"  
  15. LC_ALL=  
  16. [oracle@oddpc ~]$ echo $LANG  
  17. en_US.UTF-8  

2、该主机并未安装中文支持包,设置LANG后可以效果如下,显然无路如何调整NLS_LANG在这台机器上都无法展现中文



[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@evenpc ~]$ export LANG=zh_CN.utf8  
  2. [oracle@evenpc ~]$ date  
  3. 2016? 10? 13? ??? 15:17:01 CST  

3、安装中文支持包,使用yum -y groupinstall chinese-support 可以安装中文支持包,安装过程略过,安装完毕后可以正常显示中文



[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@oddpc ~]$ export LANG=zh_CN.utf8  
  2. [oracle@oddpc ~]$ date  
  3. 2016年 10月 13日 星期四 15:14:19 CST  


4、接下来就是展现测试,我安装了两个数据库实例PROD1和PROD5,PROD1 的字符集是WE8MSWIN1252,PROD5的字符集是AL32UTF8

默认情况下NLS_LANG是空的,此时NLS_LANG取默认安装时的值,PROD1是AMRICAN,PROD5是SIMPLIFIED CHINESE

[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@oddpc ~]$ echo $NLS_LANG  
  2. [oracle@oddpc ~]$   

[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. SQL> show parameter lang          
  2.   
  3. NAME                                 TYPE        VALUE  
  4. ------------------------------------ ----------- ------------------------------  
  5. nls_date_language                    string  
  6. nls_language                         string      AMERICAN  
[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. SQL> select sysdate from dual;  
  2.   
  3. SYSDATE  
  4. ---------  
  5. 13-OCT-16  



			


PROD5


[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. SQL> show parameter lang    
  2.   
  3. NAME                                 TYPE        VALUE  
  4. ------------------------------------ ----------- ------------------------------  
  5. nls_date_language                    string  
  6. nls_language                         string      SIMPLIFIED CHINESE  
[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. SQL> select sysdate from dual;  
  2.   
  3. SYSDATE  
  4. ----------  
  5. 13-10?-16  
5、PROD5 发生乱码,PROD1英文正常,设置下NLS_LANG参数


PROD1 的结果如下,可以看到提示信息已经变成中文,但是由于字符集非UTF8中文字符存入后将乱码


[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@oddpc ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.UTF8"  
  2. [oracle@oddpc ~]$ sqlplus / as sysdba  
  3.   
  4. SQL*Plus: Release 11.2.0.3.0 Production on 星期四 10月 13 15:42:46 2016  
  5.   
  6. Copyright (c) 1982, 2011, Oracle.  All rights reserved.  
  7.   
  8.   
  9. 连接到:   
  10. Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production  
  11. With the Partitioning, OLAP, Data Mining and Real Application Testing options<pre name="code" class="sql">SQL> show parameter lang  </pre <>
  12.   
  13. NAME                                 TYPE                              VALUE  
  14. ------------------------------------ --------------------------------- ------------------------------  
  15. nls_date_language                    string                            SIMPLIFIED CHINESE  
  16. nls_language                         string                            SIMPLIFIED CHINESE  
  17. SQL> show parameter db_name  
  18.   
  19. NAME                                 TYPE                              VALUE  
  20. ------------------------------------ --------------------------------- ------------------------------  
  21. db_name                              string                            PROD1  
  22. SQL> show parameter lang  
  23.   
  24. NAME                                 TYPE                              VALUE  
  25. ------------------------------------ --------------------------------- ------------------------------  
  26. nls_date_language                    string                            SIMPLIFIED CHINESE  
  27. nls_language                         string                            SIMPLIFIED CHINESE  
  28. SQL> select sysdate from dual;  
  29.   
  30. SYSDATE  
  31. ------------  
  32. 13-10? -16  
[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. SQL> select * from nls_database_parameters;  
  2.   
  3. PARAMETER                                VALUE  
  4. ---------------------------------------- ----------------------------------------  
  5. NLS_LANGUAGE                             AMERICAN  
  6. NLS_TERRITORY                            AMERICA  
  7. NLS_CURRENCY                             $  
  8. NLS_ISO_CURRENCY                         AMERICA  
  9. NLS_NUMERIC_CHARACTERS                   .,  
  10. NLS_CHARACTERSET                         WE8MSWIN1252  
  11. NLS_CALENDAR                             GREGORIAN  
  12. NLS_DATE_FORMAT                          DD-MON-RR  
  13. NLS_DATE_LANGUAGE                        AMERICAN  
  14. NLS_SORT                                 BINARY  
  15. NLS_TIME_FORMAT                          HH.MI.SSXFF AM  
  16.   
  17. PARAMETER                                VALUE  
  18. ---------------------------------------- ----------------------------------------  
  19. NLS_TIMESTAMP_FORMAT                     DD-MON-RR HH.MI.SSXFF AM  
  20. NLS_TIME_TZ_FORMAT                       HH.MI.SSXFF AM TZR  
  21. NLS_TIMESTAMP_TZ_FORMAT                  DD-MON-RR HH.MI.SSXFF AM TZR  
  22. NLS_DUAL_CURRENCY                        $  
  23. NLS_COMP                                 BINARY  
  24. NLS_LENGTH_SEMANTICS                     BYTE  
  25. NLS_NCHAR_CONV_EXCP                      FALSE  
  26. NLS_NCHAR_CHARACTERSET                   AL16UTF16  
  27. NLS_RDBMS_VERSION                        11.2.0.3.0  
  28.   
  29. 已选择20行。  




			



PROD5的结果如下,此时PROD5显示正常
[sql] view plain copy  Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决
  1. [oracle@oddpc ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.UTF8"  
  2. [oracle@oddpc ~]$ sqlplus / as sysdba  
  3. SQL*Plus: Release 11.2.0.3.0 Production on 星期四 10月 13 15:46:36 2016  
  4.   
  5. Copyright (c) 1982, 2011, Oracle.  All rights reserved.  
  6.   
  7.   
  8. 连接到:   
  9. Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production  
  10. With the Partitioning, OLAP, Data Mining and Real Application Testing options  
  11. SQL> show parameter db_name  
  12.   
  13. NAME                                 TYPE                              VALUE  
  14. ------------------------------------ --------------------------------- ------------------------------  
  15. db_name                              string                            PROD5  
  16. SQL> select sysdate from dual;  
  17.   
  18. SYSDATE  
  19. ------------  
  20. 13-10月-16  
  21.   
  22. SQL> show parameter lang  
  23.   
  24. NAME                                 TYPE                              VALUE  
  25. ------------------------------------ --------------------------------- ------------------------------  
  26. nls_date_language                    string                            SIMPLIFIED CHINESE  
  27. nls_language                         string                            SIMPLIFIED CHINESE<pre name</pre ="code" class="sql">SQL> select * from nls_database_parameters;  
  28.   
  29. PARAMETER                                VALUE  
  30. ---------------------------------------- ----------------------------------------  
  31. NLS_LANGUAGE                             AMERICAN  
  32. NLS_TERRITORY                            AMERICA  
  33. NLS_CURRENCY                             $  
  34. NLS_ISO_CURRENCY                         AMERICA  
  35. NLS_NUMERIC_CHARACTERS                   .,  
  36. NLS_CHARACTERSET                         AL32UTF8  
  37. NLS_CALENDAR                             GREGORIAN  
  38. NLS_DATE_FORMAT                          DD-MON-RR  
  39. NLS_DATE_LANGUAGE                        AMERICAN  
  40. NLS_SORT                                 BINARY  
  41. NLS_TIME_FORMAT                          HH.MI.SSXFF AM  
  42.   
  43. PARAMETER                                VALUE  
  44. ---------------------------------------- ----------------------------------------  
  45. NLS_TIMESTAMP_FORMAT                     DD-MON-RR HH.MI.SSXFF AM  
  46. NLS_TIME_TZ_FORMAT                       HH.MI.SSXFF AM TZR  
  47. NLS_TIMESTAMP_TZ_FORMAT                  DD-MON-RR HH.MI.SSXFF AM TZR  
  48. NLS_DUAL_CURRENCY                        $  
  49. NLS_COMP                                 BINARY  
  50. NLS_LENGTH_SEMANTICS                     BYTE  
  51. NLS_NCHAR_CONV_EXCP                      FALSE  
  52. NLS_NCHAR_CHARACTERSET                   AL16UTF16  
  53. NLS_RDBMS_VERSION                        11.2.0.3.0  
  54.   
  55. 已选择20行。  


总结:通过以上的实验可以看出,客户端展现是否乱码是由NLS_LANG决定,发生中文乱码的情况下,首先查看数据库的NLS_CHARACTERSET是否支持中文存储,如果不支持,无论如何设置均无法正常显示中文。Oracle官方文档上给出了各种语言的编码支持如下。




字符集问题的初步探讨(一)-字符集的基本知识


Oracle全球支持(即Globalization Support)允许我们使用本地语言和格式来存储和检索数据。通过全球支持,Oracle可以支持多种语言及字符集,得以展示数据库的强大魅力。

由于不同语言及字符集的共同存储存在设置上具有一定的复杂性,字符集一度成为普遍困扰大家的一个主要问题。
本文试图就一些常见问题进行探讨,希望可以把一些实际经验共享给大家!

1. 字符集的基本知识

如果从头说起,字符集最早的编码方案来自于与ASCII.
这也是我们最常见的编码方式。该方案起源于1960年代初期,最初是美国国会图书馆制定用来作为美国图书馆界书目交换的共同标准,最后完善成为美国的国家标准ASCII(American Standard Codefor Information Interchange),之后进一步演变成世界性的计算机字符编码标准ISO646(其全名为7-bit coded character set for information interchange)。成为计算机编码方案的基础。

Oracle数据库最早支持的编码方案也就是US7ASCII.
但是我们知道,英文字符一般是以一个字节来存储的,7位的编码方案最多只能代表128个字符;经过扩展的8位的编码方案也只能代表256个字符,这远远不能满足计算机发展的需要,对于亚洲国家复杂的字符存储需要更多的码位,于是各种编码方案随之而生。

为了容纳全世界各种语言的所有字符和符号,解决不同编码之间的兼容和转换问题,1991年元月,10多家公司共同出资,组建Unicode协会,随后Unicode编码产生了。
Unicode协会的口号是: 给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论什么语言。
最初Unicode编码使用2-Byte(16bit)来进行编码,但是最多只能容纳65536个字符,仍然不够使用,后来进行了扩充,也就是Unicode3.1标准,增加了额外的补充字符定义,现在Unicode4.0标准已经发布,具体可以参考Unicode官方站点:

www.unicode.org

Unicode编码方案主要有三个实施标准:
UTF-8
USC-2
UTF-16
Oracle从7.2开始支持UTF-8编码,提供Unicode编码支持。

按照各种标准的含义,Oracle推荐,如果你的数据库需要存放不同语言的不同符号和字符,建议使用Unicode编码方案。诚然,Unicode方案可以表示更多的字符,但是由于多位的存储,需要额外的存储空间和网络传输,所以选择最适合的数据库字符集仍然需要慎重考虑。

字符集问题的初步探讨(二)-数据库的字符集

2. 数据库的字符集

 

字符集在创建数据库时指定,在创建后通常不能更改,所以在创建数据库时能否选择一个正确的字符集就显得尤为重要。

在创建数据库时,我们可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。
字符集用来存储:
     CHAR, VARCHAR2, CLOB, LONG等类型数据
     用来标示诸如表名、列名以及PL/SQL变量等
     SQL和PL/SQL程序单元等
国家字符集用以存储:
     NCHAR, NVARCHAR2, NCLOB等类型数据

这些设置在数据库创建时指定,我们可以看一下数据库的创建脚本:













 

 








Oracle字符集的简单图解,中文乱码解决

 


 



 



 


 

<><><><><><>



     



 











>


>>

 

>>>>>>>>>>>

<>


>

>>>

>

>>




 

 


>

>








>>>>>>



 



<><><>


>



 

>>>>>>>>


>>




















 

>>




>>








>>



Oracle字符集的简单图解,中文乱码解决

Oracle字符集的简单图解,中文乱码解决

 

 >>>

 

 

 

 








 

 >>>>>>>>>>>>>>>>>>>>>


Oracle字符集的简单图解,中文乱码解决

 

 >>>>>


 

 >>>>>>>>>>




 

 >>>>

 >

 

 

 

 


 

 



Oracle字符集的简单图解,中文乱码解决




 

>>>>>

>




>

>
>



 

 



Oracle字符集的简单图解,中文乱码解决


 

 

 

>>>>>>>>>

 





<>


 






>>>>>>>>>

 




 

 











 





    

Oracle字符集的简单图解,中文乱码解决Oracle字符集的简单图解,中文乱码解决

Oracle字符集的简单图解,中文乱码解决
Oracle字符集的简单图解,中文乱码解决
Oracle字符集的简单图解,中文乱码解决