关于客户端字符集与乱码的困扰


1.查看oracle服务端和客户端的字符集

----查看oracle数据库字符集

select * from nls_database_parameters;

 

----查看客户端字符集

select userenv('language') from dual;

 

 

----客户端字符集环境

select * from nls_instance_parameters;

 

----会话字符集环境

select * from nls_session_parameters;

 

 

    oracle字符集相关的参数是 nls_langNLS_LANG 的格式是:

    language_territory.client_charset

    AMERICAN_AMERICA.ZHS16GBK,那么第一位AMERICAN 表示语言,第二位 AMERICA 表示日期和数字格式,第三位 ZHS16GBK 表示字符集。影响数据库和客户端的其实是第三部分。

 

2.修改服务端字符集(谨慎,不推荐)

---- 数据库创建以后,如果需要修改字符集,通常需要重建数据库,通过导入导出的方式来转换。也可以通过以下方式更改:

ALTER DATABASE CHARACTER SET

 

---- 注意修改数据库字符集时必须谨慎,修改之前一定要为数据库备份。由于不能回退这项操作,因此可能会造成数据丢失或者损坏。

 

---- 这是最简单的转换字符集的方式,但并不是总是有效。这个命令在Oracle 8时被引入Oracle,这个操作在本质上并不转换任何数据库字符,

---- 只是简单地更新数据库中所有跟字符集相关的信息。

 

---- 这意味着只能在新字符集是旧字符集严格超集的情况下使用这种方式转换。所谓超集是指当前字符集中的每一个字符集在新字符集中都可以表示,并使用相同的代码点,

---- 比如很多字符集都是US7ASCII的严格超集。

 

-- 如果不是超集将获得以下错误:

SQL> ALTER DATABASE CHARACTER SET ZHS16CGB231280;

*

ERROR at line 1:

ORA-12712: new character_set_must bu a superset of old character set

 

----下面在11g环境下进行测试

sys@ORCL>select userenv('language') from dual;

sys@ORCL>select * from nls_database_parameters;

sys@ORCL>select name,value$ from props$ where name like '%NLS%';

 

NAME                                     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                        11.2.0.4.0

20 rows selected.

 

sys@ORCL>create table scott.test(id number(18,0),name varchar2(20));

sys@ORCL>insert into scott.test values(1,'zhong');

sys@ORCL>insert into scott.test values(2,'');

sys@ORCL>commit;

SQL> select * from scott.test;

                 ID NAME

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

                  2

                  1 zhong

 

SQL> select name, dump(name) from scott.test;

NAME                 DUMP(NAME)

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

                   Typ=1 Len=2: 214,211

zhong                Typ=1 Len=5: 122,104,111,110,103

 

----转换字符集,数据库应该在RESTRICTED(限制会话)模式下进行:

sys@ORCL>shut immediate

sys@ORCL>startup mount

sys@ORCL>alter session set sql_trace=true;

sys@ORCL>alter system enable restricted session;

sys@ORCL>alter system set job_queue_processes=0;

sys@ORCL>alter system set aq_tm_processes=0;

sys@ORCL>alter database open;

sys@ORCL>alter database character set AL32UTF8;

alter database character set AL32UTF8

*

ERROR at line 1:

ORA-12712: new character set must be a superset of old character set

    出现错误提示,新字符集必须是老字符集的超集,也就原来字符集是新字符集的子集,可以再Oracle官方文档上查询字符集包含关系。下面使用Oracle内部命令internal_use,跳过超集检查,生产环境不建议使用此方法。

 

sys@ORCL>alter database character set internal_use AL32UTF8;

 

sys@ORCL>shut immediate

sys@ORCL>startup

 

sys@ORCL>select name,value$ from props$ where name like '%NLS%';

 

NAME                           VALUE$

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

NLS_LANGUAGE                   AMERICAN

NLS_TERRITORY                  AMERICA

NLS_CURRENCY                   $

NLS_ISO_CURRENCY               AMERICA

NLS_NUMERIC_CHARACTERS         .,

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_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              11.2.0.4.0

20 rows selected.

 

sys@ORCL>alter system set job_queue_processes=10;

sys@ORCL>alter system set aq_tm_processes=1;

 

SQL> select name, dump(name) from scott.test;

NAME                 DUMP(NAME)

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

                   Typ=1 Len=2: 214,211

zhong                Typ=1 Len=5: 122,104,111,110,103

 

SQL> insert into scott.test values(3,'');

1 row inserted

 

SQL> select name, dump(name) from scott.test;

NAME                 DUMP(NAME)

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

                   Typ=1 Len=2: 214,211

zhong                Typ=1 Len=5: 122,104,111,110,103

                   Typ=1 Len=3: 233,146,159

 

-- 在这里纠正一个由来已久的错误方法,经常可以在网上看到这样的更改字符集的方法,这种方法应该被忘记,绝对不应该被采用:

-- *(1) SYS用户登录ORACLE

-- *(2) 查看字符集内容

        SELECT * FROM props$;

-- *(3) 修改字符集

  update props$ set value$='ZHS16GBK' where name='NLS_CHARACTERSET';

  update props$ set value$='AL32UTF8' where name='NLS_CHARACTERSET';

-- 我们可以轻易地指出,以上方法是不正确的,通过前面“ALTER DATABASE CHARACTER SET”方式更改字符集时,Oracle 至少需要更改12张数据字典表,而这种直接更新props$表的方式只完成了其中十二分之一的工作,潜在的完整性隐患是可想而知的。

-- 所以,更改字符集尽量要使用正常的途径。

 

 

3.修改客户端字符集

----linux下:

----查看当前客户端字符集

[oracle@xuan1 ~]$ echo $NLS_LANG   

american_america.ZHS16GBK

 

[oracle@xuan1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Wed Jul 20 03:33:03 2016

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>

 

----修改客户端字符集

[oracle@xuan1 ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

 

[oracle@xuan1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on 星期三 7 20 03:30:54 2016

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

连接到:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>

 

 

----windows

----修改客户端字符集需要在注册表中修改NLS_LANG

regedit  ---> HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMExx\

xx指存在多个ORACLE_HOME时系统编号。

 

 

 

 

----乱码困扰

----有时候在linuxsqlplus插入中文字符后,使用plsql客户端连接查看确实乱码,在linux中确能看到中文,这是为什么呢?   其实与linux系统字符集设置有关,也就是LANG的设置。

 

----示列:

[oracle@xuan1 ~]$ export LANG=en_US.UTF-8

[oracle@xuan1 ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

----此时如果是sshlinux的,那么连接工具字符集应该设置为UTF-8

SQL> create table shall(zhong varchar2(100));

 

SQL> insert into shall values('test!!  测试!!');

SQL> select * from shall;

ZHONG

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

test!!  测试!!

----在客户端上看就变成乱码了......

 

 

----怎么办?看我的

[oracle@xuan1 ~]$ export LANG=zh_CN.GB2312                          

[oracle@xuan1 ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

----此时如果是sshlinux的,那么连接工具字符集应该设置为GB2312

 

SQL> insert into shall values('zhong guo!! 中国!!');

已创建 1 行。    ----有点不一样咯,这里操作后有中文提示

 

SQL> select * from shall;

ZHONG

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

test!!  娴嬭瘯锛侊紒

zhong guo!! 中国!!

 

----此时在客户端plsql上查看,也能查看到刚刚插入的那条数据咯

 

 

 

----关于乱码困扰总结一下:

---------plsql端创建表格,然后插入中文字符后,在服务端linuxsqlplus查看出现乱码?

1> 如果只想查看数据,不修改,那么只需要把ssh连接的工具编码改为GB2312就能查看表中中文数据咯,但是不能插入或修改中文;

2> 如果想修改表中的中文数据,那么需要把linux系统中的LANG改为zh_CN.GB2312,然后才能插入中文数据,并且在plsql端能正常查看;

3> 改了LANGssh连接linux工具的字符编码为GB2312后,连接数据库还是英文提示,如果改为中文提示呢?这个需要设置数据库客户端字符集,如:

select userenv('language') from dual;    ----查看当前客户端字符集

[oracle@xuan1 ~]$ export NLS_LANG=american_america.ZHS16GBK    ----这个是改为英文操作提示

[oracle@xuan1 ~]$ export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"    ----这个就是改为中文操作提示的

 

 

----当然,这只是我遇到的乱码问题,也许你的数据库字符集本身为UTF-8,那就不用想我这样设置咯。

 

 

 

 

 

 

 

reference   eygle  http://www.itpub.net/thread-176084-1-1.html

利用DMU修改数据库字符集: http://mp.weixin.qq.com/s?__biz=MjM5MDAxOTk2MQ==&mid=2650271110&idx=1&sn=fb973903d33c6f6904310bf834be966c&scene=23&srcid=0729OK8FH9iD867ThxTMNbey#rd

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30130773/viewspace-2122834/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/30130773/viewspace-2122834/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值