Oracle web介面亂碼分析

賀子_DBA時代發表於2018-11-13

問題描述web介面亂碼,廠商給我一個sql檔案,需要新建使用者,然後新建表空間,然後執行人家的sql檔案,剛開始什麼沒注意字符集問題直接執行了,很順利的執行成功,然後啟動tomcat,web介面居然亂碼了!

環境介紹:contos 6.9 +oracle 11g

資料庫的字符集為:

SQL> select userenv('language') nls_lang from dual;

NLS_LANG

----------------------------------------------------

AMERICAN_AMERICA.ZHS16GBK

解決辦法:思路:需要保證資料庫和tomcat的字符集保證一致,然後設定Oracle使用者的環境變數nls_lang和lang,保險起見可以把啟動tomcat的使用者的環境變數lang也設定成一樣的,如果想批次直接執行sql檔案,需要保證sql檔案也是一樣的字符集! 1.首先設定了oracle使用者的LNG和NLS_LANG兩個環境變數:

linux中有兩個配置編碼的引數LANG和NLS_LANG。LANG是針對Linux系統的語言、地區、字符集的設定,對linux下的應用程式有效,如date;NLS_LANG是針對Oracle語言、地區、字符集的設定,對oracle中的工具有效。    

[oracle@tvf-ncMobileapproval-oracle-01 ~]$  export  LANG=zh_CN.GB2312

[oracle@tvf-ncMobileapproval-oracle-01 ~]$ export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

之後編輯一個sql檔案,然後將人家給的指令碼記憶體複製進去,然後檢視該檔案的字符集,不再是utf-8了!

[oracle@tvf-ncMobileapproval-oracle-01 ~]$ vi 6.sql  

[oracle@tvf-ncMobileapproval-oracle-01 ~]$ file -i 6.sql 6.sql: text/x-po; charset=iso-8859-1

或者不用copy的方式,直接透過sz 或者ftp等工具直接把廠商的sql檔案上傳到伺服器上,然後透過命令修改檔案的字符集:如下具體過程 首先檢視需要轉換字符集的檔案的原始字符集,需要保證檔案的字符集和資料庫的字符集一樣! 注意 charset=iso-8859-1就和gbk相容!

[oracle@tvf-ncMobileapproval-oracle-01 ydpttomcat]$ file -i ydptdb.sql

ydptdb.sql: text/x-po; charset=utf-8

使用iconv命令轉換檔案字符集:

[oracle@tvf-ncMobileapproval-oracle-01 ydpttomcat]$ iconv -f utf-8 -t gb2312 /data/ydpttomcat/ydptdb.sql >/data/u01/1.sql 再次檢視檔案字符集發現已經改變了:

[oracle@tvf-ncMobileapproval-oracle-01 u01]$ file -i 1.sql 1.sql: text/x-po;

charset=iso-8859-1 然後可以直接登陸資料庫,然後倒進資料庫了!

2.tomcat的配置檔案字符集為gbk,然後重啟tomcat!!!

可以透過這個命令來找到tomcat的配置檔案的路徑

[root@tvf-ncMobileapproval-oracle-01 /data/ydpttomcat]# grep -i  -R  "URIEncoding"

ydptapps/mobem/META-INF/maven/com.yonyou.iuap/mobem/pom.xml:                    <uriEncoding>GBK</uriEncoding>然後最好修改下啟動tomcat服務的使用者的環境變數,然後啟動tomcat

需要保證資料庫和tomcat的字符集保證一致,然後設定Oracle使用者的環境變數nls_lang和lang,保險起見可以把啟動tomcat的使用者的環境變數lang也設定成一樣的,如果想批次直接執行sql檔案,需要保證sql檔案也是一樣的字符集! 最好的,最不容易出字符集錯誤的就是:將資料庫字符集、客戶端字符集、客戶端作業系統NLS_LANG引數三個地方作同樣的設定。

重點說下Oracle資料庫字符集讀取和插入的時候轉換過程

insert 的過程: 首先以Oracle客戶端的字符集(lang)編碼------->然後透過客戶端nls_lang告訴sqlplus是以那種字符集編碼的------->然後Oracle資料庫得知nls_lang後,藉助自己的編碼表來轉換成資料庫的字符集,如果使用lang=utf8編碼,然後nls_lang=gbk,等Oracle轉換的時候,透過gbk的編碼表來轉換,那麼肯定會亂碼的!!!!!!!所以只需要lang和nls_lang一樣,那麼insert就不會亂碼!!!!不管資料庫的字符集和他一樣不一樣!!!也就是說Oracle會做字符集轉換的工作,客戶端不會轉換,只會根據lang來查詢對應的字串,

select的過程: Oracle資料庫根據資料庫的字符集utf8把查詢的內容進行編碼--------->然後告訴sqlplus程式我查出來的內容是以utf8進行編碼的,然後sqlplus告訴Oracle他們需要的是nls_lang=gbk,於是Oracle發現不一樣,這樣Oracle就根據自己的編碼表來找gbk的對應編碼,然後傳給sqlplus程式------>sqlplus直接把得到的這串編碼扔給客戶端作業系統,而作業系統只是有ZHS16GBK編碼表(假如lang= ZHS16GBK ),它不會問得到的這串編碼是什麼格式的!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29654823/viewspace-2219825/,如需轉載,請註明出處,否則將追究法律責任。

相關文章