天天看點

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字元集與資料庫字元集之間的轉換。

四. 檢視資料庫字元集

涉及三方面的字元集,

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檔案的字元集

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. 通常需要導出資料庫資料,重建資料庫,再導入資料庫資料的方式來轉換。

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;

--如果是從子集到父集,需要使用INTERNAL_USE 參數,跳過超子集檢測

SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8;

SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE AL32UTF8;

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>STARTUP MOUNT EXCLUSIVE;

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用戶端字元集設定方法

 或者在視窗設定:

        set nls_lang=AMERICAN_AMERICA.ZHS16GBK

      本文轉自crazy_charles 51CTO部落格,原文連結:http://blog.51cto.com/douya/1665643,如需轉載請自行聯系原作者