徹底解決Oracle中文亂碼

boboan發表於2018-01-05

影響Oracle編碼的配置有3處:

服務端字符集 作業系統字符集 NLS_LANG字符集
SELECT * FROM NLS_DATABASE_PARAMETERS locale export
american_america.AL32UTF8 en_US.UTF-8 AMERICAN_AMERICA.ZHS16GBK

問題復現:

1. 建立表

CREATE TABLE "CY_BIF_DEV"."MYSQL_TEST_10" 
    (    "ID" NUMBER(7,0) NOT NULL ENABLE, 
    "STRING_VALUE_NOT_NULL" VARCHAR2(100) NOT NULL ENABLE
   );
  
select * from mysql_test_10;
delete from mysql_test_10;
select dump(STRING_VALUE_NOT_NULL, 1016) from mysql_test_10;

2. 檢查編碼配置

服務端字符集,NLS_CHARACTERSET: ZHS16GBK。
客戶端os locale:LANG=”en_US.UTF-8”。
環境變數NLS_LANG 沒有配置。

3. 寫入中文

  1. 外掛中文INSERT INTO mysql_test_10 VALUES (2, `中國`);中文是UTF-8編碼。
  2. 讀取中文select * from mysql_test_10,發現顯示亂碼。
  3. 檢查oracle儲存的編碼,發現儲存編碼錯誤。
select dump(STRING_VALUE_NOT_NULL, 1016) from mysql_test_10。
Typ=1 Len=6 CharacterSet=ZHS16GBK: 3f,3f,3f,3f,3f,3f 

正確的UTF編碼(中國e4,b8,ad,e5,9b,bd)GBK編碼(d6,d0,b9,fa)

問題修正

  • 設定NLS_LANG與客戶端os字符集相同。
  • NLS_LANG=american_america.AL32UTF8;

問題分析

  • client端使用UTF8編碼,傳送到Oracle server端後,server端讀取NLS_LANG是空後,直接用GBK編碼了資料,於是儲存時,字元就錯亂了,大小6位元組。
  • 設定NLS_LANG=american_america.AL32UTF8後,server端會先到UTF8編碼表中查詢,翻譯後以GBK編碼儲存,大小4位元組。

問題總結

  • NLS_LANG 與客戶端os字符集要保持一致。
  • 為了減少翻譯開銷,最好“服務端字符集”,“客戶端os字符集”和NLS_LANG,3者保持一致。

歡迎加入橙鷹資料, 575834439@qq.com

https://www.cnblogs.com/xdouby/p/5666624.html
https://www.cnblogs.com/bingo1717/p/7803359.html


相關文章