li
  当前位置:主页 > 配置管理 > 文章内容
li
字符集专题:数据库乱码的原因与解决
来源: www.ixdba.net  作者: www.ixdba.net    时间:2007-12-19   阅读:7  

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

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

……

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

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

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

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

在实际应用中,和字符集问题关系最大的恐怕就是exp/imp了。在做exp/imp时,如果Client Servernls_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 以下版本,进入Windows的系统目录,编辑oracle.ini文件,用US7ASCII替换原字符集,重新启动计算机,设置生效;否则,如果,客户端为 sql*net 2.0 以上版本,在Win98 运行REGEDIT,第一步选HKEY_LOCAL_MACHINE,第二步选择SOFTWARE 第三步选择 Oracle 第四步选择 NLS_LANG 与服

(本例为:HKEY_LOCAL_MACHINE\

SOFTWARE\ORACLE\NLS_LANG
AMERICAN _ AMERICA. ZHS16GBK)。

如果是UNIX客户端,则:

SQL> conn / as sysdba

Connected.

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

2 WHERE NAME=‘NLS_LANGUAGE’;

1 row updated

SQL> COMMIT;

Commit complete

SQL>

2.
服务器指定字符集与客户字符集相同,与加载数据字符集不一致。

解决方法:强制加载数据字符集与服务器端字符集一致。要做到这一点,可以通过重新创建数据库,并选择与原卸出数据一致的字符集,然后IMP数据,这种情况仅仅适用于空库和具有同一种字符集的数据。

解决这类问题,也可以先将数据加载到具有相同字符集的服务器上,然后用转换工具卸出为foxbase 格式或access格式数据库,再用转换工具转入到不同字符集的Oracle数据库中,这样就避免了Oracle字符集的困扰。目前数据库格式转换的工具很多,power builder5.0以上版本提供的pipelineMicrosoft Access数据库提供的数据导入/导出功能等。

3.
服务器指定字符集与客户字符集不同,与输入数据字符集不一致。

对于这种情况,目前为止都还没有太好的解决方法。

通过上面的了解,我们知道,导致在后期使用数据库时出现种种关于字符集的问题,多半是由于在数据库设计、安装之初没有很好地考虑到以后的需要,所以,我们完全可以通过在服务器上和客户端使用相同的字符集来避免由此类问题引出的麻烦。




  上一篇: 安装篇推荐:oracle9i安装综合以...   下一篇: 疑惑解答:重建控制文件示疑
li
 §相关评论  
 热点文章
·oracle字符集设置问题
·新手强烈推荐:Oracle 体系结构
·推荐阅读:成就DBA职业生涯
·字符集专题:数据库乱码的原因
·如何把数据导入不同的表空间
·用Oracle导入导出工具实现Orac
·Oracle数据库空间使用和管理若
·Oracle数据库手边命令
·Oracle后台进程详解
·Oracle10g归档参数研究
·v$parameter,v$system_paramet
li
 编辑推荐
·oracle字符集设置问题
·新手强烈推荐:Oracle 体系结构
·推荐阅读:成就DBA职业生涯
·字符集专题:数据库乱码的原因
·如何把数据导入不同的表空间
·用Oracle导入导出工具实现Orac
·Oracle数据库空间使用和管理若
·Oracle数据库手边命令
·Oracle后台进程详解
·Oracle10g归档参数研究
·v$parameter,v$system_paramet
li
 相关篇章
·安装篇推荐:oracle9i安装综合以...
·Oracle10g在Redhat AS4u2 x86_64...
·手动创建oracle9i数据库具体步骤
·Oracle登录认证方式探讨
·Oracle预定义角色有哪些?
·Oracle 9i轻松取得建表和索引的D...
·Oracle 9i初始化参数文件详解
·Oracle入门基本知识一点通
·推荐阅读:成就DBA职业生涯
·新手强烈推荐:Oracle 体系结构简...
·疑惑解答:重建控制文件示疑
·Oracle10g特性:Recycle Bin回收站
 
li
设为首页 | 关于我们 | 技术服务 | 收藏本站 | 网站地图 | 联系方式 | 本站友情连接