Oracle漢字亂碼問題原因及解決方法
by wangd
出現中文亂碼的主要原因是字符集不同。
在Oracle中,我們關心三個地方的字符集:
l Oracle服務器內部的字符集
l NLS_LANG變量裡保存的字符集
l 客戶端應用的字符集
Oracle服務器內部的字符集
這是Oracle數據庫存儲數據使用的字符集。
在Oracle中可能使用
Select userenv(''language'') from dual;
或者:
Select name, value$ from props$;
查看。
NLS_LANG變量裡保存的字符集
這個是Oracle設置的一個變量。
在Windows中,這個變量保存在注冊表中:
HKEY_LOCAL_MacHINE\SOFTWARE\Oracle\HOME0保存著NLS_LANG變量。
在Unix/Linux中,則需要自己進行設置了。我本人是在.profile裡面加上
NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
export NLS_LANG
客戶端應用的字符集
使用Oracle裡數據或者向Oracle提供數據的應用程序。
如果 Oracle服務器內部的字符集 和 NLS_LANG變量裡保存的字符集 相同,在進行Oracle查詢時,就會將Oracle中的數據直接查出來,返回給查詢用戶。進行Oracle的插入操作,就會直接將插入的數據保存進數據庫中。
但是如果不同的話,Oracle查詢時,會根據這兩個字符集的一個映射,將數據庫中的數據作一個轉換,再返回給查詢用戶。進行插入操作時,也會根據映射,將插入的數據作一個轉換,再插入數據庫。這也是產生亂碼的原因,這一層轉換,把數據都給轉亂了。
將數據庫的字符集和NLS_LANG字符集設置的一樣,就可以避免亂碼的出現了。
修改數據庫字符集的步驟如下:
1、擁有修改權限(用管理用戶登錄)。
SQL> conn sys/sys as sysdba;
2、關閉數據庫。
SQL>shutdown immediate;
3、啟動數據庫到Mount狀態下。
SQL> STARTUP MOUNT;
Oracle instance started.
Total System Global Area 76619308 bytes
Variable Size 58720256 bytes
Database Buffers 16777216 bytes
Redo Buffers 667648 bytes
Database mounted.
SQL> ALTER SESSION SET SQL_TRACE=TRUE;
Session altered.
SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
System altered.
SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
System altered.
SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;
System altered.
4、啟動數據庫
SQL> Alter database open;
5、修改字符集
SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;
注:
1. 如果數據庫表中有CLOB類型的列,是不允許修改字符集的,解決方法為,先導出這個表的內容,然後刪除這個表,修改完後,再導入這個表的內容就可以了。
2. 舊的字符集必須是新的字符集的子集,否則不能修改。
修改完後,可以查看一下修改是否成功。
6、關閉數據庫
SQL> Shutdown immediate;
7、重新啟動數據庫
SQL> startup;
經過設置完Oracle字符集後,一般的亂碼問題應該解決掉了。
在開發中,還遇到了這樣一個問題:
數據庫服務器和應用服務器都布署在Solaris上面了,建庫的腳本也是在Solaris上面執行的,在Solaris上面查詢數據是正常的,但是在Windows上用浏覽器看時,就會變成?了。
這個問題的解決辦法是,將數據庫建庫腳本在Windows上執行,再查看就都變正常了。