NLS_LANG = LANGUAGE_TERRITORY.CHARACTERSET
例:AMERICAN_AMERICA.ZHS16GBK、SIMPLIFIED CHINESE_CHINA.AL32UTF8。
| 端點 | 查詢方法 | 關鍵指標 |
|---|---|---|
| Server 端 | SELECT * FROM nls_database_parameters WHERE parameter IN ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');SELECT userenv('language') FROM dual; |
數據庫存儲編碼 (如 ZHS16GBK, AL32UTF8)客戶端會話衍生編碼 |
| Client 端 | Windows: 注冊表 HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_Linux/Unix: echo $NLS_LANG會話級: SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK (Win) / export NLS_LANG=... (Linux) |
客戶端聲明編碼,**必須與 Server 字符集兼容** (子集→超集或相同) |
| DMP 文件 | 小文件: UltraEdit 16進制查看第 2-3 字節 (如 03 54)大文件: 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 |
導出時客戶端字符集快照,**導入時將與目標庫 Server 字符集比對** |
-- 1. 獲取目標字符集 16 進制 ID
SELECT TO_CHAR(nls_charset_id('AL32UTF8'), 'XXXX') FROM dual; -- 返回 8733 (十進制) -> 221D (十六進制)
-- 2. 修改 DMP 第 2-3 字節
# 小文件: UltraEdit 直接改為 22 1D
# 大文件: dd if=exp.dmp of=exp_modified.dmp bs=1 count=2 conv=notrunc 2>/dev/null
# printf '\x22\x1D' | dd of=exp_modified.dmp bs=1 seek=1 count=2 conv=notrunc
# cat exp.dmp | tail -c +4 >> exp_modified.dmp
**適用場景**:Server 字符集相同,僅 Client/DMP 不一致導致導入報錯。
**禁忌**:實際數據含目標字符集無法表示的字符 (如 GBK 環境存入 Emoji),修改後導入將產生亂碼或截斷。
-- 僅當「當前字符集為目標字符集真子集」且「數據純屬子集範圍」時可嘗試
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER SYSTEM ENABLE RESTRICTED SESSION;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
ALTER SYSTEM SET AQ_TM_PROCESSES=0;
ALTER DATABASE OPEN;
ALTER DATABASE CHARACTER SET AL32UTF8; -- 目標超集
ALTER DATABASE NATIONAL CHARACTER SET AL16UTF16;
SHUTDOWN IMMEDIATE;
STARTUP;
**後果風險**:數據字典損壞、索引鍵值順序錯亂、PL/SQL 代碼編碼錯誤、應用亂碼。Oracle 12c+ 強烈建議使用 **DMU (Database Migration Assistant for Unicode)** 進行離線掃描、轉換、驗證全流程。
AL32UTF8 (Oracle 實現的 UTF-8),支援全語系、Emoji、補充字符。oracle.jdbc.convertNcharLiterals=true。| 現象 | 典型原因 | 排查入口 |
|---|---|---|
| 中文顯示 ??? 或 | Client NLS_LANG 與 Server 字符集不匹配 (如 Client US7ASCII 連 Server ZHS16GBK) | 檢查注冊表/環境變量 NLS_LANG |
| 導入 DMP 報 ORA-31065/31108 | DMP 字符集與目標庫 Server 字符集不兼容 | 檢查 DMP 第 2-3 字節 vs 目標庫 NLS_CHARACTERSET |
| 跨 DB Link 查詢亂碼 | 兩庫 Server 字符集不同,隱式轉換丟失 | 統一雙端字符集或應用層顯式 CONVERT |
| PL/SQL 代碼變亂碼 | 源碼文件編碼與數據庫字符集不一致 | 統一源碼文件保存為 UTF-8 無 BOM |
字符集問題 90% 源於 **「客戶端聲明編碼與數據庫存儲編碼不匹配」**。新建項目**強制 AL32UTF8 全鏈路**,存量系統**用 DMU 規範遷移**,拒絕手工修改字典表、拒絕偽裝 DMP 字符集上線。建立「字符集一致性」作為交付驗收硬性指標,從源頭杜絕亂碼基因。