Oracle字符集是一個(gè)字節(jié)數(shù)據(jù)的解釋的符號(hào)集合,有大小之分,有相互的包容關(guān)系。ORACLE 支持國(guó)家語(yǔ)言的體系結(jié)構(gòu)允許你使用本地化語(yǔ)言來(lái)存儲(chǔ),處理,檢索數(shù)據(jù)。它使數(shù)據(jù)庫(kù)工具,錯(cuò)誤消息,排序次序,日期,時(shí)間,貨幣,數(shù)字,和日歷自動(dòng)適應(yīng)本地化語(yǔ)言和平臺(tái)。
Oracle 在進(jìn)行dmp備份和還原的時(shí)候,服務(wù)器端字符集和客戶端字符集會(huì)對(duì)這個(gè)過(guò)程有較大影響,特別是數(shù)據(jù)表中存儲(chǔ)了中文、存儲(chǔ)過(guò)程中使用了中文編碼(注釋)的時(shí)候,如果沒(méi)有處理好字符集的問(wèn)題,在進(jìn)行還原的時(shí)候就會(huì)遇到問(wèn)題,我所遇到過(guò)的問(wèn)題有一下幾種:
1:導(dǎo)入后數(shù)據(jù)表中存儲(chǔ)的中文字符成了亂碼;
2:導(dǎo)入后存儲(chǔ)過(guò)程中的中文字符成了亂碼;
3:導(dǎo)入時(shí),提示某些存儲(chǔ)過(guò)程不存在,報(bào)IMP-00098 INTERNAL ERROR:impccr2錯(cuò)誤:
其中問(wèn)題1出現(xiàn)的原因是源數(shù)據(jù)庫(kù)使用的字符集和你現(xiàn)在導(dǎo)入的目標(biāo)數(shù)據(jù)庫(kù)字符集不一致,且目標(biāo)數(shù)據(jù)庫(kù)字符集不是源數(shù)據(jù)庫(kù)字符集的超集。解決辦法是修改目標(biāo)數(shù)據(jù)庫(kù)的字符集(這個(gè)字符集是在創(chuàng)建數(shù)據(jù)庫(kù)實(shí)例的時(shí)候設(shè)置的),改成和源數(shù)據(jù)庫(kù)一致,再執(zhí)行導(dǎo)入操作,可以解決數(shù)據(jù)表中中文字符亂碼問(wèn)題。
問(wèn)題2和問(wèn)題3的解決辦法,修改客戶端字符集,檢查你的系統(tǒng)環(huán)境變量NLS_LANG的值或者注冊(cè)表HKEY_LOCAL_MACHINE-->SOFTWARE-->ORACLE 在這個(gè)分支下面找NLS_LANG鍵,修改這個(gè)鍵值再重新導(dǎo)入數(shù)據(jù)即可。
最后我們需要知道字符集應(yīng)該改成什么?
方法一:去源數(shù)據(jù)庫(kù)上查詢
需要用到的視圖: nls_database_parameters、props$、v$nls_parameters
方法二:查看導(dǎo)入的時(shí)候sqlplus中的提示信息:
最后一行可以看到,export client uses ....也就是說(shuō)導(dǎo)出客戶端使用的字符集是ZHS16GBK,而且根據(jù)當(dāng)前的設(shè)置,是有可能進(jìn)行字符集的轉(zhuǎn)換(也就意味著有可能出現(xiàn)亂碼,如果現(xiàn)在用的字符集不是導(dǎo)出字符集的超集)。所以這里就用該把導(dǎo)入數(shù)據(jù)庫(kù)客戶端字符集設(shè)置成ZHS16GBK,再執(zhí)行導(dǎo)入可以解決問(wèn)題。
網(wǎng)上有些辦法是修改dmp文件,個(gè)人認(rèn)為,如果是目標(biāo)數(shù)據(jù)庫(kù)端字符集不滿足要求,可以采用這種方法修改dmp文件,畢竟server端字符集不能隨便更改(生產(chǎn)server一個(gè)實(shí)例下可能有多個(gè)應(yīng)用系統(tǒng)的用戶數(shù)據(jù))。如果是客戶端字符集問(wèn)題,建議還是修改一下客戶端字符集配置,等導(dǎo)入完成之后再把客戶端字符集修改回來(lái)。
打開(kāi)dmp文件,它的字符集是US7ASCII,我的服務(wù)器和客戶端都是ZHS16GBK,有人說(shuō)只要把dmp文件字符集修改就可以,但修改后文件就無(wú)法導(dǎo)入,報(bào)錯(cuò)說(shuō)文件無(wú)效。我又試著把我服務(wù)器和客戶端字符集改成US7ASCII,結(jié)果sql*plus打開(kāi)就亂碼,導(dǎo)入dmp文件后數(shù)據(jù)也還是亂碼。。
修改數(shù)據(jù)庫(kù)字符集為'us7ascii'。
查看數(shù)據(jù)庫(kù)當(dāng)前數(shù)據(jù)集有兩種方式:
a).select name,value$ from props$ where name like '%NLS_CHARACTERSET%',
b).select userenv('language') from dual;
1.常規(guī)方案修改數(shù)據(jù)庫(kù)字符集
1).sys登陸數(shù)據(jù)庫(kù):conn / as sysdba;
2).關(guān)閉數(shù)據(jù)庫(kù):shutdown immediate;
3).以mount方式開(kāi)啟數(shù)據(jù)庫(kù):startup mount;
4).限制其它用戶連接數(shù)據(jù)庫(kù)使用資源: alter system enable restricted session;
5).查看系統(tǒng)當(dāng)前的進(jìn)程(最大連接數(shù)):show parameter processes;記住job_queue_processes參數(shù)的當(dāng)前值,后面需要修改回來(lái)。
6).殺掉CJQ0及相應(yīng)job進(jìn)程: alter system set job_queue_processes=0;
7).修改隊(duì)列監(jiān)視進(jìn)程參數(shù)alter system set aq_tm_processes=0;
8).更改數(shù)據(jù)庫(kù)為open方式:alter database open;
9).更改字符集:alter database character set us7ascii;
a).如果當(dāng)前數(shù)據(jù)庫(kù)的字符集是系統(tǒng)字符集us7asci的超集,更改不會(huì)出問(wèn)題;如果不是,將會(huì)提示:
ORA-12712: 新字符集必須為舊字符集的超集
b).如果數(shù)據(jù)庫(kù)數(shù)據(jù)有CLOB類型,系統(tǒng)將會(huì)提示:
ORA-12716: Cannot ALTER DATABASE CHARACTER SET when CLOB data exists
2. 針對(duì)以上的錯(cuò)誤a)的解決方案:使用INTERNAL_USE跳過(guò)超集檢測(cè)
ALTER DATABASE character set INTERNAL_USE us7ascii;
3. 針對(duì)以上的錯(cuò)誤b)的解決方案:使用internal_convert轉(zhuǎn)換含有CLOB字段的表
1).截?cái)啾韙runcate table Metastylesheet;
2).alter database character set internal_convert zhs16gbk;-- ORACLE會(huì)自動(dòng)轉(zhuǎn)換含有CLOB
3).因?yàn)榍懊媲蹇樟薙YS.METASTYLESHEET表,需要重新創(chuàng)建
9.2通過(guò)運(yùn)行catmet.sql腳本來(lái)重建;@?/rdbms/admin/catmet.sql
10g后通過(guò)運(yùn)行catmeta.sql腳本來(lái)重建:@?/rdbms/admin/catmeta.sql
(注意這個(gè)地方有待商榷,不確定,最好不要使用這種方法修改)
4.完成方案a)和b)后再做如下步驟:
1).查看當(dāng)前字符集,確認(rèn)是否正確修改select userenv('language') from dual;
2).解除限制:
alter system disable restricted session;
alter system set job_queue_processes=10;--修改回開(kāi)始記錄的原始值
3).最好也也設(shè)置一下set NLS_LANG 環(huán)境變量
4).關(guān)閉數(shù)據(jù)庫(kù)再打開(kāi);