1. 程式人生 > >dos環境下執行dmp時顯示亂碼解決辦法之一

dos環境下執行dmp時顯示亂碼解決辦法之一

現象:windows系統dos環境下執行dmp指令碼時,中文資訊顯示為????亂碼

解決辦法1:統一字符集

(1)查詢資料庫字符集:一是Oracle server端的字符集,二是Oracle client端字符集,三是dmp檔案字符集;三者統一才能正確匯入;

       (1-1)查詢server端字符集:<1> SQL>select userenv('language') from dual;

                                                      結果類似為:AMERICAN_AMERICA.ZHS16GBK

                                                      <2> SQL>select * from nls_database_parameters;  來源於prop$,表示資料庫的字符集。

       (1-2)查詢client端字符集:

          windows平臺:<1>登錄檔中相應OracleHome的NLS_LANG;

                                   <2>dos視窗中設定,SQL>select * from nls_instance_parameters;  來源於V$parameter,表示客戶端字符集的設定,可能是引數檔案,環境變數或登錄檔。

         unix平臺:修改環境變數NLS_LANG

                          $echo $NLS_LANG

                          AMERICAN_AMERICA.ZHS16GBK

       (1-3)查詢dmp檔案字符集:dmp檔案的第2和第3個位元組記錄了dmp檔案的字符集。

             <1>dmp檔案較小(幾M或幾十M),用UltraEdit開啟(16進位制方式),看第2個和第3個位元組的內容,如0354,查詢:SQL>select nls_charect_name(to_number('0354','xxxx')) from dual;

           結果類似:ZHS16GBK

             <2>Zdmp檔案較大(比如2G),用文字編輯器開啟很慢或者完全打不開,可以以下命令(在nuix主機上):

                   cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6,然後用上述sql也可得到對應字符集。

       (1-4)查詢會話字符集:

                   SQL>select * from nls_session_parameter; 來源於V$nls_parameter,表示會話自己的設定,可能是會話的環境變數或者alter session完成,如果會話沒有特殊設定,將於nls_instance_parameter一致。

         備註:客戶端字元要求與服務端一致,才能正確顯示資料庫的非Ascii字元。如果多個設定存在的時候,alter session>環境變數>登錄檔>引數檔案 字符集要求一致,但語言設定可以不同,語言設定建議用英文。如字符集是ZHS16QBK,則nls_lang可以是AMERICAN_AMERICA.ZHS16GBK。

(2)修改字符集:

         oracle字符集有相互包容關係,如us7asc就是zhs16gbk的子集,從us7asc到zhs16gbk不會有資料解釋上的問題,不會有資料丟失。在所有字符集中utf8應該是最大,因為它是基礎Unicode雙位元組儲存字元。

        一旦資料庫建立後,資料庫的字符集理論上講是不能改變的。因此,在設計和安裝之初考慮使用哪一種字符集十分重要。根據Oracle的官方說明,字符集的轉換是從子集到超集受支援,反之不行。如果兩種字符集之間根本沒有子集和超集的關係,那麼字符集的轉換是不受oracle支援的。對資料庫server而言,錯誤的修改字符集將會導致很多不可測的後果,可能會嚴重影響資料庫的正常執行,所以在修改之前一定要確認兩種字符集是否存在子集和超集的關係。一般來說,除非萬不得已,我們不建議修改oracle資料庫server端的字符集。特別說明,我們最常用的兩種字符集ZHS16GBK和ZHS16CGB231280之間不存在子集和超集關係,因此理論上講這兩種字符集之間的相互轉換不受支援。

(2-1)修改server端字符集(不建議使用)

SQL>sqlplus /nolog

SQL>conn / as sysdba

SQL>shutdown immediate; --關閉資料庫伺服器

SQL>startup mount;

SQL>alert system enable restricted session;

SQL>alert system set job_queue_processes=0;

SQL>alert system set aq_tm_processes=0;

SQL>alert database open;

SQL>alert database character set zhs16gbk;

SQL>alert database national character set zhs16gbk;

SQL>shutdown immediate;

SQL>startup;

    備註:如果沒有大物件,在使用過程中進行語言轉換沒有什麼影響,(切記設定的字符集必須是oracle支援,不然不能start),按上面的做法就可以,但是可能會出現‘ORA-12717:Cannot ALERT DATABASE NATIONAL CHARACTER SET when NCLOB data exists’這樣的提示資訊;

解決辦法1:利用INTERNAL_USE 關鍵字修改區域設定;

SQL>shutdown immediate;

SQL>startup mount exclusive;

SQL>alert system enable restricted session;

SQL>alert system set job_queue_processes=0;

SQL>alert system set aq_tm_processes=0;

SQL>alert database open;

SQL>alert database national character set internal_use utf8;

SQL>shutdown immediate;

SQL>startup;

如果按上面的做法做,national charset的區域設定就沒有問題;

SQL>SQL>SQL>SQL>SQL>

解決辦法2:利用re-create,但是re-create有點複雜,所以請用internal_use;

(2-2)client修改字符集:

         比如set nls_lang=AMERICAN_AMERICA.ZHS16GBK;這個隻影響dos窗口裡的環境變數;

(2-3)修改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無法開啟,就需要用程式的方法了


小知識:

影響oracle資料庫字符集最重要的引數是NLS_LANG引數。
它的格式如下:   NLS_LANG = language_territory.charset
它有三個組成部分(語言、地域和字符集),每個成分控制了NLS子集的特性。

Language 指定伺服器訊息的語言,territory 指定伺服器的日期和數字格式,charset 指定字符集。如:AMERICAN _ AMERICA. ZHS16GBK

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

所以兩個資料庫之間的字符集只要第三部分一樣就可以相互匯入匯出資料,前面影響的只是提示資訊是中文還是英文。

參考部落格  http://blog.csdn.net/dream19881003/article/details/6800056

                http://blog.csdn.net/rbyyyblog/article/details/7397076