关于Oracle中文字符乱码的问题与解决方案

Blank

因为数据库输入中文显示乱码的问题。研究了一下,现说明如下:

要想我们正确显示中文字符:
要保证3个字符集正确:
(1)服务器端数据库字符集(CharacterSet)设置.
(2)客户端NLS_LANG参数设置.
(3)客户端应用字符集.
客户端应用中能够显示什么样的字符取决于客户端操作系统语言环境(客户端应用字符集),但在应用中录入这些字符后,这些字符能否在数据库中正常存储,还与另外两个字符集设置紧密相关,其中客户端NLS_LANG参数主要用于字符数据传输过程中的转换判断.常见的乱码大致有两种情形:
(1)汉字变成问号“?”;
当从字符集A转换成字符集B时,如果转换字符之间不存在对应关系,NLS_LANG使用替代字符“?”替代无法映射的字符.

(2)汉字变成未知字符(虽然有些是汉字,但与原字符含义不同).
转换存在对应关系,但字符集A中的字符编码与字符集B中的字符编码代表不同含义.
 
 
1. 数据库字符集
 
用以下2个SQL语句查看数据库字符集设置:
 
select * from NLS_DATABASE_PARAMETERS       --显示数据库当前NLS参数取值,包括数据库字符集取值.
select * from NLS_SESSION_PARAMETERS          --显示由NLS_LANG设置的参数,或经过alter session改变后的参数值(不包括由NLS_LANG设置的客户端字符集).
select * from NLS_INSTANCE_PARAMETE             --显示由参数文件init.ora定义的参数
select * from V$NLS_PARAMETERS                      --显示数据库当前NLS参数取值.
 
 
查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集.
 
 
数据库字符集在创建后原则上不能更改.如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或通过 ALTER DATABASE CHARACTERSET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTERSET UTF8.
 
 
2. 客户端字符集(NLS_LANG参数)

2.5.1客户端字符集含义
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如sqlplus,exp/imp等.客户端字符集是通过设置NLS_LANG参数来设定的.

2.5.2NLS_LANG参数格式
NLS_LANG=_.
Language:显示oracle消息,校验,日期命名.
Territory:指定默认日期、数字、货币等格式.
Clientcharacterset:指定客户端将使用的字符集.
例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII.
AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集.

2.5.3客户端字符集设置方法
Windows编辑注册表
Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOMExxx.
 
 
这个的设置可以在我们建立与Oracle的连接的时候,对session进行设置 譬如:OracleConnection m_connection.SetSessionInfo(OracleGlobalization SessionParam);
 
OracleGlobalization是Oracle在客户端的应用字符集设置,它自动从注册表中读取参数,这跟安装的Oracle的ODP以及本地设置的Windows语言及字符集等格式有关系。
这个不建议大家修改注册表,而是在软件的Setting里设置自己的应用语言和字符集。
 
 
3. 客户端应用字符集
 
 
这个一般应该问题不大,只要你的系统能显示中文即可。我姑且这么认为。

验证中。。。。


另外有人提出一种客户端手动转化字符集的方式,借鉴一下:

解决Oracle处理中文乱码的一种方法

项目中用到Oracle,服务器端使用AMERICAN_AMERICA.WE8ISO8859P1字符编码,我没有修改服务器端的权限,只能修改客户 端.但是客户端无论我换什么字符编码均得到乱码,最后我将客户端的字符编码也设为AMERICAN_AMERICA.WE8ISO8859P1,然后从程 序中下手.
AMERICAN_AMERICA.WE8ISO8859P1,这个字符编码是西欧字符编码,对应于.Net的就是iso-8859-1字符编码,所以只需要改到系统的默认字符编码就行了.
写一个函数:
        /// <summary>
        
/// 将西欧字符编码转换成GB2312
        
/// </summary>
        
/// <param name="s"></param>
        
/// <returns></returns>

        public static string Convert8859P1ToGB2312(string s)
        
{
            
return System.Text.Encoding.Default.GetString(System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(s));
        }

 
posted @ 2009-09-24 16:05  cubean  阅读(35492)  评论(0编辑  收藏  举报