请教字符集的问题
在linux端登录到windows端的数据库后,提示错误的时候是乱码,在linux端登录前已经执行了export NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'设置的和windows端数据库的字符集相同了,为什么还是乱码? 字符集要考虑三个方面的因素,“数据库端字符集、客户端字符集、操作系统字符集”,简单来说大致的流程如下:
1、用户设置客户端的字符集环境变量即NLS_LANG
2、用户执行查询语句,此时ORACLE在服务器端会根据用户设置的客户端字符集进行相应的字符集转换,然后把转化后的数据发给客户端;
3、客户端接收到来自服务器端的数据后进行展现;
上面三个步骤中后两个步骤错误配置都会导致显示出来的字符是错误的或乱码,第二步需要注意的是两个字符集必须是包含关系,也就是说在两个字符集中都有相应字符的编码,字样才能发生无损的字符转换,否则在这一步得到的字符就已经是乱码了,所以这一步关键看“服务器端的字符集(安装ORACLE是指定)和客户端的NLS_LANG配置”;
第三步需要操作系统的支持,假如说第二步ORACLE服务器端发生了正确的字符集转换,并且把数据传回到客户端,接下来显示数据就要靠客户端操作系统字符集的支持了,如果客户端操作系统根本不支持中文环境,那即使正确发生了字符集转换也是不能正常显示汉字的,这一点在LZ安装LINUX时是否选择安装中文支持有关;如果操作系统安装了中文支持就能够正常显示汉字了。
我做了一个在LINUX环境下访问LINUX数据库服务器的例子,给LZ参考。
环境配置
服务器字符集:AL32UTF8
--数据库端字符集
select * from nls_database_parameters;
PARAMETER VALUE
-------------------- ------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTE .,RS
NLS_CHARACTERSET AL32UTF8
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 TZR
NLS_TIMESTAMP_TZ_FOR DD-MON-RR HH.MI.SSXFF AM TZRMAT
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCPFALSE
NLS_NCHAR_CHARACTERS AL16UTF16ET
NLS_RDBMS_VERSION 10.2.0.1.0
--设置客户端字符集
export NLS_LANG="SIMPLIFIED CHINESE"_CHINA.ZHS16GBK
--查看客户端字符集
col parameter for a20
col value for a30
select * from nls_session_parameters;
PARAMETER VALUE
-------------------- ------------------------------
NLS_LANGUAGE SIMPLIFIED CHINESE
NLS_TERRITORY CHINA
NLS_CURRENCY \uffff\uffff
NLS_ISO_CURRENCY CHINA
NLS_NUMERIC_CHARACTE .,RS
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE SIMPLIFIED CHINESE
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 TZR
NLS_TIMESTAMP_TZ_FOR DD-MON-RR HH.MI.SSXFF AM TZRMAT
NLS_DUAL_CURRENCY \uffff\uffff
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCPFALSE
--插入中文
conn scott/tiger
insert into tt values(1,'快捷');
commit;
select * from tt;
本帖最后由 chenyu 于 2010-12-7 16:24 编辑
LINUX下访问WINDOWS数据库的测试
WINDOWS服务器端数据库字符集配置
SQL> select * from nls_database_parameters;
PARAMETER VALUE
------------------------------ --------------------------------------------------
NLS_LANGUAGE AMERICAN
NLS_NCHAR_CHARACTERSET AL16UTF16
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 TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_RDBMS_VERSION 10.2.0.4.0
当前WINDOWS中的服务器中已经有一条数据了,是在WINDOWS的客户端输入的,使用windows客户端使用sqlplus查看
SQL> select name,dump(name) from a;
NAME DUMP(NAME)
-------------------- -----------------------------------------------------------
中国 Typ=1 Len=4: 214,208,185,250
LINUX下用sqlplus客户端查看
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
把客户端的字符集环境变量设置成和操作系统的字符集一致,这里不能设置为"SIMPLIFIED CHINESE"_CHINA.ZHS16GBK,因为如果这么设置就不会发生字符集转换,但是客户端的操作系统是AL32UTF8(或者是和AL32UTF8兼容的字符集),服务器端直接把ZHS16GBK的编码发过来在AL32UTF8下显示肯定是乱码,我们要保证服务器端发过来的也是AL32UTF8编码,所以我们这里设置为AMERICAN_AMERICA.AL32UTF8,这样ORACLE就会在服务器端把数据由ZHS16GBK转换成AL32UTF8并发送到客户端,而客户端的操作系统也是AL32UTF8(或者是和AL32UTF8兼容的字符集)所以中文就能够正常显示了。
SQL> select * from a;
NAME
------------------------------------------------------------
中国
--在linux客户端插入中文
SQL> insert into a values('用户');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from a;
NAME
------------------------------------------------------------
用户
中国
然后在使用WINDOWS的客户端来显示
SQL> select name,dump(name) from a;
NAME DUMP(NAME)
-------------------- -----------------------------------------------------------
用户 Typ=1 Len=4: 211,195,187,167
中国 Typ=1 Len=4: 214,208,185,250 从WINDOWS服务器中EXP数据IMP到LINUX服务器中
WINDOWS数据库端字符集:ZHS16GBK,LINUX数据库端字符集:AL32UTF8
原理:EXP时发生字符集转换,IMP时不发生字符集转换;
在WINDOWS端导出数据
C:\>set NLS_LANG=AMERICAN_AMERICA.AL32UTF8
C:\>exp gpsdata/gpsdata@zjdb4 tables=(a) file=a.dmp
Export: Release 10.2.0.1.0 - Production on Tue Dec 7 16:28:00 2010
Copyright (c) 1982, 2005, Oracle.All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export done in AL32UTF8 character set and AL16UTF16 NCHAR character set
server uses ZHS16GBK character set (possible charset conversion)--注意这里发生字符集转换
About to export specified tables via Conventional Path ...
. . exporting table A 2 rows exported
Export terminated successfully without warnings.
在LINUX端导入数据
$ imp scott/tiger@PROD fromuser=gpsdata touser=scott file=a.dmp
Import: Release 10.2.0.1.0 - Production on Tue Dec 7 16:38:02 2010
Copyright (c) 1982, 2005, Oracle.All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options
Export file created by EXPORT:V10.02.01 via conventional path
Warning: the objects were exported by GPSDATA, not by you
import done in US7ASCII character set and AL16UTF16 NCHAR character set
import server uses AL32UTF8 character set (possible charset conversion) --这里没有发生字符集转换,直接以AL32UTF8导入
export client uses AL32UTF8 character set (possible charset conversion)
. importing GPSDATA's objects into SCOTT
. . importing table "A" 2 rows imported
Import terminated successfully without warnings.
在LINUX中查看导入的数据
这里开两个客户端,一个设置NLS_LANG,一个不设置
不设置NLS_LANG的客户端
SQL> select * from a;
NAME
--------------------
?? --显示为乱码
??
设置NLS_LANG的客户端
$ export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
SQL> select * from a;
NAME
--------------------
用户
中国
经过检查不设置NLS_LANG的客户端中的nls_database_parameters、nls_session_parameters和设置NLS_LANG的客户端中的nls_database_parameters、nls_session_parameters完全一致并没有任何不同,所以我感觉环境变量NLS_LANG除了能够影响当前客户端而且还有设置当前操作系统要显示的字符集的作用; 回复 chenyu 的帖子
chengyu大哥请问:
linux(客户端)----------->windows(服务器)
客户端发出一条请求需要经过几步字符集的转换?
客户端--------客户端的操作系统----------服务器端数据库 还需不需要经过服务器端的操作系统的字符集转换? 回复 chenyu 的帖子
您上面说的操作系统的字符集是服务器端的操作系统还是客户端的操作系统?还是两者都要有? 回复 chenyu 的帖子
传输的时候不会发生操作系统字符集的转换,只是显示的时候才会有操作系统字符集的转换是吗?还有就是我怎么查看linux系统是否支持中文呢? linux(客户端)----------->windows(服务器)
客户端发出一条请求需要经过几步字符集的转换?
字符集的转换只发生一次,而且一定是在服务器端才有能力进行字符集转换
客户端--------客户端的操作系统----------服务器端数据库 还需不需要经过服务器端的操作系统的字符集转换?
正确的步骤是客户端设置字符集环境变量(和操作系统保持一致)然后发出查询请求,服务器端接收请求并做字符集转换,然后把转换后的结果发给客户端,客户端接收数据并展现;
您上面说的操作系统的字符集是服务器端的操作系统还是客户端的操作系统?还是两者都要有?
是客户端的操作系统
传输的时候不会发生操作系统字符集的转换,只是显示的时候才会有操作系统字符集的转换是吗?还有就是我怎么查看linux系统是否支持中文呢?
请记住,字符集转换智能发生在服务器端。至于怎样知道LINUX支持中文,好像在系统配置中有一个“语言”选项,选择进入后可以看见LINUX所安装的语言支持,如果有中文支持那就是支持中文了,还有一种方法是只要在LINUX系统中能够显示汉字,应该就表明安装了中文支持。
页:
[1]