Oracle 字符集 = 位元組資料解釋的符號集合,具有大小之分與**包容關係** (子集 → 超集)。
NLS_LANG = LANGUAGE_TERRITORY.CHARACTERSET
三個組成部分:
1. LANGUAGE — 伺服器訊息語言 (錯誤訊息、月份名稱等)
2. TERRITORY — 日期/數字/貨幣格式
3. CHARACTERSET — **真正影響資料儲存與解釋的關鍵**
結論:兩資料庫間匯入匯出僅需 **CHARACTERSET (第三部分) 相同** 即可正確遷移資料。前兩部分僅影響顯示語系與格式。
-- 方法一:直觀查詢
SELECT USERENV('language') FROM dual;
-- 結果範例:AMERICAN_AMERICA.ZHS16GBK
-- 方法二:參數視圖
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET';
-- 結果:NLS_CHARACTERSET = ZHS16GBK
-- 方法三:Props$ 表 (內部)
SELECT * FROM SYS.PROPS$ WHERE NAME = 'NLS_CHARACTERSET';
| 平台 | 查詢/設定位置 |
|---|---|
| Windows | 註冊表:`HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_ |
| Linux/Unix | 環境變數:`echo $NLS_LANG` 或 `export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK` |
| 會話級臨時 | SQL*Plus:`SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK` (僅影響當前會話) |
EXP 匯出檔第 2、3 位元組記錄字符集 ID (16 進位)。
-- 讀取第 2、3 位元組 (如 03 54)
-- 轉換為字符集名稱
SELECT NLS_CHARSET_NAME(TO_NUMBER('0354','XXXX')) FROM dual;
-- 結果:ZHS16GBK
cat exp.dmp | od -x | head -1 | awk '{print $2 $3}' | cut -c 3-6
-- 輸出 4 位十六進位 (如 0354)
-- 再用上述 SQL 查詢名稱
US7ASCII ⊂ WE8ISO8859P1 ⊂ ZHS16GBK / ZHS16CGB231280 ⊂ AL32UTF8 (UTF-8)
│ │ │ │
7-bit 8-bit 西歐 簡體中文 (雙位元組) Unicode (變長 1-4 位元組)
英文數字 西歐語系 含 GBK/GB2312 含全球所有字符
| 方向 | 支援性 | 風險 |
|---|---|---|
| 子集 → 超集 (如 US7ASCII → ZHS16GBK) | ✅ 官方支援 | 無資料遺失,安全 |
| 超集 → 子集 (如 ZHS16GBK → US7ASCII) | ❌ 不支援 | 資料截斷/遺失,嚴重損壞 |
| 無包容關係 (如 ZHS16GBK ↔ ZHS16CGB231280) | ❌ 官方不支援 | 理論不可行,實測某些情況可行但極高風險 |
警告:ZHS16GBK (GBK) 與 ZHS16CGB231280 (GB2312) **無包容關係**,官方不支援相互轉換。GBK 是 GB2312 超集,但編碼映射不同,直接修改字符集會導致中文資料亂碼。
-- 僅在 子集→超集 且完全備份後嘗試
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 ZHS16GBK; -- 目標字符集
ALTER DATABASE NATIONAL CHARACTER SET ZHS16GBK; -- NCHAR/NVARCHAR2
SHUTDOWN IMMEDIATE;
STARTUP;
直接修改 DMP 第 2、3 位元組,「欺騙」 IMP 認為檔案為目標字符集。
-- Java Stored Procedure 範例 (需資料庫安裝 JVM)
-- 讀取 DMP 為 BLOB,修改位元組,寫回新檔案
-- 優點:跨平台、可處理大檔;缺點:需 JVM、程式較複雜
| 字符集 | ID (十進位) | ID (十六進位) | 說明 |
|---|---|---|---|
| US7ASCII | 1 | 0001 | 7-bit ASCII |
| WE8ISO8859P1 | 31 | 001F | 8-bit 西歐 |
| ZHS16CGB231280 | 850 | 0352 | GB2312-80 |
| ZHS16GBK | 852 | 0354 | GBK (含繁體/擴展) |
| AL32UTF8 | 873 | 0369 | UTF-8 (Oracle 推薦) |
| UTF8 | 871 | 0367 | UTF-8 (舊版本,CESU-8 編碼) |
新建資料庫
│
├─ 需支援多語言/表情符/未來擴充 → **AL32UTF8** (首選)
│
├─ 僅簡體中文、舊系統相容、存儲極度敏感 → ZHS16GBK
│
└─ 僅英文/西歐 → WE8ISO8859P1 (不推薦新系統)
字符集問題 90% 發生於「建庫時未統一規劃」與「客戶端 NLS_LANG 配置錯誤」。統一 AL32UTF8、全鏈路一致 NLS_LANG、避免事後修改,是根治之道。