|
P4
|
发表于 2014-6-18 03:27:56
字符集的问题主要是客户端系统和服务端数据库的字符集要一致,如果不一致,
要变成一致
实验:
初始环境Redhat5.5、Oracle 10.2.0.5
login as: oracle
oracle@192.16.16.10's password:
Server refused to set all environment variables
Last login: Tue Jun 17 22:59:00 2014 from 192.16.16.3
[oracle@sfwlinux ~]$ cd /oracle
[oracle@sfwlinux oracle]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
[oracle@sfwlinux oracle]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.5.0 - Production on Tue Jun 17 23:01:25 2014
Copyright (c) 1982, 2010, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit
Production
With the Partitioning, OLAP, Data Mining and Real Application Testing
options
SQL> select * from nls_database_parameters;
PARAMETER VALUE
------------------------------
--------------------------------------------------------------------------------
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 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_NCHAR_CHARACTERSET AL16UTF16
NLS_RDBMS_VERSION 10.2.0.5.0
20 rows selected.
SQL> create table test (a varchar2(32));
Table created.
SQL> insert into test values('中文');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test;
A
------------
??????
查询出来的都是乱码,这是因为数据库是ZHS16GBK,而系统是UTF-8的
1.将数据库的字符集改为和OS系统字符一致
目标:将数据库的字符集改为UTF8.
如果按照export NLS_LANGUAGE=AMERICAN_AMERICA.UTF8,结果效果没
出来。。
然后想到直接改数据库字符集
这个是有很大风险的,因为如果要改变字符集,new字符集需要是old字符集的超
集,
如果没有超级子集关系,需要强制转换,可能会造成数据的损坏,务必慎重!
本例从ZHS16GBK到UTF8的转换就是强制转换。
现在做个测试:
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.
Total System Global Area 1845493760 bytes
Fixed Size 2021568 bytes
Variable Size 452986688 bytes
Database Buffers 1375731712 bytes
Redo Buffers 14753792 bytes
Database mounted.
SQL> alter session set sql_trace=true;
Session altered.
SQL> alter system enable restricted session;
System altered.
SQL> alter system set job_queue_processes=0;
System altered.
SQL> alter system set aq_tm_processes=0;
System altered.
SQL> alter database open;
Database altered.
SQL> alter database character set INTERNAL_USE UTF8;
/******INTERNAL_USE 强制不检查是否超子集关系,否则此处会报
alter database character set utf8
*
ERROR at line 1:
ORA-12712: new character set must be a superset of old character set****/
Database altered.
SQL>update props$ set VALUE$='UTF8' where
NAME='NLS_NCHAR_CHARACTERSET'
SQL>commit;
然后重启数据库,shutdown immediate 再startup(不重启应该也可以,保险起
见重启)
SQL> select * from test;
A
------------
??????
原有的还是不能正常显示
SQL>insert into test values('我爱中文');
SQL>commit;
SQL>select * from test;
A
----------------------------------------------------------------
??????
我爱中文
最后再解释为什么以前的数据无法显示为中文
2.将OS中的UTF-8变成和数据库 ZHS16GBK一致
首先将环境再次切换到初始试验环境
①.通过中文环境下Windows 7下面的PL/SQL Developer访问数据库
select * from test;
?????
insert into test values('我是win7');
提交
我是Win7
由于客户端是win7中文,数据库也是ZHS16GBK,所以没有问题
②.如果非要钻牛角尖,说我要用redhat5.5既做服务器端又做客户端,
那就必须要将UTF-8改成和数据库一致了。
试验:
[oracle@sfwlinux ~]$ cd /oracle
[oracle@sfwlinux oracle]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
[oracle@sfwlinux oracle]$ export
NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
[oracle@sfwlinux oracle]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
[oracle@sfwlinux oracle]$ sqlplus / as sysdba
......
SQL>insert into test values('中文');
SQL>commit;
SQL>select * from test;
A
--------------------------------
??????
中文
这一步不是改数据库或者OS字符集,只是申明了一个环境变量
由于UTF-8包含了所有ZHS16GBK的字符,只是编码方式不一样。
所以此处没有将OS中的UTF-8改为中文字符集就已经实现了中文
的插入显示。
下面是在Linux下将UTF-8转为中文
[oracle@sfwlinux Oracle]#export LANG=zh_CN.GBK
[oracle@sfwlinux oracle]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
这样就算结束了
如果要保持NLS_LANG持久,请写入vi ~/.bash_profile
export NLS_LANG=NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
|
|