设为首页 加入收藏

TOP

数据库乱码的原因和解决(一)
2014-11-24 01:43:26 来源: 作者: 【 】 浏览:38
Tags:数据库 乱码 原因 解决

在SQL*Plus中用insert插进的都是中文的,为什么一存入服务器后,再select出的就是 ”


“有的时候,服务器数据先导出,重装服务器,再导入数据,结果,发生数据查询成 ”


……


这些问题,一般是因为字符集设置不对造成的。


非常久以来,字符集一直是困扰着众多Oracle爱好者的问题,笔者从事Oracle数据库管理和应用已几年了,经常接到客户的类似上面提到的有关数据库字符集的“告急”和“求救”,在此我们就这个问题做一些分析和探讨。


首先,我们要明确什么是字符集?字符集是个字节数据的解释的符号集合,有大小之分,有相互的包括关系,如us7ascii就是zhs16gbk的子集, 从us7ascii到zhs16gbk不会有数据解释上的问题,不会有数据丢失,Oracle对这种问题也需求从子集到超集的导出受支持,反之不行。在所有的字符集中utf8应该是最大,因为他基于unicode,双字节保存字符(也因此在存储空间上占用更多)。


其次,一旦数据库创建后,数据库的字符集是不能改动的。因此,在设计和安装之初考虑使用哪一种字符集是十分重要的。数据库字符集应该是操作系统本地字符集的一个超集。存取数据库的客户使用的字符集将决定选择哪一个超集,即数据库字符集应该是所有客户字符集的超集。


在实际应用中,和字符集问题关系最大的恐怕就是exp/imp了。在做exp/imp时,如果Client 和Server的nls_lang设置是相同的,一般就没有问题的。不过,要在两个不同字符集的系统之间导数据就经常会有这样或那样的问题,如,导出时数据库的显示正常,是中文,当导入到其他系统时,就成了乱码,这也是一类常见问题。


目前,介绍一些和字符集有关的NLS_LANG参数,


NLS_LANG格式:


NLS_LANG = language_territory.charset


有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。其中:language 指定服务器消息的语言。


territory 指定服务器的日期和数字格式。


charset 指定字符集


例如:


AMERICAN_AMERICA.US7SCII


AMERICAN _ AMERICA. ZHS16GBK


更有一些子集能更明确定义NLS_LANG参数:


DICT.BASE 数据字典基本 表版本


DBTIMEZONE 数据库时区


NLS_LANGUAGE 语言


NLS_TERRITORY 地域


NLS_CURRENCY 本地货币字符


NLS_ISO_CURRENCY ISO货币字符


NLS_NUMERIC_CHARACTERS 小数字符和组 分隔开


NLS_CHARACTERSET 字符集


NLS_CALENDAR 日历系统


NLS_DATE_FORMAT 缺省的日期格式


NLS_DATE_LANGUAGE 缺省的日期语言


NLS_SORT 字符排序序列


NLS_TIME_FORMAT 时间格式


NLS_TIMESTAMP_FORMAT 时间戳格式


……


通过props$动态性能视图,我们能查看数据库的字符集信息:


$> sqlplus internal


SQL> desc props$


Name Type Nullable Default Comments


NAME VARCHAR2(30)


VALUE$ VARCHAR2(4000) Y


COMMENT$ VARCHAR2(4000) Y


SQL> set arraysize 1


SQL> col value$ format a40


SQL> select name,value$ from props$ where name=‘NLS_CHARACTERSET’;


NAME VALUE$


NLS_CHARACTERSET ZHS16GBK


SQL> select * from sys.props$;


NAME VALUE$


DICT.BASE 2


DBTIMEZONE 0:00


NLS_LANGUAGE AMERICAN


NLS_TERRITORY AMERICA


NLS_CURRENCY $


NLS_ISO_CURRENCY AMERICA


NLS_NUMERIC_CHARACTERS .,


NLS_CHARACTERSET ZHS16GBK


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


NLS_TIME_TZ_FORMAT HH.MI.


SSXFF AM TZH:TZM


NLS_TIMESTAMP_TZ_FORMAT DD-MON- RR HH.MI. SSXFF AM TZH:TZM


NLS_DUAL_CURRENCY $


NLS_COMP BINARY


NLS_NCHAR_CHARACTERSET ZHS16GBK


NLS_RDBMS_VERSION 8.1.6.0.0


NAME VALUE$


GLOBAL_DB_NAME SCPDB1


EXPORT_VIEWS_VERSION 8


22 rows selected


SQL>


从结果能看出:


NLS_LANG = AMERICAN _ AMERICA. ZHS16GBK


虽然,数据库的字符集是在create database的时候指定的,以后不允许改动,但在一个已建立好的数据库上,我们能通过修改SYS.PROPS$来修改主要是对应客户端的显示,和存储无关。


如:


SQL> conn / as sysdba


Connected.


SQL> SQL> select * from sys.props$


2 WHERE NAME=‘NLS_LANGUAGE’;


NAME VALUE$


NLS_LANGUAGE AMERICAN


SQL>


SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’


2 WHERE NAME=‘NLS_LANGUAGE’;


1 row updated


SQL>


SQL> select * from sys.props$


2 WHERE NAME=‘NLS_LANGUAGE’;


NAME VALUE$


NLS_LANGUAGE SIMPLIFIED CHINESE


SQL>


通常出现问题的原因,可分为三种:


1. 服务器指定字符集和客户字符集不同,而和加载数据字符集一致。


解决方法:对于这种情况,只需要设置客户端字符集和服务器端字符集一致就能了,具体操作如下:


* 查看当前字符集:


SQL> select * from sys.props$


2 WHERE NAME=‘NLS_CHARACTERSET’;


NAME VALUE$


NLS_CHARACTERSET ZHS16GBK


SQL>


能看出,目前服务器端Oracle数据库的字符集为‘ZHS16GBK’


* 根据服务器的字符集在客户端作相应的设置或安装Oracle的客户端软件时指定:


如果还没安装客户端,那么在安装客户端时,指定和服务器相吻合的字符集即可;如果已安装好了客户端,并且客户端为 sql*net 2.0 以下版本,进入视窗系统的系统目录,编辑oracle.ini文件,用US7ASCII替换原字符集,重新启动计算机,设置生效;否则,如果,客户端为 sql*net 2.0 以上版本,在Win98 下 运行REGEDIT,第一步选HKEY_LOCAL_MACHINE,第二步选择SOFTWARE, 第三步选择Oracle

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇如何用PHP连接MySQL 下一篇如果让你测试一个输入框,你如何..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: