以前也看了一些關於字符集轉換的文章
但是實際使用的時候還是發生了問題
出現了亂碼
為了徹底搞清楚字符集問題
我決定做測試
用EXP/IMP工具在不同字符集之間互相轉換數據
環境
兩台測試PC機器
分稱A機器(
)和B機器(
)
兩台機器的配置都是一致的
安裝WIN
操作系統和Oracle
數據庫
計劃從A機器導出包含有中文的數據
然後倒入到B機器中
測試計劃 分別在兩台機器上安裝兩個instance
這兩個instance又分別是中
英文字符集
為了簡單起見
國家字符集和字符集設置都是一樣的
就是說
設置成英文字符集的時候
上面說的兩個設置都是US
ASCII
設置中文字符集的時候都是ZHS
GBK
我沒有考慮國家字符集和字符集不一致的情況
客戶端也分成C
D兩個部分
實際測試的時候C和D是一個客戶端
因為如果A和C的字符集不一致
是不允許導出的
同樣
如果B和D的字符集不一致
是不允許導入的
在C機器上建立四個服務指向上面新建的
個instance
c
中文 在A機器上
e
英文 在A機器上
c
中文 在B機器上
e
英文 在B機器上
四個進程都建立相同的用戶和表
Connect system/manager
Create user test identified by test default tablespace users temporary tablespace temp;
Grant connect
resource to test;
Connect test/test
Create table emp(id number(
)
address varchar
(
));
然後只在A機器上的兩個進程中插入數據
Insert into emp(id
address) values(
北京市
);
Insert into emp(id
address) values(
成都市
);
Insert into emp(id
address) values(
上海市
);
Insert into emp(id
address) values(
天津市
);
Insert into emp(id
address) values(
重慶市
);
Insert into emp(id
address) values(
武漢市
);
Insert into emp(id
address) values(
廣州市
);
Commit;
然後測試
過程如下
一在C機器上測試C機器是英文字符集 exp system/manager@
c file=c:
c
dmp owner=test
exp system/manager@
e file=c:
e
dmp owner=test
都導出成功
發現上面兩個文件的ACSII字符集都是
二在C機器上測試C機器換成中文字符集 exp system/manager@
c file=c:
c
dmp owner=test
exp system/manager@
e file=c:
e
dmp owner=test
發現上面兩個文件的ACSII字符集都是
A機器上的數據庫變換字符集
就是把原來英文字符集數據庫換成中文字符集
把原來中文字符集數據庫換成英文字符集
備注
之後沒有把原來的數據刪掉重新錄入中文數據
而是用以前的舊的數據
後來發現
原來英文字符集數據庫換成中文字符集後
數據可以正常顯示
反之
中文字符集數據庫換成英文字符集後
數據已經是亂碼了
已經不能正常顯示了
原因
中文字符集占兩個字節
英文字符集占一個字節
所以當中文轉換成英文的時候
數據庫壓縮
數據就無法正常顯示了
反過來可以正常顯示
所以推薦建立數據庫的時候用英文字符集
好處多多(包括全文索引的時候)
所以後來倒出的
c
dmp和
c
dmp實際上包含的數據都已經是不對的
測試已經沒有意義了
於是我重新進行試驗
在變換數據庫字符集後
刪掉原來的數據庫emp表中的數據
插入正確的數據
保證源數據庫中的數據是可用的
重新測試
然後把A機器上的數據庫變換字符集
就是原來是中文的數據庫我換成英文
原來是英文的數據庫我換成中文
采用的方法是修改props$表
三A機器上的數據庫變換字符集後 C機器上導出操作
C機器是英文字符集
exp system/manager@
c file=c:
c
dmp owner=test
exp system/manager@
e file=c:
e
dmp owner=test
都導出成功
發現上面兩個文件的ACSII字符集都是
四A機器上的數據庫變換字符集後 C機器上導出操作
C機器是中文字符集
exp system/manager@
c file=c:
c
dmp owner=test
exp system/manager@
e file=c:
e
dmp owner=test
都導出成功
發現上面兩個文件的ACSII字符集都是
備份上面導出的
個數據文件
這時候修改上面導出的
個文件的ACSII字符集
進行中英文互換
把
和
互換
修改後的文件名都加了一個
_
標記
小結 導出的時候
如果客戶端和數據庫的字符集設置不一致
導出的時候Oracle並沒有提示
導出文件的ACSII字符集和客戶端的字符集設置有關
與被導數據庫字符集的設置無關
****************************************
**** 導入操作 ****
****************************************
一向B的c倒入操作客戶機D是英文字符集 D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是改成中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是中文客戶端導出的中文數據庫文件
ASCII字符集是中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是中文客戶端導出的中文數據庫文件
但是ASCII字符集是改成英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
ASCII字符集是英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
但是ASCII字符集是改成中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是中文客戶端導出的英文數據庫文件
但是數據庫是換過的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是英文客戶端導出的英文數據庫文件
ASCII字符集是英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是英文客戶端導出的英文數據庫文件
但是ASCII字符集是換成中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集侵形模?e
dmp是中文客戶端導出的英文數據庫文件
ASCII字符集是中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是中文客戶端導出的英文數據庫文件
但是ASCII字符集是換成英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是英文客戶端導出的中文數據庫文件
但是數據庫是換過的
ASCII字符集是英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是英文客戶端導出的中文數據庫文件
但是數據庫是換過的
但是ASCII字符集是換成中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是英文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
但是ASCII字符集是換成英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
小結 導入的時候
如果客戶端和數據庫的字符集設置不一致
導入的時候Oracle並沒有提示
導入的時候
如果客戶端和數據庫的字符集設置不一致
ORACLE不進行字符集驗證
最終結果是數據庫不可用
至於是亂碼還是問號
我沒有總結
因為沒有必要
反正是數據庫不可用
上面的操作其實沒有必要做
因為導入的客戶端和目的數據庫字符集不一致
導入後肯定不能用
但是為了試驗的完整性
我還是自己做了一遍
希望大家不要嫌煩
二向B的c倒入操作客戶機是中文字符集 D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是改成中文的
導入成功
有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是中文客戶端導出的中文數據庫文件
ASCII字符集是中文的
導入成功
有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是中文客戶端導出的中文數據庫文件
但是ASCII字符集是改成英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
ASCII字符集是英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
但是ASCII字符集是改成中文的
導入成功
有報錯信息
用英文字符集客戶端是???
問號
用中文客戶端是正確結果
可以看到中文
實際上導入成功
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
dmp是中文客戶端導出的英文數據庫文件
但是數據庫是換過的
ASCII字符集是中文的
導入成功
有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
c
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
c
_
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
ASCII字符集是換成英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是英文客戶端導出的英文數據庫文件
ASCII字符集是英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是英文客戶端導出的英文數據庫文件
但是ASCII字符集是換成中文的
導入成功
有報錯信息
用英文字符集客戶端是???
問號
用中文客戶端是正確結果
可以看到中文
實際上導入成功
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是中文客戶端導出的英文數據庫文件
ASCII字符集是中文的
導入成功
有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是中文客戶端導出的英文數據庫文件
但是ASCII字符集是換成英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是英文客戶端導出的中文數據庫文件
但是數據庫是換過的
ASCII字符集是英文的
提示
不支持要求的字符集轉換
倒入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是英文客戶端導出的中文數據庫文件
但是數據庫是換過的
但是ASCII字符集是換成中文的
導入成功
有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
C
數據庫是???(注意
問號不是亂碼)
實際上導入失敗
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
導入成功
有報錯信息
用英文字符集客戶端是???
問號
用中文客戶端是正確結果
可以看到中文
實際上導入成功
D機器是中文字符集
B機器是中文數據庫
imp system/manager@
c file=c:
e
_
dmp fromuser=test touser=test ignore=y
C數據庫字符集是中文
e
_
dmp是中文客戶端導出的中文數據庫文件
但是數據庫是換過的
但是ASCII字符集是換成英文的
提示
不支持要求的字符集轉換
倒入失敗
小結 :導入的時候
只有當客戶機和服務器的字符集一致的時候才進行倒入的字符集驗證
當導入文件(DMP文件)的ASCII字符集和他們一致的時候才能導入
否則報:不支持要求的字符集轉換
:必要條件是導出文件是可用的
就是說
導出的時候的客戶端和服務器端的字符集是一致的
可以解釋
和
的成功
:
的成功說明了就算是英文的數據庫保存中文數據
在導出後修改DMP文件的字符集
還是可以導入到中文數據庫中的
:
的成功說明了就算數據庫是轉換過的
但是還是可以正確導出中文數據的
:
的成功說明了就算是英文的數據庫保存中文數據
在導出後修改DMP文件的字符集
還是可以導入到中文數據庫中的
(即使這個英文數據庫原來是中文的)
:最不可理解的是
為什麼不行
按道理說
它應該是最有把握的
三向B的e倒入操作(數據庫是英文數據庫)客戶機D是英文字符集 備注
客戶機是中文字符集的情況其實不用測試了
因為客戶機和服務器不一致
肯定出現問題
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
dmp fromuser=test touser=test ignore=y
c
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
E
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
_
dmp fromuser=test touser=test ignore=y
c
_
dmp是英文客戶端導出的中文數據庫文件
ASCII字符集是改成中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
E
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
dmp fromuser=test touser=test ignore=y
c
dmp是中文客戶端導出的中文數據庫文件
ASCII字符集是中文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
E
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
_
dmp fromuser=test touser=test ignore=y
c
_
dmp是中文客戶端導出的中文數據庫文件
但是ASCII字符集是改成英文的
導入成功
沒有報錯信息
但是不管用中文客戶端還是用英文客戶端SQL/PLUS訪問
E
數據庫是亂碼(注意
亂碼不是問號)
實際上導入失敗
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
dmp fromuser=test touser=test ignore=y
c
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
ASCII字符集是英文的
導入成功
沒有報錯信息
用英文客戶端SQL/PLUS訪問
E
數據庫是中文
實際上導入成功
D機器是英文字符集
B機器是英文數據庫
imp system/manager@
e file=c:
c
_
dmp fromuser=test touser=test ignore=y
>
c
_
dmp是英文客戶端導出的英文數據庫文件
但是數據庫是換過的
但是ASCII字符集是改成中文的
導入成功
沒有報錯信息
用英文客戶端SQL/PLUS訪問
E
數據庫是???
倒入不成功
From:http://tw.wingwit.com/Article/program/Oracle/201311/18526.html