Oracle 11gR2修改服務器端字符集

一.字符集編碼知識


查詢字符集編碼:

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

或者 select * from V$NLS_PARAMETERS;

或者 select * from nls_database_parameters where parameter like 'NLS%CHARACTERSET';


USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

環境變量nls_lang便是由這三部分組成:

1. NLS_LANGUAGE

2. NLS_TERRITORY

3. NLS_CHARACTERSET

組成如下:NLS_LANG = language_territory.charset

即語言、地域和字符集,每個成分控制了 NLS 子集的特性。其中:
Language: 指定服務器消息的語言, 影響提示信息是中文還是英文
Territory: 指定服務器的日期和數字格式

Charset:指定字符集。

真正影響數據庫的是第三部分,因此,我們將Charset修改爲常用的AL32UTF8


二. 修改Oracle服務器端的字符集


SQL> shutdown immediate
SQL> startup nomount
SQL> alter database mount exclusive;  --裝載數據爲專用的高級模式;
SQL> alter system enable restricted session; --啓用受限制的session模式
SQL> alter system set job_queue_processes=0; --'maximum number of job queue slave processes' 設置工作隊列的最大進程數爲0
SQL> alter system set aq_tm_processes=0;
SQL> alter database open;
SQL> alter database character set AL32UTF8; --新的字符集必須支持舊的字符集(舊字符集的超集),
報錯:ORA-12712: new character set must be a superset of old character set,
SQL> shutdown immediate
SQL> startup

因爲沒有執行成功,所以再次查詢依然是ZHS16GBK

SQL>  select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

於是重新關閉數據庫,重新執行:
SQL>shutdown immediate;
等了好長時間沒有反映,於是重新打開終端,然後重新進入數據庫,報錯!
ERROR:
ORA-28056: Writing audit records to Windows Event Log failed
ORA-28056: Writing audit records to Windows Event Log failed
查詢alert_log後發現:
OSD-00001: 附加錯誤信息
O/S-Error: (OS 1502)
事件日誌文件已滿。
原來是系統日誌寫滿了,需要清除後在登錄,於是按照 http://jingyan.baidu.com/article/ce436649f198503772afd355.html將系統日誌清除,正常重啓。
更詳細的解決方案如下:

Cause
The Event Viewer log is full and not able to log any more events.

Justified by unpublished Bug 6823281 ORA-28056 WRITING AUDIT RECORDS TO WINDOWS EVENT LOG FAILED

which was closed as not a bug.

Solution
Try doing the following using Windows Event Viewer:

To open Event Viewer, click Start, click Control Panel, 
click Performance and Maintenance, click Administrative Tools, 
and then double-click Event Viewer.

You must be logged on as an administrator or a member of the 
Administrators group to free an event log.

1) When a log is full, it stops recording new events. Clearing the log 
is one way to free the log and start recording new events.

2) You can also free a log and start recording new events by overwriting 
old events. To overwrite events, on the Action menu, click Properties, 
and then click Overwrite events as needed. This ensures that all new 
events are written to the log, even when the log is full.

3) You can also start logging new events by increasing the maximum 
log size. To increase the log size, on the Action menu, click Properties, 
and then increase the Maximum log size. 
References


言歸正傳,剛纔ORA-12712錯誤是因爲改後字符集必須是現字符集的超子集可以使用INTERNAL_USE 跳過超子集檢測,於是將
SQL> alter database character set AL32UTF8; 
改爲:
SQL> alter database character set INTERNAL_USE AL32UTF8; 

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

USERENV('LANGUAGE')
-------------------------------------------------------------------------------
SIMPLIFIED CHINESE_CHINA.AL32UTF8

可以看到已經更改成功!如果此時執行命令時出現亂碼可能是因爲本機的NLS_LANG參數和Oracle服務器不一致。


三. 客戶端關於Oracle的字符集編碼設置


客戶端與服務器端字符集不一致時可能導致cmd或者shell顯示亂碼:

Windows:
# 常用中文字符集
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK(僅在此cmd窗口立即生效)
# 常用unicode字符集
set NLS_LANG=american_america.AL32UTF8
可以通過修改註冊表鍵值永久設置
HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/KEY_OraDb11g_home1/NLS_LANG(任何窗口生效,但是需要重啓系統生效)

#通過屬性-高級系統設置-環境變量加入

NLS_LANG=american_america.AL32UTF8環境變量(此環境變量優先級高於註冊表環境變量)


Unix:
# 常用unicode字符集
export NLS_LANG=american_america.AL32UTF8
# 常用中文字符集
export NLS_LANG="Simplified Chinese_china".ZHS16GBK
可以編輯 bash_profile 文件進行永久設置
vi .bash_profile
NLS_LANG="Simplified Chinese_china".ZHS16GBK export NLS_LANG
# 使 bash_profile 設置生效
source .bash_profile



四. sql腳本導入Oralce服務器執行時各種字符集的測試


windows下Oracle11gR2服務器端字符集編碼爲 CHINESE_CHINA.ZHS16GBK,NLS_LANG變量編碼爲CHINESE_CHINA.ZHS16GBK,sql腳本編碼爲UTF8編碼。以此爲測試環境,測試sql腳本編碼和服務器端字符集編碼各種情況下的結果:

執行結果


結果一. 在windows下裝Oracle服務器端字符集爲 CHINESE_CHINA.ZHS16GBK,裝載UTF8編碼的sql腳本文件,在數據庫中查詢出來的中文是亂碼;將UTF8編碼的sql腳本文件複製出來後再粘貼至新建的sql文件中(可能已經是CHINESE_CHINA.ZHS16GBK編碼),然後重新執行插入後沒有亂碼現象。

結果二.接着結果一。強行將Oracle服務器端字符集由CHINESE_CHINA.ZHS16GBK改爲CHINESE_CHINA.AL32UTF8後,原來查詢不是亂碼的中文出現  ERROR:ORA-29275: 部分多字節字符,不是亂碼這麼簡單了

結果三。接着結果二,再強行將Oracle服務器端字符集由改回原來的CHINESE_CHINA.ZHS16GBK後,查詢原中文恢復正常,沒有出現亂碼。

結果四。接着結果三。刪除後sql腳本執行結果後,重新執行UTF8編碼的腳本(Oracle服務器端字符集爲CHINESE_CHINA.AL32UTF8,沒有特意設置系統的NLS_LANG變量),查詢出來的中文是亂碼。(後來分析可能是UTF8編碼的腳本有問題);

結果五。接着結果四。刪除後重新執行UTF8編碼的腳本(Oracle服務器端字符集爲CHINESE_CHINA.AL32UTF8,設置系統的NLS_LANG變量爲CHINESE_CHINA.AL32UTF8),查詢出來的中文仍然是亂碼。但是在終端裏自己寫插入語句插入中文再查詢不是亂碼(是不是顯示時不是UTF8編碼?)。

結果六。接着結果五。再強行將Oracle服務器端字符集改爲CHINESE_CHINA.AL32UTF8後,查詢仍然是亂碼

對結果的分析


如果是UTF8的sql腳本插入字符集爲CHINESE_CHINA.AL32UTF8的數據庫應該沒有問題的,也就是不會出現亂碼,出現亂碼的原因如下:

1.UTF8編碼的sql腳本有問題,因爲在執行sql腳本時,部分語句出現 ERROR:ORA-01756: 引號內的字符串沒有正確結束,但經過仔細檢查沒有任何語法錯誤,由此推測sql腳本不是真正的UTF8編碼,在用UltraEdit再重新生成UTF8編碼後(UltraEdit:文件->轉換)就果然沒有問題了。

2.UTF8的腳本插入字符集爲CHINESE_CHINA.AL32UTF8的數據庫應該沒有問題,也就是存儲的中文數據是正確的。windows顯示錯誤的原因肯能是cmd終端的編碼不是UTF8,使用http://blog.itpub.net/25744374/viewspace-753227/
(1. chcp 65001  2.屬性->字體->Lucida Console) 將cmd字符集更改後就可以正常顯示中文了。

3. 在修改系統的NLS_LANG變量爲CHINESE_CHINA.AL32UTF8時,必須要關閉所有cmd窗口,然後再重新開纔會生效。

4.如果Oracle服務器字符集由GBK改爲UTF8後,存儲的數據不能自動改變其編碼,還是GBK的編碼,則顯示時有可能出現亂碼。(沒有亂碼的情況:當客戶端編碼爲UTF8,操作系統編碼(cmd窗口或Shell終端)爲GBK時。因爲Oracle中存儲的編碼格式是GBK的,而且客戶端編碼=服務器端編碼=UTF8,所以在取出時不需要轉換編碼,而操作系統編碼是GBK,顯示GBK編碼當然沒有問題了)。


補充:


NLS_CHARACTERSET與NLS_NCHAR_CHARACTERSET的區別


NLS_CHARACTERSET是數據庫字符集,NLS_NCHAR_CHARACTERSET是國家字符集
ORACLE中有兩大類字符型數據,VARCHAR2是按照數據庫字符集來存儲數據。而NVARCHAR2是按照國家字符集存儲數據的。同樣,CHAR和NCHAR也一樣,一是數據庫字符符,一是國家字符集。
字符集不同,二進制碼的組合就不同。
比如有一串二進制信息:1101,0110,1101,0000,1011,1001,1111,1010,按照16位雙字節GBK字符集理解,可以代表“中國”兩個字。如果單字節的字符集,這一串二進制代表ASC碼爲214、208、185、250的四個怪字符。
這就是字符集的作用,就是以什麼樣的形式理解信息。

The NLS_CHARACTERSET is used for CHAR, VARCHAR2, LONG and CLOB columns;
The NLS_NCHAR_CHARACTERSET is used for NCHAR, NVARCHAR2 and NCLOB columns.
From 9i onwards the NLS_NCHAR_CHARACTERSET can have only 2 values: UTF8 or AL16UTF16 who are Unicode charactersets


注:我的例子中“中國”的二進制形式來自dump('中國',16)。


Windows修改cmd字符集 


http://blog.itpub.net/25744374/viewspace-753227/


oracle不同系統之間時間轉換


http://www.2cto.com/database/201302/191460.html


 參考:

http://blog.chinaunix.net/uid-25492475-id-3140218.html

http://www.eygle.com/archives/2004/09/nls_character_set_01.html

http://blog.csdn.net/wzy0623/article/details/1683337

http://blog.sina.com.cn/s/blog_95c27c530101ap58.html

http://bbs.51cto.com/thread-1017691-1.html

http://blog.chinaunix.net/uid-21125022-id-4195664.html
http://blog.csdn.net/ding43930053/article/details/42460693
http://www.cnblogs.com/lanston/p/3755978.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章