程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle數據庫字符集轉換規律全面剖析

Oracle數據庫字符集轉換規律全面剖析

編輯:Oracle數據庫基礎

作為一個Oracle數據庫的用戶,對於Export和Import兩個命令絕對不會感到陌生,因為這二者正是我們經常用於數據備份和恢復的工具。但在使用這兩個命令過程中所發生的Oracle字符集問題,常給一些Oracle使用者帶來不必要的麻煩和不必要的數據損失。本文將就Export和Import過程中Oracle字符集的轉換規律及使用這兩個命令的注意事項做一總結。

字符集轉換的原因

Export、Import過程如上圖所示,從這個示意圖中可以看到有四處關系到字符集,而這四處字符集的不一致恰恰是導致Oracle進行字符集轉換的原因。

* 源數據庫字符集;

* Export過程中用戶會話字符集;

* Import過程中用戶會話字符集;

* 目標數據庫字符集。

在Export和Import過程中,如果存在影響字符集轉換的四因素不一致,則可能發生Oracle字符集轉換,即:

在Export過程中,如果源數據庫字符集與Export用戶會話字符集不一致,會發生字符集轉換,並在導出的二進制格式Dmp文件的頭部幾個字節中存儲Export用戶會話字符集的ID號。在這個轉換過程中可能發生數據的丟失。

例1: 如果源數據庫使用ZHS16GBK,而Export用戶會話字符集使用US7ASCII,由於ZHS16GBK是8位字符集,而US7ASCII是7位字符集,這個轉換過程中,中文字符在US7ASCII中不能夠找到對等的字符,所以所有中文字符都會丟失而變成“?? ”形式,即這種轉換後生成的Dmp文件已經發生了數據丟失。

例2: 如果源數據庫使用ZHS16GBK,而Export用戶會話字符集使用ZHS16CGB231280,但由於ZHS16GBK字符集是ZHS16CGB231280字符集的超集,這個過程中絕大部分字符都能夠正確轉換,只有一些超出ZHS16CGB231280字符集的字符變為“?? ”形式。如果源數據庫使用ZHS16CGB231280字符集,而Export用戶會話使用ZHS16GBK字符集,則轉換過程能夠完全轉換成功。

在Import向目標數據庫轉換過程中,其字符集發生轉換的情況正好與Export過程相反,這裡不再詳述。

在Export導出的Dmp文件中,含有Export用戶會話字符集。在Import過程中,首先發生的是Dmp文件字符集(即Export用戶會話字符集)向Import用戶會話字符集的轉換。如果這個轉換過程不能正確完成,Import向目標數據庫的導入過程也就不能完成。

進行字符集的正確轉換

通常情況下,我們在使用Oracle的Export和Import過程中,並不希望發生字符的轉換,但有時這種轉換卻是必要的。如我們在安裝Oracle數據庫時,選擇ZHS16CGB231280字符集,由於這種字符集是一種中文小字符集,對於一些漢字不能夠正確表示,這需要通過使用ZHS16GBK字符集得到解決,此時就要進行字符集的轉換。

為了確保Export、Import過程中,Oracle字符集不發生轉換或正確轉換,建議最好在進行這個過程前,檢查一下源數據庫字符集與Export用戶會話字符集是否一致,源數據庫字符集與目標數據庫字符集是否一致,目標數據庫字符與Import用戶會話字符集是否一致。如果能夠保證這四個字符集是一致的,則在Export、Import過程中,Oracle字符集就不用發生轉換。

可用以下辦法檢查數據庫字符集:

通過InitXXXX.ora文件進行查看;

借助SQL語句查看: SELECT NAME,VALUE$ FROM SYS.PROPS$ WHERE NAME=‘NLS_CHARACTERSET’。

對於Export、Import用戶會話字符集,在Windows系統中也可以通過注冊表中的NLS_LANG進行查看或修改,對於Unix系統則可通過設置用戶的環境變量NLS_LANG來查看或修改。

特別要注意的是,Oracle數據庫字符集通常是在創建時確定,一旦存儲用戶數據後就不要再修改了,因為其數據都是使用該字符集進行存儲的,改換其他字符集之後,原有數據就不能夠正確表示了。但如果確實想進行字符集改變,則可通過以下幾步來實現:

備份數據庫後刪除原數據(可物理備份,如使用Export,請注意確保字符集不發生轉換或數據無損失);

使用Internal用戶更新sys.props$表中的字符集:

Update sys.props$ set name=‘Dest.CharSet’
Where name=‘NLS_CHARACTERSET’; COMMIT;

重啟數據庫;

恢復數據。

下面字符集之間的轉換是可行的:

字符集子集向字符集父集轉換是可行的,如ZHS16CGB231280向ZHS16GBK轉換;而字符集父類向字符集子集進行轉換時,會損失部分數據。

只包含英文字符數據的雙字節字符集也可向單字節字符集轉換,如ZHS16GBK(English Only)可以向US7ASCII正確轉換。

編碼范圍相同的單字節字符集之間通常可以進行相互轉換。

請注意,這裡所說的沒有數據損失,是指一種字符集A轉換成另一種字符集B之後,可以再從字符集B正確轉換成字符集A或字符集B能夠正確表示字符集A中轉換過來的數據。

字符集對程序的影響 根據一個字符需要多少位字節來表示,可以把字符集分為單字節字符集和多字節字符集。其中,單字節字符集又分為7位字符集和8位字符集。單字節7位編碼字符集有US7ASCⅡ,單字節8位編碼字符集有符合ISO 8859-1標准規定的WE8ISO8859P1等。多字節編碼又分為固定長度(長度大於或等於2)編碼模式和不固定長度編碼模式。多字節編碼字符集中的ZHS16GBK、ZHS16CGB231280、JA16SJIS等是采用兩個字節表示一個字符的字符集,又叫雙字節字符集。

一個英文字母是一個字符,一個中文漢字是幾個字符呢?我們知道,一個中文漢字是雙字節字符,但它有幾個字符與其數據庫字符集有關。如果數據庫字符集使用單字節US7ASCII,則一個中文漢字是二個字符;如果數據庫字符集使用雙字節字符集ZHS16GBK,則一個中文漢字是一個字符。有關這一點可以使用Oracle的函數Substr得到證明。

使用US7ASCⅡ字符集時:

Select substr(‘東北大學’,1,2) from dual;

語句執行結果返回‘東’。

使用ZHS16GBK字符集時:

Select substr(‘東北大學’,1,2) from dual;

語句執行結果返回‘東北’。

選擇合適的數據庫字符集

選擇數據庫字符集時應考慮以下事項:

1.數據庫需要支持什麼語言

在為數據庫選擇字符集時,常會發現幾種字符集都適合你當前語言需求,如簡體中文就有ZHS16GBK和ZHSCGB231280等字符集可供選擇,應選擇哪種?在選擇字符集時,應考慮到數據庫將來的系統需求。如果知道將來數據庫要擴展支持不同的語言,選擇一個范圍較廣的字符集會是一個更好的主意。

2.系統資源與應用之間的互作用性

選擇的數據庫字符集應保證操作系統與應用之間的無縫連接。如果選擇的字符集不是操作系統有效的字符集,則系統就需要在這兩者之間做字符轉換。在這種字符轉換過程中,就有可能發生一些字符丟失現象。從一種字符集A向另一種字符集B轉換過程中,A中的字符必須在B中可以找到等價的字符,否則就會以“?”來代替。從這個意義上說,如果兩種字符集編碼范圍是相同的,則可以相互轉換。

字符集轉換過程中會影響系統性能,因此,應保證客戶端和服務器端有相同的字符集以避免字符集轉換,也可以提高一定的系統性能。

3.系統的性能要求

不同的數據庫字符集對於數據庫的性能是有一定影響的。為了得到最好的數據庫性能,選擇的數據庫字符集應避免字符轉換,並且要選擇對於期望的語言有最高效的編碼效率。通常,單字節字符集比多字節字符集有更優的性能表現,在空間需求方面也更小些。

4.其他一些限制

在為數據庫選擇一個合適的字符集時,應參考Oracle對應版本的相關文檔,檢查Oracle對於一些字符集的限制。如Oracle 8.1.5版本中,以下字符集是不能使用的: JA16EUCFIXED、ZHS16GBKFIXED、JA16DBCSFIXED、KO16DBCSFIXED、ZHS16DBCSFIXED、JA16SJISFIXED、ZHT32TRISFIXED。

綜上所述,正確理解Oracle字符集的轉換過程,可以使我們避免不必要的麻煩和數據損失。合理利用Oracle字符集的轉換過程,也可以幫助我們正確地從一種字符集轉換到另一種字符集,以滿足我們各種不同的應用需求。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved