Oracle 字符集的查看和修改

一、什麼是 Oracle 字符集

       Oracle 字符集是一個字節數據的解釋的符號集合 , 有大小之分 , 有相互的包容關係。 ORACLE 支持國家語言的體系結構允許你使用本地化語言來存儲,處理,檢索數據。它使 數據庫 工具,錯誤消息,排序次序,日期,時間,貨幣,數字,和日曆自動適應本地化語言和平臺。

 

影響 Oracle 數據庫字符集最重要的參數是 NLS_LANG 參數。

它的格式 如下 : NLS_LANG = language_territory.charset

它有三個組成部分 ( 語言、地域和字符集 ) ,每個成分控制了 NLS 子集的特性。

其中 :

Language 指定服務器消息的語言, 影響提示信息是中文還是英文

Territory 指定服務器的日期和數字格式,

Charset   指定字符集。

:AMERICAN _ AMERICA. ZHS16GBK

NLS_LANG 的組成我們可以看出,真正影響數據庫字符集的其實是第三部分

所以兩個數據庫之間的字符集只要第三部分一樣就可以相互導入導出數據,前面影響的只是提示信息是中文還是英文

 

二.字符集的相關知識:

2.1 字符集
   
實質就是按照一定的字符編碼方案,對一組特定的符號,分別賦予不同數值編碼的集合。 Oracle 數據庫最早支持的編碼方案是 US7ASCII
    Oracle
的字符集命名遵循以下命名規則 :
    <Language><bit size><encoding>
   
: < 語言 >< 比特位數 >< 編碼
>
   
比如 : ZHS16GBK 表示採用 GBK 編碼格式、 16 位(兩個字節)簡體中文字符集

 
2.2
字符編碼方案


2.2.1
單字節編碼
   
1 單字節 7 位字符集 ,可以定義 128 個字符,最常用的字符集爲 US7ASCII
   
2 單字節 8 位字符集 ,可以定義 256 個字符,適合於歐洲大部分國家

            
例如: WE8ISO8859P1( 西歐、 8 位、 ISO 標準 8859P1 編碼 )

 

2.2.2 多字節編碼
   
1 )變長多字節編碼
   
某些字符用一個字節表示,其它字符用兩個或多個字符表示,變長多字節編碼常用於對亞洲語言的支持,    例如日語、漢語、印地語等
   
例如: AL32UTF8 (其中 AL 代表 ALL, 指適用於所有語言)、 zhs16cgb231280
   
2 )定長多字節編碼

   
每一個字符都使用固定長度字節的編碼方案,目前 oracle 唯一支持的定長多字節編碼是 AF16UTF16 ,也是僅用於國家字符集

2.2.3 unicode 編碼
    Unicode
是一個涵蓋了目前全世界使用的所有已知字符的單一編碼方案,也就是說 Unicode 爲每一個字符提供唯一的編碼。 UTF-16 unicode 16 位編碼方式 ,是一種定長多字節 編碼,用 2 個字節表示一個 unicode 字符, AF16UTF16 UTF-16 編碼字符集
    UTF-8
unicode 8 位編碼方式 ,是一種變長多字節 編碼,這種編碼可以用 1 2 3 個字節表示一個 unicode 字符, AL32UTF8 UTF8 UTFE UTF-8 編碼字符集
 
2.3
字符集超級

   
當一種字符集(字符集 A )的編碼數值包含所有另一種字符集(字符集 B )的編碼數值,並且兩種字符集相同編碼數值代表相同的字符時,則字符集 A 是字符集 B 的超級,或稱字符集 B 是字符集 A 的子集。
    Oracle8i
oracle9i 官方文檔資料中備有子集 - 超級對照表( subset-superset pairs ,例如: WE8ISO8859P1 WE8MSWIN1252 的子集。由於 US7ASCII 是最早的 Oracle 數據庫編碼格式,因此有許多字符集是 US7ASCII 的超集,例如 WE8ISO8859P1 ZHS16CGB231280 ZHS16GBK 都是 US7ASCII 的超集。
 
2.4
數據庫字符集( oracle 服務器端字符集)

   
數據庫字符集在創建數據庫時指定,在創建後通常不能更改 。在創建數據庫時,可以指定字符集 (CHARACTER SET) 和國家字符集 (NATIONAL CHARACTER SET)

 

2.4.1 字符集
    (1)
用來存儲 CHAR, VARCHAR2, CLOB, LONG 等類型數據
    (2)
用來標示諸如表名、列名以及 PL/SQL 變量等
    (3)
用來存儲 SQL PL/SQL 程序單元等

 

2.4.2 國家字符集:
    (1)
用以存儲 NCHAR, NVARCHAR2, NCLOB 等類型數據
    (2)
國家字符集實質上是爲 oracle 選擇的附加字符集,主要作用是爲了增強 oracle 的字符處理能力,因爲 NCHAR 數據類型可以提供對亞洲使用定長多字節編碼的支持,而數據庫字符集則不能。國家字符集在 oracle9i 中進行了重新定義,只能在 unicode 編碼中的 AF16UTF16 UTF8 中選擇,默認值是 AF16UTF16

 

2.4.3 查詢字符集參數
   
可以查詢以下數據字典或視圖查看字符集設置情況
    nls_database_parameters
props$ v$nls_parameters
   
查詢結果中 NLS_CHARACTERSET 表示字符集 NLS_NCHAR_CHARACTERSET 表示國家字符集

 

2.4.4 修改數據庫字符集
   
按照上文所說,數據庫字符集在創建後原則上不能更改 。不過有 2 種方法可行。

 

1. 如果需要修改字符集,通常需要導出數據庫數據,重建數據庫,再導入數據庫數據的方式來轉換

2. 通過 ALTER DATABASE CHARACTER SET 語句修改字符集, 但創建數據庫後修改字符集是有限制的,只有新的字符集是當前字符集的超集時才能修改數據庫字符集 ,例如 UTF8 US7ASCII 的超集,修改數據庫字符集可使用 ALTER DATABASE CHARACTER SET UTF8
 
2.5
客戶端字符集( NLS_LANG 參數)


2.5.1
客戶端字符集含義
   
客戶端字符集定義了客戶端字符數據的編碼方式,任何發自或發往客戶端的字符數據均使用客戶端定義的字符集編碼 , 客戶端可以看作是能與數據庫直接連接的各種應用,例如 sqlplus,exp/imp 等。客戶端字符集是通過設置 NLS_LANG 參數來設定的。

 

2.5.2 NLS_LANG 參數格式
    NLS_LANG=<language>_<territory>.<client character set>
    Language:
顯示 oracle 消息 , 校驗,日期命名
    Territory
指定默認日期、數字、貨幣等格式
    Client character set
指定客戶端將使用的字符集
   
例如: NLS_LANG=AMERICAN_AMERICA.US7ASCII
    AMERICAN
是語言, AMERICA 是地區, US7ASCII 是客戶端字符集

 

2.5.3 客戶端字符集設置方法
     1)UNIX
環境
         $NLS_LANG=“simplified chinese”_china.zhs16gbk
         $export NLS_LANG
        
編輯 oracle 用戶的 profile 文件
    2)Windows
環境
        
編輯註冊表
         Regedit.exe ---
HKEY_LOCAL_MACHINE --- SOFTWARE --- ORACLE-HOME

 

2.5.4 NLS 參數查詢
    Oracle
提供若干 NLS 參數定製數據庫和用戶機以適應本地格式,例如有 NLS_LANGUAGE ,NLS_DATE_FORMAT ,NLS_CALENDER 等,可以通過查詢以下數據字典或 v$ 視圖查看。
NLS_DATABASE_PARAMETERS:
顯示數據庫當前 NLS 參數取值,包括數據庫字符集取值
NLS_SESSION_PARAMETERS
  顯示由 NLS_LANG 設置的參數,或經過 alter session 改變後的參數值(不包括由 NLS_LANG 設置的客戶端字符集)
NLS_INSTANCE_PARAMETE
顯示由參數文件 init<SID>.ora 定義的參數

V$NLS_PARAMETERS 顯示數據庫當前 NLS 參數取值

 

2.5.5 修改 NLS 參數
   
使用下列方法可以修改 NLS 參數
   
1 )修改實例啓動時使用的初始化參數文件
   
2 )修改環境變量 NLS_LANG
   
3 )使用 ALTER SESSION 語句,在 oracle 會話中修改

   
4 )使用某些 SQL 函數
    NLS
作用優先級別 Sql function > alter session > 環境變量或註冊表 > 參數文件 > 數據庫默認參數

 

三. EXP/IMP 字符集

3.1 EXP/IMP
    Export
Import 是一對讀寫 Oracle 數據的工具。 Export Oracle 數據庫中的數據輸出到操作系統文件中 , Import 把這些文件中的數據讀到 Oracle 數據庫中,由於使用 exp/imp 進行數據遷移時,數據從源數據庫到目標數據庫的過程中有四個環節涉及到字符集,如果這四個環節的字符集不一致,將會發生字符集轉換。
EXP
     ____________ _________________ _____________
     |imp
導入文件 |<-| 環境變量 NLS_LANG|<-| 數據庫字符集
|
      ------------   -----------------   -------------

IMP
     ____________ _________________ _____________
     |imp
導入文件 |->| 環境變量 NLS_LANG|->| 數據庫字符集
|
      ------------   -----------------   -------------

 

 

四個字符集是
  
1 )源數據庫字符集
  
2 Export 過程中用戶會話字符集(通過 NLS_LANG 設定)

  
3 Import 過程中用戶會話字符集(通過 NLS_LANG 設定)
  
4 )目標數據庫字符集
 
3.2
導出的轉換過程

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


: 如果源數據庫使用 ZHS16GBK ,而 Export 用戶會話字符集使用 US7ASCII ,由於 ZHS16GBK 16 位字符集 , US7ASCII 7 位字符集,這個轉換過程中,中文字符在 US7ASCII 中不能夠找到對等的字符,所以所有中文字符都會丟失而變成 “?? ” 形式,這樣轉換後生成的 Dmp 文件已經發生了數據丟失。
因此如果想正確導出源數據庫數據,則 Export 過程中用戶會話字符集應等於源數據庫字符集或是源數據庫字符集的超集
 
3.3
導入的轉換過程

   
1 )確定導出數據庫字符集環境
            
通過讀取導出文件頭,可以獲得導出文件的字符集設置
   
2 )確定導入 session 的字符集,即導入 Session 使用的 NLS_LANG 環境變量
   
3 IMP 讀取導出文件
            
讀取導出文件字符集 ID ,和導入進程的 NLS_LANG 進行比較
   
4 )如果導出文件字符集和導入 Session 字符集相同,那麼在這一步驟內就不需要轉換,              如果不同,就需要把數據轉換爲導入 Session 使用的字符集。可以看出,導入數據到數據庫過程中發生兩次字符集轉換


   
第一次 : 導入文件字符集與導入 Session 使用的字符集之間的轉換,如果這個轉換過程不能正確完成, Import 向目標數據庫的導入過程也就不能完成。
   
第二次 : 導入 Session 字符集與數據庫字符集之間的轉換。

 

. 查看數據庫字符集

涉及三方面的字符集,

1. oracel server 端的字符集 ;

2. oracle client 端的字符集 ;

3. dmp 文件的字符集。

 

在做數據導入的時候,需要這三個字符集都一致才能正確導入。

 

4.1 查詢 oracle server 端的字符集

有很多種方法可以查出 oracle server 端的字符集,比較直觀的查詢方法是以下這種 :

SQL> select userenv('language') from dual;

USERENV('LANGUAGE')

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

SIMPLIFIED CHINESE_CHINA.ZHS16GBK

 

SQL>select userenv(‘language’) from dual;

AMERICAN _ AMERICA. ZHS16GBK

 

4.2 如何查詢 dmp 文件的字符集

oracle exp 工具導出的 dmp 文件也包含了字符集信息, dmp 文件的第 2 和第 3 個字節記錄了 dmp 文件的字符集 。如果 dmp 文件不大,比如只有幾 M 或幾十M ,可以用 UltraEdit 打開 (16 進制方式 ) ,看第 2 3 個字節的內容,如 0354 ,然後用以下 SQL 查出它對應的字符集 :

SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;

ZHS16GBK

 

如果 dmp 文件很大,比如有 2G 以上 ( 這也是最常見的情況 ) ,用文本編輯器打開很慢或者完全打不開,可以用以下命令 ( unix 主機上 ):

cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6

然後用上述 SQL 也可以得到它對應的字符集。

 

4.3 查詢 oracle client 端的字符集

windows 平臺下,就是註冊表裏面相應 OracleHome NLS_LANG 。還可以在 dos 窗口裏面自己設置,

比如 : set nls_lang=AMERICAN_AMERICA.ZHS16GBK

這樣就隻影響這個窗口裏面的環境變量。

 

unix 平臺下,就是環境變量 NLS_LANG

$echo $NLS_LANG

AMERICAN_AMERICA.ZHS16GBK

 

如果檢查的結果發現 server 端與 client 端字符集不一致,請統一修改爲同 server 端相同的字符集。

 

補充:

(1). 數據庫服務器字符集

select * from nls_database_parameters

來源於 props$ ,是表示數據庫的字符集。

 

(2). 客戶端字符集環境

select * from nls_instance_parameters

其來源於 v$parameter ,表示客戶端的字符集的設置,可能是參數文件,環境變量或者是註冊表

 

(3). 會話字符集環境

select * from nls_session_parameters

來源於 v$nls_parameters ,表示會話自己的設置,可能是會話的環境變量或者是 alter session 完成,如果會話沒有特殊的設置,將與 nls_instance_parameters 一致。

 

(4). 客戶端的字符集要求與服務器一致,才能正確顯示數據庫的非 Ascii 字符

如果多個設置存在的時候, NLS 作用優先級別 Sql function > alter session > 環境變量或註冊表 > 參數文件 > 數據庫默認參數

 

字符集要求一致,但是語言設置卻可以不同,語言設置建議用英文。如字符集是 zhs16gbk ,則 nls_lang 可以是 American_America.zhs16gbk

 

 

五. 修改 oracle 的字符集

按照上文所說,數據庫字符集在創建後原則上不能更改 。因此,在設計和安裝之初考慮使用哪一種字符集十分重要。對數據庫 server 而言,錯誤的修改字符集將會導致很多不可測的後果,可能會嚴重影響數據庫的正常運行,所以在修改之前一定要確認兩種字符集是否存在子集和超集的關係。一般來說,除非萬不得已,我們不建議修改 oracle 數據庫 server 端的字符集。特別說明,我們最常用的兩種字符集 ZHS16GBK ZHS16CGB231280 之間不存在子集和超集關係,因此理論上講這兩種字符集之間的相互轉換不受支持。

 

不過修改字符集有 2 種方法可行。

1. 通常需要導出數據庫數據,重建數據庫,再導入數據庫數據的方式來轉換

2. 通過 ALTER DATABASE CHARACTER SET 語句修改字符集, 但創建數據庫後修改字符集是有限制的,只有新的字符集是當前字符集的超集時才能修改數據庫字符集 ,例如 UTF8 US7ASCII 的超集,修改數據庫字符集可使用 ALTER DATABASE CHARACTER SET UTF8
 

 

5.1 修改 server 端字符集 ( 不建議使用 )

 

1.        關閉數據庫

SQL> SHUTDOWN IMMEDIATE

 

2. 啓動到 Mount

SQL>STARTUP MOUNT;

SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;

SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;

SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;

SQL>ALTER DATABASE OPEN;

SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;

SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;

SQL>SHUTDOWN IMMEDIATE;

SQL>STARTUP

注意: 如果沒有大對象,在使用過程中進行語言轉換沒有什麼影響,(切記設定的字符集必須是 ORACLE 支持,不然不能 start 按上面的做法就可以。

 

若出現 ‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’ 這樣的提示信息,

要解決這個問題有兩種方法

1. 利用 INTERNAL_USE 關鍵字修改區域設置 ,

2. 利用 re-create, 但是 re-create 有點複雜 , 所以請用 internal_use

 

SQL>SHUTDOWN IMMEDIATE;

SQL>STARTUP MOUNT EXCLUSIVE;

SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;

SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;

SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;

SQL>ALTER DATABASE OPEN;

SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;

SQL>SHUTDOWN immediate;

SQL>startup;

如果按上面的做法做 ,National charset 的區域設置就沒有問題

 

5.2 修改 dmp 文件字符集

上文說過, dmp 文件的第 2 3 字節記錄了字符集信息,因此直接修改 dmp 文件的第 2 3 字節的內容就可以 oracle 的檢查。這樣做理論上也僅是從子集到超集可以修改,但很多情況下在沒有子集和超集關係的情況下也可以修改 ,我們常用的一些字符集,如 US7ASCII WE8ISO8859P1 ZHS16CGB231280 ZHS16GBK 基本都可以改。因爲改的只是 dmp 文件,所以影響不大。

 

具體的修改方法比較多,最簡單的就是直接用 UltraEdit 修改 dmp 文件的第 2 和第 3 個字節。

比如想將 dmp 文件的字符集改爲 ZHS16GBK ,可以用以下 SQL 查出該種字符集對應的 16 進制代碼 : SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual;

0354

然後將 dmp 文件的 2 3 字節修改爲 0354 即可。

如果 dmp 文件很大,用 ue 無法打開,就需要用程序的方法了。

 

5.3 客戶端字符集設置方法
     1)UNIX
環境
         $NLS_LANG=“simplified chinese”_china.zhs16gbk
         $export NLS_LANG
        
編輯 oracle 用戶的 profile 文件
    2)Windows
環境
        
編輯註冊表
         Regedit.exe ---
HKEY_LOCAL_MACHINE --- SOFTWARE --- ORACLE-HOME

  或者在窗口設置:

         set nls_lang=AMERICAN_AMERICA.ZHS16GBK

發佈了66 篇原創文章 · 獲贊 7 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章