核心概念區分
| 參數 | 層級 | 作用 | 註冊表/環境變數 |
NLS_LANG | Client | 客戶端字符集、語言、地區;決定 SQL*Plus 顯示與匯出編碼 | HKLM\Software\Oracle\HOME0\NLS_LANG / $NLS_LANG |
NLS_CHARACTERSET | Database | 資料庫內部儲存編碼;建庫時固定,不可變 | SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET'; |
測試矩陣與結果
| 案例 | Client NLS_LANG | DB Character Set | 中文顯示 | 建表含中文 | 匯出/匯入 |
| 1 | ZHS16GBK | ZHS16GBK | ✅ | ✅ | ✅ |
| 2 | ZHS16GBK | US7ASCII | ❌ | ❌ | ⚠️ 轉換警告 |
| 3 | US7ASCII | US7ASCII | ✅ (純 ASCII) | ❌ | ❌ |
| 4 | ZHS16GBK | US7ASCII | ❌ | ❌ | ⚠️ 轉換警告 |
關鍵結論
- Client 與 DB 字符集必須一致(或 Client 為超集),否則中文亂碼。
NLS_LANG 決定 EXP 匯出檔編碼;IMP 讀取時依檔案標記轉換。
US7ASCII 不支援中文,強行寫入會導致資料損壞。
- Oracle 9i+ 強制要求 Client/Server 字符集相容,否則拋
ORA-12705。
驗證查詢
SELECT * FROM V$NLS_PARAMETERS;
SELECT * FROM NLS_DATABASE_PARAMETERS;
SELECT * FROM PROPS$ WHERE NAME='NLS_CHARACTERSET';
遺留問題
案例 3:Client/DB 皆為 US7ASCII,為何建表含中文後無法正常顯示?
→ 根因:US7ASCII 無中文字碼對應,寫入時已遺失資訊,非顯示層問題。
最佳實務
- 新建庫統一採用
AL32UTF8 (UTF-8),Client 同設 NLS_LANG=.AL32UTF8。
- 舊系統 GBK 遷移至 UTF8 需用
DMU (Database Migration Assistant for Unicode) 逐字轉換。
- 應用層統一使用 Unicode (Java String / .NET String / Python 3 str),避免編碼轉換鏈條過長。