Oracle字元集轉換

來源:互聯網
上載者:User

標籤:

        這幾天在工作中碰到一個字元亂碼的問題,發現在cmd視窗的sqlplus中直接update一個中文和使用@調用一個檔案作同樣更新的時候,儲存的結果 竟不一樣。一時比較迷惑,對Oracle如何處理各個字元集的問題不是很清楚。特此通過一些資料和實驗總結,系統學習一下Oracle中字元集的相關知 識。

一. 字元集的基礎知識:
在網路上已有不少網友對字元集進行了研究,個人覺得有幾個不錯的網站可以參考
http://blog.csdn.net/tianlesoftware/article/details/4915223
http://www.itstreets.com/post/34.html
http://www.oraclefans.cn/forum/showblog.jsp?rootid=3303


二. Oracle字元集的轉換

以下用幾個實驗來學習一下Oracle對各種字元集的處理
此處涉及3個概念:資料庫服務端的字元集,用戶端的字元集和作業系統的字元集
實驗環境中:資料庫服務端的字元集是AL32UTF8

1. 用戶端和伺服器端的字元集一致的時候
實驗一:用戶端字元集也是AL32UTF8, 作業系統的字元集是GB2312
[email protected]>update c_language set languagename=‘中國‘ where id = ‘zh-CN‘;

1 row updated.

[email protected]>commit ;

Commit complete.

[email protected]>select dump(languagename, 1016) from c_language where id = ‘zh-CN‘;

DUMP(LANGUAGENAME,1016)
-----------------------------------------------------------------------------------------

Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa

[email protected]>

使用dump函數以16進位查看在資料庫中的儲存,可以看出“中國”這2個字,在資料庫中的儲存編碼是:d6,d0,b9,fa

先建一個檔案t1.txt,寫上“中國”這2個字,以GB2312(codepage 為936)的格式儲存。
在cmd視窗使用type命令查看,可以看到此時在cmd視窗能正確顯示文本。

V:\>chcp
Active code page: 936

V:\>type e:\t1.txt
中國
V:\>

再用winhex工具查看t1.txt文本,可以看到其16進位編碼為:D6,D0,B9,FA


實驗二:在sqlplus環境中使用@來調用一個sql檔案,檔案的內容是和實驗一同樣的一句sql,檔案格式為UTF8
伺服器和用戶端的字元集依然是AL32UTF8, 作業系統的codepage為936

[email protected]>select dump(languagename, 1016) from c_language where id = ‘zh-CN‘;

DUMP(LANGUAGENAME,1016)
---------------------------------------------------------------------------------------

Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd

[email protected]>

同樣建一個文字檔t2.txt,以UTF8的格式儲存。再使用WinHex查看, 可以看到其16進位編碼為:E4, B8, AD, E5, 9B, BD


通過這2個實驗,可以清楚的看出,在用戶端和資料庫服務端的字元集一致的時候,Oracle並不進行儲存轉換。如在cmd視窗之中,
以作業系統預設的GB2312編碼的“中國”,和以檔案方式按UFT8編碼格式的“中國”,都會直接儲存到Oracle伺服器上。

但是我們會發現,按UTF8格式編碼的儲存,在cmd裡面查詢的結果會是亂碼。如下:

[email protected]>host chcp
Active code page: 936

[email protected]>col languagename format A30
[email protected]>select * from c_language where id=‘zh-CN‘;

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                涓浗
[email protected]>

這是因為我機器cmd視窗的codepage 預設是936,而用戶端和伺服器端的字元集都一樣,Oracle會不做任何轉換的把儲存的字元編碼
直接返回回來,但是資料庫裡面的編碼是按UTF8的儲存的,而cmd視窗的字元編碼為GB2312,故而是顯示的亂碼。

我們可以將cmd視窗的codepage先改為UTF8(codepage為65001)格式的,則可以看到正常的顯示“中國”這2個字了。如下:
(如何修改codepage,可以參考:http://xiangqinghu1988.blog.163.com/blog/static/58822991201222232456746/)

Active code page: 65001

[email protected]>select * from c_language where id = ‘zh-CN‘;

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                中國

[email protected]>

因此,在Oracle沒有施行字元轉換的時候,即(用戶端和伺服器端的字元集是一致的時候),如果出現亂碼,那麼則是表明用戶端的環境編碼(如cmd視窗的編碼)和Oracle資料庫儲存的字元編碼(cmd視窗直接用sqlplus更新和調用一個UTF8檔案格式的更新)不一致。如果要查看,需要修改用戶端的環境編碼。比如修改cmd的codepage。

2. 用戶端和伺服器端的字元集不一致的時候
實驗三:將用戶端的字元集設定為ZHS16GBK,在sqlplus裡面直接更新記錄如下:

V:\>set NLS_LANG=American_America.ZHS16GBK

V:\>sqlplus [email protected]

SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 22 15:29:43 2012

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

Enter password:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

[email protected]>Update c_language set languagename=‘中國‘ where id = ‘zh-CN‘;

1 row updated.

[email protected]>commit;

Commit complete.

[email protected]>col languagename format A30
[email protected]>select * from c_language where id = ‘zh-CN‘;

ID                                       LANGUAGENAME
---------------------------------------- ------------------------------
zh-CN                                    中國

[email protected]>select dump(languagename, 1016) from c_language where id = ‘zh-CN‘;

DUMP(LANGUAGENAME,1016)
-----------------------------------------------------------------------------------------

Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd

[email protected]>

結果很有意思,資料庫中儲存的不再是像實驗一中的d6,d0,b9,fa, 而是很巧的變成了UTF8格式的儲存了。如果我們開另外一個
sqlplus視窗,其用戶端字元集為AL32UTF8,這時來查看一下這條記錄如下,發現亂碼了

V:\>sqlplus [email protected]

SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 22 15:36:56 2012

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

Enter password:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

[email protected]>col languagename format A30
[email protected]>select * from c_language where id = ‘zh-CN‘;

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                涓浗

[email protected]>

如果我們把cmd的codepage設定為UTF8格式的,我們就可以看到是正常的顯示了(這時還是要求用戶端與伺服器端的字元集一致)

Active code page: 65001
[email protected]>select * from c_language where id = ‘zh-CN‘;

ID                   LANGUAGENAME
-------------------- ------------------------------
zh-CN                中國

[email protected]>

注意,這個實驗的結果比較巧合,如果將sqlplus用戶端的字元集不是設定ZHS16GBK,而是設為其他的字元集,那麼Oracle中儲存的就不一定是UTF8的編碼了。
實際上,如果用戶端和服務端的字元集不一致,Oracle底層會對字元編碼進行轉換,具體如何轉換我也還不清楚,望有高手深入研究。

總的來說,在實際中如果碰到亂碼情況,需要知曉Oracle用戶端字元集,伺服器端字元集以及作業系統字元集這幾個之間的關係。
1. 如果用戶端和伺服器端的字元集一致,Oracle不會進行編碼轉換。直接按儲存作業系統相關的編碼格式儲存。在查詢的時候,也不會轉換,而是直接返回資料庫中儲存的編碼
2. 如果用戶端和伺服器端的字元集不一致,Oracle會在底層對儲存的字元進行編碼轉換。在查詢返回的時候,同樣會轉換一次。

Oracle字元集轉換

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.