亂碼本質是三端字符集不一致導致的錯誤轉換:
V$NLS_PARAMETERS.NLS_CHARACTERSETNLS_LANG 決定(Windows 註冊表、Linux .bash_profile)EXP 導出時將字符集 ID 寫入檔頭第 2~3 字節鐵律:導入成功需 三端字符集完全一致,或 Client/Server 為 Dump File 字符集的超集。
NLS_LANG = LANGUAGE_TERRITORY.CHARACTERSET
-- 範例:AMERICAN_AMERICA.ZHS16GBK
-- 只有第三段 CHARACTERSET 影響資料存儲與轉換,前兩段僅影響提示語言、日期/數字格式
SELECT USERENV('LANGUAGE') FROM DUAL; -- 回傳如 AMERICAN_AMERICA.ZHS16GBK
-- 或
SELECT VALUE FROM V$NLS_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET';
-- 小檔:UltraEdit 16進制開啟,看第 2-3 字節(如 0354)
-- 大檔:Linux 命令
cat exp.dmp | od -x | head -1 | awk '{print $2 $3}' | cut -c 3-6
-- 再查對應字符集
SELECT NLS_CHARSET_NAME(TO_NUMBER('0354','XXXX')) FROM DUAL; -- 回傳 ZHS16GBK
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0\NLS_LANGecho $NLS_LANG 或 set NLS_LANG=AMERICAN_AMERICA.ZHS16GBK(當前 Session)-- 1. 查目標字符集 16 進制 ID
SELECT TO_CHAR(NLS_CHARSET_ID('ZHS16GBK'), 'XXXX') FROM DUAL; -- 0354
-- 2. 小檔:UltraEdit 直接改第 2-3 字節為 0354
-- 3. 大檔:需編寫程式(Java Stored Procedure / Python / C)修改檔頭,要求資料庫安裝 JVM
| 現象 | 成因 | 解決 |
|---|---|---|
| Client 顯示亂碼,Server/資料正確 | Client NLS_LANG ≠ Server | 修正 Client NLS_LANG 與 Server 一致 |
| 導入後亂碼,Client/Server 一致 | Dump File 字符集 ≠ Server | 修正 Dump File 字符集(子集→超集)或重建目標庫字符集後再導入 |
| 輸入中文存入後查詢亂碼 | 輸入時 Client ≠ Server | 統一 Client/Server 後重新輸入資料 |
# Linux/Unix
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK # 顯示英文介面
export NLS_LANG="SIMPLIFIED CHINESE"_CHINA.ZHS16GBK # 顯示中文介面
# Windows CMD
SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
中文環境首選 ZHS16GBK(涵蓋 ZHS16CGB231280,支援港台罕用字);多語系系統建議直接採用 AL32UTF8(Oracle 推薦的 UTF-8 實作),一次到位避免後續轉換痛苦。