關於客戶端字符集與亂碼的困擾

xypincle發表於2017-10-06

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/28878983/viewspace-2145727/,如需轉載,請註明出處,否則將追究法律責任。

相關文章