概念描敘web
ORACLE數據庫有國家字符集(national character set)與數據庫字符集(database character set)之分。二者都是在建立數據庫時須要設置的。國家字符集主要是用於NCHAR、NVARCHAR、NCLOB類型的字段數據,而數據庫字符集使用很普遍,它用於:CHAR、VARCHAR、CLOB、LONG類型的字段數據;數據庫
ORACLE的字符集名字通常由如下部分組成:語言或區域、表示一個字符的比特位數、標準字符集名稱(可選項,S或C,表示服務器或客戶端)。ORACLE字符集UTF8與UTFE不符合此規定,其它基本都是這種格式。NLS_LANG=<Language>_<Territory>.<Clients Characterset>bash
set nls_lang=AMERICAN_AMERICA.UTF8服務器
set nls_lang=SIMPLIFIED CHINESE_AMERICA.UTF8session
NLS( National Language Support)國家語言支持。NLS是數據庫的一個很是強大的特性,它控制着數據的許多方面:好比數據如何存儲,通常來講它控制着如下兩個方面:oracle
文本數據持久存儲在磁盤上時如何編碼app
透明的將數據從一個字符集轉換到另一個字符集。編碼
假設你在數據庫中用WE8ISO8859P1 字符集存儲8 位的數據,可是你的某些客戶使用的是一種7 位字符集,如US7ASCII字符集轉換過程一般會修改數據,而你每每會把一個較大的字符集(在此例中就是8 位字符集)映射到一個較小的字符集(此例中的7 位字符集)。這是一種有損轉換(lossy conversion),字符就會被修改,這只是由於:較小的字符集不可能表示較大字符集中的每個字符。可是這種轉換必須發生。這也是亂碼產生的緣由。若是數據庫以一種單字節字符集存儲數據,可是客戶(如一個Java 應用,由於Java 語言使用Unicode)但願數據採用多字節表示,就必須執行轉換,只有這樣客戶應用才能使用這些數據。spa
ORACLE支持的Unicode字符集有如下幾種,下面的列表給出了字符集的名稱、對應的數據庫版本範圍、採用的Unicode的版本。.net
AL24UTFFSS:是ORACLE第一種支持Unicode的字符集,從7.2版本開始使用,可是它支持的Unicode版本爲1.1,所以從9i開始就不支持此字符集了。
UTF8 : 是ORACLE從ORACLE8開始使用的屬於UTF-8編碼的字符集,從ORACLE8.0到ORACLE8.16,Unicode版本爲2.1,而ORACLE817到10g,採用的Unicode標 準爲3.0
UTFE :用於EBCDIC碼平臺上的數據庫Unicode字符集。所以它屬於專用系統使用的字符集,其它屬性與UTF8基本相同。
AL32UTF8 :是從ORACLE9開始使用的屬於UTF-8編碼的字符集,與UTF8相比,它採用的Unicode版本更新,在10g版本中使用的是Unicode 4.01標準,而UTF8因 爲兼容性的考慮,在10g版本中用的是Unicode 3.0標準。
AL16UTF16:是ORACLE第一種採用UTF-16編碼方式的字符集,從ORACLE9開始使用,是做爲缺省的國家字符集使用,它不能被用做數據庫的字符集。這是由於數 據庫的字符集決定了SQL與PL/SQL源碼的編碼方式,對於UTF-16這種使用固定的兩個字節來表示英文字母的編碼方案來講,確實不適於用做數據庫 的字符集,ORACLE目前採用的數據庫字符集都是基於ASCII或EBCDID做爲子集的編碼方案。
對於US7ASCII,表示區域是US,用7個比特位表示一個字符,標準的字符集名稱爲ASCII。
對於中文字符集ZHS16GBK,表示簡體中文(ZHT爲繁體中文),一個字符須要16位比特,標準的字符集名稱爲GBK。而ZHS16CGB231280表示簡體中文,一個字符須要16位比特,標準的字符集名稱爲GB231280,屬於咱們前面提過的1981年發佈的GB2312-80標準。雖然咱們說,GBK編碼標準是GB2312編碼標準的擴展,可是數據庫字符集ZHS16GBK與ZHS16CGB231280之間卻不是嚴格的超集與子集的關係,主要是有些漢字的編碼在兩個字符集中的數值是不一樣的,所以它們進行字符集轉換時會出現問題。
查看字符集參數
1:查看NLS_CHARACTERSET:字符集,NLS_NCHAR_CHARACTERSET:國家字符集
實例字符集環境
SELECT * FROM NLS_INSTANCE_PARAMETERS
主要涉及NLS_LANGUAGE、NLS_TERRITORY的值. NLS_INSTANCE_PARAMETERS其來源於v$parameter,注意:網上不少資料都說"NLS_INSTANCE_PARAMETERS 表示客戶端的字符集的設置,能夠是參數文件,環境變量或者是註冊表",並且網上都人人亦云。記住它是表示實例的字符集環境。
數據庫可用字符集參數設置
SELECT * FROM V$NLS_VALID_VALUES
數據庫服務器字符集
SELECT * FROM NLS_DATABASE_PARAMETERS
NLS_DATABASE_PARAMETERS其來源於props$,是表示數據庫的字符集。
客戶端字符集環境
SELECT * FROM V$NLS_PARAMETERS;
SELECT USERENV('language') FROM DUAL;
USERENV、 V$NLS_PARAMETERS表示當前字符集環境。若是你在客戶端執行,則表示客戶端字符集環境。
會話字符集環境
SELECT * FROM NLS_SESSION_PARAMETERS;
它來源於v$nls_parameters,表示會話本身的設置,多是會話的環境變量或者是ALTER SESSION完成,若是會話沒有特殊的設置,將與 V$NLS_PARAMETERS一致。
2: 查看客戶端字符集(NLS_LANG) 的方法
若是系統是LINUX或UNIX平臺,則也能夠經過下面命令查看(前提是必須設置了NLS_LANG,不然查出來的是空值)
[etl@m1 ~]$env | grep NLS_LANG
NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
[etl@m1 ~]$echo $NLS_LANG
AMERICAN_AMERICA.ZHS16GBK
若是系統是WINDOWS平臺,則能夠經過下面命令查看:
1:在運行裏面,輸入regedit進入註冊表,HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1\裏面(最後一項與實例名、數據庫版本有關係),找到NLS_LANG選項,雙擊它,你就能夠看到相應的值。
2:echo %NLS_LANG% 。若是沒有設置NLS_LANG,用這個命令看不到相關信息。
3: 設置NLS_LANG的方法
Windows平臺:
3.1
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
3.2 能夠經過修改註冊表鍵值永久設置
HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/KEY_XXXX_home1/NLS_LANG
UNIX & LINUX
3.3
export NLS_LANG=AMERICAN_AMERICA.UTF8
3.4能夠編輯 bash_profile 文件進行永久設置
vi .bash_profile
export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"
客戶端的字符集要求與服務器一致,才能正確顯示數據庫的非Ascii字符。若是多個設置存在的時候,優先級關係爲:SQL Function >Alter session>環境變量>註冊表>參數文件 字符集要求一致,可是語言設置卻能夠不一樣,語言設置建議用英文。如字符集是zhs16gbk,則nls_lang能夠是American_America.zhs16gbk。
修改數據庫字符集
數據庫字符集在建立後原則上不能更改。所以,在前期規劃和安裝之初考慮使用哪種字符集十分重要。對數據庫服務器而言,錯誤的修改字符集將會致使不少不可測的後果,可能會嚴重影響數據庫的正常運行,因此在修改以前必定要確認兩種字符集是否存在子集和超集的關係。通常來講,除非萬不得已,咱們不建議修改ORACLE數據庫SERVER端的字符集。
有兩種方法修改數據庫字符集設置
1. 一般須要導出數據庫數據,重建數據庫,而後再導入數據庫數據的方式來轉換。
2. 經過ALTER DATABASE CHARACTER SET語句修改字符集,但建立數據庫後能夠修改的字符集是有限制的,只有新的字符集是當前字符集的超集時才能修改數據庫字符集,例如UTF8是US7ASCII的超集,修改數據庫字符集可以使用ALTER DATABASE CHARACTER SET UTF8。
特別說明,咱們最經常使用的兩種字符集ZHS16GBK和ZHS16CGB231280之間不存在子集和超集關係,所以理論上講這兩種字符集之間的相互轉換不受支持修改
關於數據庫子集-超級對照表(subset-superset pairs),能夠參考官方文檔,例如ORACLE 10g的http://docs.oracle.com/cd/B19306_01/server.102/b14225/applocaledata.htm
Table A-11 Subset-Superset Pairs
Subset |
Superset |
AR8ADOS710 |
AR8ADOS710T |
AR8ADOS720 |
AR8ADOS720T |
AR8ADOS720T |
AR8ADOS720 |
AR8APTEC715 |
AR8APTEC715T |
AR8ARABICMACT |
AR8ARABICMAC |
AR8ISO8859P6 |
AR8ASMO708PLUS |
AR8ISO8859P6 |
AR8ASMO8X |
AR8MUSSAD768 |
AR8MUSSAD768T |
AR8MUSSAD768T |
AR8MUSSAD768 |
AR8NAFITHA711 |
AR8NAFITHA711T |
AR8NAFITHA721 |
AR8NAFITHA721T |
AR8SAKHR707 |
AR8SAKHR707T |
AR8SAKHR707T |
AR8SAKHR707 |
BLT8CP921 |
BLT8ISO8859P13 |
BLT8CP921 |
LT8MSWIN921 |
D7DEC |
D7SIEMENS9780X |
D7SIEMENS9780X |
D7DEC |
DK7SIEMENS9780X |
N7SIEMENS9780X |
I7DEC |
I7SIEMENS9780X |
I7SIEMENS9780X |
IW8EBCDIC424 |
IW8EBCDIC424 |
IW8EBCDIC1086 |
KO16KSC5601 |
KO16MSWIN949 |
LT8MSWIN921 |
BLT8ISO8859P13 |
LT8MSWIN921 |
BLT8CP921 |
N7SIEMENS9780X |
DK7SIEMENS9780X |
US7ASCII |
See Table A-12, "US7ASCII Supersets". |
UTF8 |
AL32UTF8 |
WE8DEC |
TR8DEC |
WE8DEC |
WE8NCR4970 |
WE8ISO8859P1 |
WE8MSWIN1252 |
WE8ISO8859P9 |
TR8MSWIN1254 |
WE8NCR4970 |
TR8DEC |
WE8NCR4970 |
WE8DEC |
WE8PC850 |
WE8PC858 |
1: SQL>CONN / AS SYSDBA;
2:
3: SQL>SHUTDOWN IMMEDIATE;
4:
5: SQL>STARTUP MOUNT;
6:
7: SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
8:
9: SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
10:
11: SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
12:
13: SQL>ALTER DATABASE OPEN;
--能夠從子集到父集
1: SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
2:
3: --若是是從父集到子集,須要使用INTERNAL_USE參數,跳過超子集檢測
4:
5: SQL>ALTER DATABASE NATIONAL CHARACTER SET UTF8;
6:
7: --SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;
8:
9: SQL>SHUTDOWN IMMEDIATE;
10:
11: SQL>STARTUP;
ALTER DATABASE NATIONAL CHARACTER SET UTF8;
有可能會出現ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists 這樣的提示信息.這時你用ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;就可解決上述問題。
參考資料:
http://blog.csdn.net/jkl_123/article/details/6157379
http://blog.csdn.net/tianlesoftware/article/details/4915223