| 端別 | 查看方法 | 範例輸出 |
| Server (資料庫) | SELECT USERENV('LANGUAGE') FROM DUAL;
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET'; | AMERICAN_AMERICA.ZHS16GBK |
| Client (用戶端) | Windows:註冊表 HKLM\SOFTWARE\ORACLE\KEY_\NLS_LANG Linux/Unix:echo $NLS_LANG 臨時設定:SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK | SIMPLIFIED CHINESE_CHINA.ZHS16GBK |
| DMP 匯出檔 | 小檔:UltraEdit 開啟 16 進制看第 2-3 位元組 (如 0354) 大檔:cat exp.dmp | od -x | head -1 | awk '{print $2$3}' | cut -c3-6 解碼:SELECT NLS_CHARSET_NAME(TO_NUMBER('0354','XXXX')) FROM DUAL; | ZHS16GBK |
四種 NLS 參數視圖差異
-- 1. 資料庫層級 (實際儲存字符集)
SELECT * FROM NLS_DATABASE_PARAMETERS; -- 來源:PROPS$
-- 2. 實例層級 (參數檔/環境變數/註冊表)
SELECT * FROM NLS_INSTANCE_PARAMETERS; -- 來源:V$PARAMETER
-- 3. 會話層級 (當前會話生效設定)
SELECT * FROM NLS_SESSION_PARAMETERS; -- 來源:V$NLS_PARAMETERS
-- 4. 會話級動態修改
ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_TERRITORY = 'AMERICA';
-- 字符集不可在會話層級修改!
優先順序:ALTER SESSION > 環境變數 > 註冊表 > 參數檔。字符集必須一致,語言/地區可不同 (建議用英文避免錯誤訊息編碼問題)。
修改資料庫字符集:只能擴大不能縮小
-- 必須關閉資料庫,以 RESTRICTED 模式啟動
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER SYSTEM ENABLE RESTRICTED SESSION;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
ALTER DATABASE OPEN;
ALTER DATABASE CHARACTER SET AL32UTF8; -- 目標必須為原字符集的超集
- 超集原則:US7ASCII ⊂ WE8ISO8859P1 ⊂ ZHS16GBK ⊂ AL32UTF8
- ZHS16GBK → ZHS16CGB231280 不可行 (非超集關係)
- 若需縮小字符集:只能重建資料庫 + EXPDP/IMPDP
導入導出字符集一致性鐵律
- DMP 檔字符集 = 匯出時 Server 字符集 (由 EXP 寫入檔頭)
- 匯入時:Client NLS_LANG 必須 = DMP 字符集 = 目標 Server 字符集
- 三者一致 → 正確導入;任何一端不一致 → 亂碼或報錯 (ORA-02374, ORA-12899)
實戰排查清單
- 查詢三端字符集是否一致
- 若 Client ≠ Server:修改 Client 環境變數/註冊表
- 若 DMP ≠ 目標 Server:檢查是否為超集關係,否則需轉碼或重建庫
- 新專案強制統一 AL32UTF8,避免所有字符集痛點
- 上一篇文章: Oracle 分頁與排序查詢完全指南:ROWNUM 三層巢狀寫法、OFFSET/FETCH (12c+) 與效能優化
- 下一篇文章: Oracle RAC 環境下 PreparedStatement setMaxRows 失效問題分析與解決方案
Copyright ©
程式碼之家 All Rights Reserved