oracle字符集相關問題

整理自網絡+實驗
字符集介紹
影響Oracle數據庫字符集最重要的參數是NLS_LANG參數。
它的格式以下: NLS_LANG = language_territory.charset
 NLS_LANG參數由如下部分組成:
NLS_LANG=<Language>_<Territory>.<Clients Characterset>
NLS_LANG各部分含義以下:
LANGUAGE指定:
-Oracle消息使用的語言
-日期中月份和日顯示
TERRITORY指定
-貨幣和數字格式
-地區和計算星期及日期的習慣
從NLS_LANG的組成咱們能夠看出,真正影響數據庫字符集的實際上是第三部分。
因此兩個數據庫之間的字符集只要第三部分同樣就能夠相互導入導出數據,前面影響的只是提示信息是中文仍是英文.
 
字符集
    實質就是按照必定的字符編碼方案,對一組特定的符號,分別賦予不一樣數值編碼的集合。Oracle數據庫最先支持的編碼方案是US7ASCII。
    Oracle的字符集命名遵循如下命名規則:
    <Language><bit size><encoding>
    即: <語言><比特位數><編碼>
    好比: ZHS16GBK表示採用GBK編碼格式、16位(兩個字節)簡體中文字符集
如何查詢數據庫字符集 
 
EXP/IMP 與 字符集
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)目標數據庫字符集

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

例:若是源數據庫使用ZHS16GBK,而Export用戶會話字符集使用US7ASCII,因爲ZHS16GBK是16位字符集,而US7ASCII是7位字符集,這個轉換過程當中,中文字符在US7ASCII中不可以找到對等的字符,因此全部中文字符都會丟失而變成「?? 」形式,這樣轉換後生成的Dmp文件已經發生了數據丟失。
所以若是想正確導出源數據庫數據,則Export過程當中用戶會話字符集應等於源數據庫字符集或是源數據庫字符集的超集

5.3導入的轉換過程
    (1)肯定導出數據庫字符集環境
             經過讀取導出文件頭,能夠得到導出文件的字符集設置
    (2)肯定導入session的字符集,即導入Session使用的NLS_LANG環境變量
    (3)IMP讀取導出文件
             讀取導出文件字符集ID,和導入進程的NLS_LANG進行比較
    (4)若是導出文件字符集和導入Session字符集相同,那麼在這一步驟內就不須要轉換,             若是不一樣,就須要把數據轉換爲導入Session使用的字符集。能夠看出,導入數據到數據庫過程當中發生兩次字符集轉換

    第一次:導入文件字符集與導入Session使用的字符集之間的轉換,若是這個轉換過程不能正確完成,Import向目標數據庫的導入過程也就不能完成。
    第二次:導入Session字符集與數據庫字符集之間的轉換。
SQL> select userenv('language') from dual;

USERENV('LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK
 
 
dmp文件字符集查看(EXP)
 
SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;

NLS_CHARSET_NAME(TO_NUMBER('0354','XXXX'))
--------------------------------------------------------------------------------
ZHS16GBK
 
若是dmp文件很大,好比有2G以上(這也是最多見的狀況),用文本編輯器打開很慢或者徹底打不開,能夠用如下命令(在unix主機上):
 
[root@NETDATA11G-01 ~]#.cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6
0345
 
查詢oracle client端的字符集
在windows平臺下,就是註冊表裏面相應OracleHome的NLS_LANG。還能夠在dos窗口裏面本身設置,
好比: set nls_lang=AMERICAN_AMERICA.ZHS16GBK
通常出現最多問題就是plsqldevelop問題
在sqlplus 創建一個腳本
@echo off
 set nls_lang=數據庫端字符集
start plsqldevelop.exe
 
linux 客戶端建議在環境變量裏面設置
NLS_LANG=American_America.zhs16gbk;export NLS_LANG
 
查詢數據庫字符集
SQL> set line 200
SQL> col VALUE format A50
SQL> col parameters format A20
SQL> select * from nls_database_parameters;

PARAMETER                 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

PARAMETER                 VALUE
------------------------------ --------------------------------------------------
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.
 
SQL> select '測試' from dual;

'測
------
測試

SQL>
 
 
 
常見問題
imp導入亂碼
修改dmp文件字符集
上文說過,dmp文件的第2第3字節記錄了字符集信息,所以直接修改dmp文件的第2第3字節的內容就能夠‘騙’過oracle的檢查。這樣作理論上也僅是從子集到超集能夠修改,但不少狀況下在沒有子集和超集關係的狀況下也能夠修改,咱們經常使用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本均可以改。由於改的只是dmp文件,因此影響不大。
 
總結
修改NLS參數
    使用下列方法能夠修改NLS參數
    (1)修改實例啓動時使用的初始化參數文件
    (2)修改環境變量NLS_LANG
    (3)使用ALTER SESSION語句,在oracle會話中修改
    (4)使用某些SQL函數
客戶端的字符集要求與服務器一致,才能正確顯示數據庫的非Ascii字符。
若是多個設置存在的時候,NLS做用優先級別:Sql function > alter session > 環境變量或註冊表> 參數文件> 數據庫默認參數
字符集要求一致,可是語言設置卻能夠不一樣,語言設置建議用英文。如字符集是zhs16gbk,則nls_lang能夠是American_America.zhs16gbk 
 
修改服務器端字符集
 數據庫字符集在建立後原則上不能更改。所以,在設計和安裝之初考慮使用哪種字符集十分重要。對數據庫server而言,錯誤的修改字符集將會致使不少不 可測的後果,可能會嚴重影響數據庫的正常運行,因此在修改以前必定要確認兩種字符集是否存在子集和超集的關係。通常來講,除非萬不得已,咱們不建議修改 oracle數據庫server端的字符集。特別說明,咱們最經常使用的兩種字符集ZHS16GBK和ZHS16CGB231280之間不存在子集和超集關 系,所以理論上講這兩種字符集之間的相互轉換不受支持。
 不過修改字符集有2種方法可行。
1. 一般須要導出數據庫數據,重建數據庫,再導入數據庫數據的方式來轉換。
2. 經過ALTER DATABASE CHARACTER SET語句修改字符集,但建立數據庫後修改字符集是有限制的,只有新的字符集是當前字符集的超集時才能修改數據庫字符集,例如UTF8是US7ASCII的超集,修改數據庫字符集可以使用ALTER DATABASE CHARACTER SET UTF8。
啓動到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 AL16UTF16; --若是是從子集到父集,須要使用INTERNAL_USE 參數,跳過超子集檢測 SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8; SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE AL16UTF16;
相關文章
相關標籤/搜索