重新装mysql出现乱码,数据库出现乱码的原因和解决办法

本文详细分析了Oracle数据库中字符集问题的原因及影响,包括服务器字符集与客户端字符集不一致导致的数据乱码问题。文章指出,数据库创建后的字符集不可更改,因此在设计阶段选择合适的字符集至关重要。同时,提供了通过修改DMP文件字节和调整NLS_LANG参数来解决数据导入导出时的字符集转换问题。文章还介绍了NLS_LANG参数的作用及其对客户端显示的影响,并列举了常见的字符集问题及解决策略。
摘要由CSDN通过智能技术生成

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

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

… …

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

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

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

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

在实际的应用中,和字符集问题最相关的恐怕就是exp/imp了。在做exp/imp是,如果client和server的nls_lang设置是一样的,一般就没有问题。但是,要在两个不同字符集的系统之间导数据就经常会有这样那样的问题,如,导出时数据库的显示正常,是中文,当导入到其他系统时,就成了乱码,这也是一类常见问题。对于这个问题,有一个常用的转换方法,首先用一个二进制编辑器(如,UltraEdit)察看到出文件(DMP文件)的第二和第三字节,这两个字节的内容是服务器端的字符集,比如0001,那么在数据库中查找出它代表的字符集:

bepone> sqlplus internal

SQL> select nls_charset_name(to_number(‘0001‘,‘xxxx‘)) from dual;

NLS_CHARSET_NAME(TO_NUMBER(‘0001‘,‘XXXX‘)

----------------------------------------

US7ASCII

SQL>

然后,如果在导入数据时需要修改为ZHS16GBK,我们就需要知道如何修改这两个字节才能让他们和ZHS16GBK对应:

bepone> sqlplus internal

SQL> SQL> select to_char(nls_charset_id(‘ZHS16GBK‘), ‘xxxx‘) from dual;

TO_CH

-----

354

SQL>

因此,可以将这两个字节手工修改为0354(不足4位时前面补0),然后就可以正常导入数据了。

现在,为了进一步搞清楚字符集的秘密,介绍一些与字符集有关的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_CURRENCYISO货币字符

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$

NameTypeNullable Default Comments

-------- -------------- -------- ------- --------

NAMEVARCHAR2(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‘;

NAMEVALUE$

------------------------------ ----------------------------------------

NLS_CHARACTERSETZHS16GBK

SQL> select * from sys.props$;

NAMEVALUE$

------------------------- ----------------------------------

DICT.BASE2

DBTIMEZONE0:00

NLS_LANGUAGEAMERICAN

NLS_TERRITORYAMERICA

NLS_CURRENCY$

NLS_ISO_CURRENCYAMERICA

NLS_NUMERIC_CHARACTERS.,

NLS_CHARACTERSETZHS16GBK

NLS_CALENDARGREGORIAN

NLS_DATE_FORMATDD-MON-RR

NLS_DATE_LANGUAGEAMERICAN

NLS_SORTBINARY

NLS_TIME_FORMATHH.MI.SSXFF AM

NLS_TIMESTAMP_FORMATDD-MON-RR HH.MI.SSXFF AM

NLS_TIME_TZ_FORMATHH.MI.SSXFF AM TZH:TZM

NLS_TIMESTAMP_TZ_FORMATDD-MON-RR HH.MI.SSXFF AM TZH:TZM

NLS_DUAL_CURRENCY$

NLS_COMPBINARY

NLS_NCHAR_CHARACTERSETZHS16GBK

NLS_RDBMS_VERSION8.1.6.0.0

NAMEVALUE$

------------------------- ----------------------------------

GLOBAL_DB_NAMESCPDB1

EXPORT_VIEWS_VERSION8

22 rows selected

SQL>

从接过可以看出:

NLS_LANG =AMERICAN_AMERICA.ZHS16GBK

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

如:

SQL> conn / as sysdba

Connected.

SQL> SQL> select * from sys.props$

2WHERE NAME=‘NLS_LANGUAGE‘;

NAMEVALUE$

------------------------------ ---------------------

NLS_LANGUAGEAMERICAN

SQL>

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

2WHERE NAME=‘NLS_LANGUAGE‘;

1 row updated

SQL>

SQL> select * from sys.props$

2WHERE NAME=‘NLS_LANGUAGE‘;

NAMEVALUE$

------------------------------ ---------------------

NLS_LANGUAGESIMPLIFIED CHINESE

SQL>

通常我们常见问题的原因,基本上可以分为三种:

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

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

§察看当前字符集:

SQL> select * from sys.props$

2WHERE NAME=‘NLS_CHARACTERSET‘;

NAMEVALUE$

------------------------------ ----------

NLS_CHARACTERSETZHS16GBK

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‘

2WHERE NAME=‘NLS_LANGUAGE‘;

1 row updated

SQL> COMMIT;

Commit complete

SQL>

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

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值