數(shù)據(jù)庫(kù)亂碼的原因與解決
2005-08-24 10:00 am
作者:linux寶庫(kù) ( http://www.linuxmine.com )
來(lái)自:linux寶庫(kù) ( http://www.linuxmine.com )
聯(lián)系:linuxmine#gmail.com
在SQL*Plus中用insert插進(jìn)的都是中文的,為什么一存入服務(wù)器后,再select出的就是???”
“有的時(shí)候,服務(wù)器數(shù)據(jù)先導(dǎo)出,重裝服務(wù)器,再導(dǎo)入數(shù)據(jù),結(jié)果,發(fā)生數(shù)據(jù)查詢成???”
……
這些問(wèn)題,一般是因?yàn)樽址O(shè)置不對(duì)造成的。
很久以來(lái),字符集一直是困擾著眾多Oracle愛(ài)好者的問(wèn)題,筆者從事Oracle數(shù)據(jù)庫(kù)管理和應(yīng)用已經(jīng)幾年了,經(jīng)常接到客戶的類似上面提到的有關(guān)數(shù)據(jù)庫(kù)字符集的“告急”和“求救”,在此我們就這個(gè)問(wèn)題做一些分析和探討。
首先,我們要明確什么是字符集?字符集是一個(gè)字節(jié)數(shù)據(jù)的解釋的符號(hào)集合,有大小之分,有相互的包括關(guān)系,如us7ascii就是zhs16gbk的子集, 從us7ascii到zhs16gbk不會(huì)有數(shù)據(jù)解釋上的問(wèn)題,不會(huì)有數(shù)據(jù)丟失,Oracle對(duì)這種問(wèn)題也要求從子集到超集的導(dǎo)出受支持,反之不行。在所 有的字符集中utf8應(yīng)該是最大,因?yàn)樗趗nicode,雙字節(jié)保存字符(也因此在存儲(chǔ)空間上占用更多)。
其次,一旦數(shù)據(jù)庫(kù)創(chuàng)建后,數(shù)據(jù)庫(kù)的字符集是不能改變的。因此,在設(shè)計(jì)和安裝之初考慮使用哪一種字符集是十分重要的。數(shù)據(jù)庫(kù)字符集應(yīng)該是操作系統(tǒng)本地字符集的一個(gè)超集。存取數(shù)據(jù)庫(kù)的客戶使用的字符集將決定選擇哪一個(gè)超集,即數(shù)據(jù)庫(kù)字符集應(yīng)該是所有客戶字符集的超集。
在實(shí)際應(yīng)用中,和字符集問(wèn)題關(guān)系最大的恐怕就是exp/imp了。在做exp/imp時(shí),如果Client 和Server的nls_lang設(shè)置是一樣的,一般就沒(méi)有問(wèn)題的。但是,要在兩個(gè)不同字符集的系統(tǒng)之間導(dǎo)數(shù)據(jù)就經(jīng)常會(huì)有這樣或那樣的問(wèn)題,如,導(dǎo)出時(shí)數(shù) 據(jù)庫(kù)的顯示正常,是中文,當(dāng)導(dǎo)入到其他系統(tǒng)時(shí),就成了亂碼,這也是一類常見(jiàn)問(wèn)題。
現(xiàn)在,介紹一些與字符集有關(guān)的NLS_LANG參數(shù),
NLS_LANG格式:
NLS_LANG = language_territory.charset
有三個(gè)組成部分(語(yǔ)言、地域和字符集),每個(gè)成分控制了NLS子集的特性。其中:language 指定服務(wù)器消息的語(yǔ)言。
territory 指定服務(wù)器的日期和數(shù)字格式。
charset 指定字符集
例如:
AMERICAN_AMERICA.US7SCII
AMERICAN _ AMERICA. ZHS16GBK
還有一些子集可以更明確定義NLS_LANG參數(shù):
DICT.BASE 數(shù)據(jù)字典基本 表版本
DBTIMEZONE 數(shù)據(jù)庫(kù)時(shí)區(qū)
NLS_LANGUAGE 語(yǔ)言
NLS_TERRITORY 地域
NLS_CURRENCY 本地貨幣字符
NLS_ISO_CURRENCY ISO貨幣字符
NLS_NUMERIC_CHARACTERS 小數(shù)字符和組 分隔開(kāi)
NLS_CHARACTERSET 字符集
NLS_CALENDAR 日歷系統(tǒng)
NLS_DATE_FORMAT 缺省的日期格式
NLS_DATE_LANGUAGE 缺省的日期語(yǔ)言
NLS_SORT 字符排序序列
NLS_TIME_FORMAT 時(shí)間格式
NLS_TIMESTAMP_FORMAT 時(shí)間戳格式
……
通過(guò)props$動(dòng)態(tài)性能視圖,我們可以查看數(shù)據(jù)庫(kù)的字符集信息:
$> sqlplus internal
SQL> desc props$
Name Type Nullable Default Comments
NAME VARCHAR2(30)
VALUE$ VARCHAR2(4000) Y
COMMENT$ VARCHAR2(4000) Y
SQL> set arraysize 1
SQL> col value$ format a40
SQL> select name,value$ from props$ where name=‘NLS_CHARACTERSET’;
NAME VALUE$
NLS_CHARACTERSET ZHS16GBK
SQL> select * from sys.props$;
NAME VALUE$
DICT.BASE 2
DBTIMEZONE 0:00
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET ZHS16GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI. SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.
SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT DD-MON- RR HH.MI. SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_NCHAR_CHARACTERSET ZHS16GBK
NLS_RDBMS_VERSION 8.1.6.0.0
NAME VALUE$
GLOBAL_DB_NAME SCPDB1
EXPORT_VIEWS_VERSION 8
22 rows selected
SQL>
從結(jié)果可以看出:
NLS_LANG = AMERICAN _ AMERICA. ZHS16GBK
雖然,數(shù)據(jù)庫(kù)的字符集是在create database的時(shí)候指定的,以后不允許改變,但在一個(gè)已經(jīng)建立好的數(shù)據(jù)庫(kù)上,我們可以通過(guò)修改SYS.PROPS$來(lái)修改主要是對(duì)應(yīng)客戶端的顯示,與存儲(chǔ)無(wú)關(guān)。
如:
SQL> conn / as sysdba
Connected.
SQL> SQL> select * from sys.props$
2 WHERE NAME=‘NLS_LANGUAGE’;
NAME VALUE$
NLS_LANGUAGE AMERICAN
SQL>
SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’
2 WHERE NAME=‘NLS_LANGUAGE’;
1 row updated
SQL>
SQL> select * from sys.props$
2 WHERE NAME=‘NLS_LANGUAGE’;
NAME VALUE$
NLS_LANGUAGE SIMPLIFIED CHINESE
SQL>
通常出現(xiàn)問(wèn)題的原因,可分為三種:
1. 服務(wù)器指定字符集與客戶字符集不同,而與加載數(shù)據(jù)字符集一致。
解決方法:對(duì)于這種情況,只需要設(shè)置客戶端字符集與服務(wù)器端字符集一致就可以了,具體操作如下:
* 查看當(dāng)前字符集:
SQL> select * from sys.props$
2 WHERE NAME=‘NLS_CHARACTERSET’;
NAME VALUE$
NLS_CHARACTERSET ZHS16GBK
SQL>
可以看出,現(xiàn)在服務(wù)器端Oracle數(shù)據(jù)庫(kù)的字符集為‘ZHS16GBK’
* 根據(jù)服務(wù)器的字符集在客戶端作相應(yīng)的配置或者安裝Oracle的客戶端軟件時(shí)指定:
如果還沒(méi)安裝客戶端,那么在安裝客戶端時(shí),指定與服務(wù)器相吻合的字符集即可;如果已經(jīng)安裝好了客戶端,并且客戶端為 sql*net 2.0 以下版本,進(jìn)入Windows的系統(tǒng)目錄,編輯oracle.ini文件,用US7ASCII替換原字符集,重新啟動(dòng)計(jì)算機(jī),設(shè)置生效;否則,如果,客戶 端為 sql*net 2.0 以上版本,在Win98 下 運(yùn)行REGEDIT,第一步選HKEY_LOCAL_MACHINE,第二步選擇SOFTWARE, 第三步選擇 Oracle, 第四步選擇 NLS_LANG, 鍵 入 與服 務(wù) 器 端 相 同 的 字 符 集
(本例為:HKEY_LOCAL_MACHINE\
SOFTWARE\ORACLE\NLS_LANG :AMERICAN _ AMERICA. ZHS16GBK)。
如果是UNIX客戶端,則:
SQL> conn / as sysdba
Connected.
SQL> SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’
2 WHERE NAME=‘NLS_LANGUAGE’;
1 row updated
SQL> COMMIT;
Commit complete
SQL>
2. 服務(wù)器指定字符集與客戶字符集相同,與加載數(shù)據(jù)字符集不一致。
解決方法:強(qiáng)制加載數(shù)據(jù)字符集與服務(wù)器端字符集一致。要做到這一點(diǎn),可以通過(guò)重新創(chuàng)建數(shù)據(jù)庫(kù),并選擇與原卸出數(shù)據(jù)一致的字符集,然后IMP數(shù)據(jù),這種情況僅僅適用于空庫(kù)和具有同一種字符集的數(shù)據(jù)。
解決這類問(wèn)題,也可以先將數(shù)據(jù)加載到具有相同字符集的服務(wù)器上,然后用轉(zhuǎn)換工具卸出為foxbase 格式或access格式數(shù)據(jù)庫(kù),再用轉(zhuǎn)換工具轉(zhuǎn)入到不同字符集的Oracle數(shù)據(jù)庫(kù)中,這樣就避免了Oracle字符集的困擾。目前數(shù)據(jù)庫(kù)格式轉(zhuǎn)換的工具 很多,像power builder5.0以上版本提供的pipeline及Microsoft Access數(shù)據(jù)庫(kù)提供的數(shù)據(jù)導(dǎo)入/導(dǎo)出功能等。
3. 服務(wù)器指定字符集與客戶字符集不同,與輸入數(shù)據(jù)字符集不一致。
對(duì)于這種情況,目前為止都還沒(méi)有太好的解決方法。
通過(guò)上面的了解,我們知道,導(dǎo)致在后期使用數(shù)據(jù)庫(kù)時(shí)出現(xiàn)種種關(guān)于字符集的問(wèn)題,多半是由于在數(shù)據(jù)庫(kù)設(shè)計(jì)、安裝之初沒(méi)有很好地考慮到以后的需要,所以,我們完全可以通過(guò)在服務(wù)器上和客戶端使用相同的字符集來(lái)避免由此類問(wèn)題引出的麻煩。
全文結(jié)束
2005-08-24 10:00 am
作者:linux寶庫(kù) ( http://www.linuxmine.com )
來(lái)自:linux寶庫(kù) ( http://www.linuxmine.com )
聯(lián)系:linuxmine#gmail.com
在SQL*Plus中用insert插進(jìn)的都是中文的,為什么一存入服務(wù)器后,再select出的就是???”
“有的時(shí)候,服務(wù)器數(shù)據(jù)先導(dǎo)出,重裝服務(wù)器,再導(dǎo)入數(shù)據(jù),結(jié)果,發(fā)生數(shù)據(jù)查詢成???”
……
這些問(wèn)題,一般是因?yàn)樽址O(shè)置不對(duì)造成的。
很久以來(lái),字符集一直是困擾著眾多Oracle愛(ài)好者的問(wèn)題,筆者從事Oracle數(shù)據(jù)庫(kù)管理和應(yīng)用已經(jīng)幾年了,經(jīng)常接到客戶的類似上面提到的有關(guān)數(shù)據(jù)庫(kù)字符集的“告急”和“求救”,在此我們就這個(gè)問(wèn)題做一些分析和探討。
首先,我們要明確什么是字符集?字符集是一個(gè)字節(jié)數(shù)據(jù)的解釋的符號(hào)集合,有大小之分,有相互的包括關(guān)系,如us7ascii就是zhs16gbk的子集, 從us7ascii到zhs16gbk不會(huì)有數(shù)據(jù)解釋上的問(wèn)題,不會(huì)有數(shù)據(jù)丟失,Oracle對(duì)這種問(wèn)題也要求從子集到超集的導(dǎo)出受支持,反之不行。在所 有的字符集中utf8應(yīng)該是最大,因?yàn)樗趗nicode,雙字節(jié)保存字符(也因此在存儲(chǔ)空間上占用更多)。
其次,一旦數(shù)據(jù)庫(kù)創(chuàng)建后,數(shù)據(jù)庫(kù)的字符集是不能改變的。因此,在設(shè)計(jì)和安裝之初考慮使用哪一種字符集是十分重要的。數(shù)據(jù)庫(kù)字符集應(yīng)該是操作系統(tǒng)本地字符集的一個(gè)超集。存取數(shù)據(jù)庫(kù)的客戶使用的字符集將決定選擇哪一個(gè)超集,即數(shù)據(jù)庫(kù)字符集應(yīng)該是所有客戶字符集的超集。
在實(shí)際應(yīng)用中,和字符集問(wèn)題關(guān)系最大的恐怕就是exp/imp了。在做exp/imp時(shí),如果Client 和Server的nls_lang設(shè)置是一樣的,一般就沒(méi)有問(wèn)題的。但是,要在兩個(gè)不同字符集的系統(tǒng)之間導(dǎo)數(shù)據(jù)就經(jīng)常會(huì)有這樣或那樣的問(wèn)題,如,導(dǎo)出時(shí)數(shù) 據(jù)庫(kù)的顯示正常,是中文,當(dāng)導(dǎo)入到其他系統(tǒng)時(shí),就成了亂碼,這也是一類常見(jiàn)問(wèn)題。
現(xiàn)在,介紹一些與字符集有關(guān)的NLS_LANG參數(shù),
NLS_LANG格式:
NLS_LANG = language_territory.charset
有三個(gè)組成部分(語(yǔ)言、地域和字符集),每個(gè)成分控制了NLS子集的特性。其中:language 指定服務(wù)器消息的語(yǔ)言。
territory 指定服務(wù)器的日期和數(shù)字格式。
charset 指定字符集
例如:
AMERICAN_AMERICA.US7SCII
AMERICAN _ AMERICA. ZHS16GBK
還有一些子集可以更明確定義NLS_LANG參數(shù):
DICT.BASE 數(shù)據(jù)字典基本 表版本
DBTIMEZONE 數(shù)據(jù)庫(kù)時(shí)區(qū)
NLS_LANGUAGE 語(yǔ)言
NLS_TERRITORY 地域
NLS_CURRENCY 本地貨幣字符
NLS_ISO_CURRENCY ISO貨幣字符
NLS_NUMERIC_CHARACTERS 小數(shù)字符和組 分隔開(kāi)
NLS_CHARACTERSET 字符集
NLS_CALENDAR 日歷系統(tǒng)
NLS_DATE_FORMAT 缺省的日期格式
NLS_DATE_LANGUAGE 缺省的日期語(yǔ)言
NLS_SORT 字符排序序列
NLS_TIME_FORMAT 時(shí)間格式
NLS_TIMESTAMP_FORMAT 時(shí)間戳格式
……
通過(guò)props$動(dòng)態(tài)性能視圖,我們可以查看數(shù)據(jù)庫(kù)的字符集信息:
$> sqlplus internal
SQL> desc props$
Name Type Nullable Default Comments
NAME VARCHAR2(30)
VALUE$ VARCHAR2(4000) Y
COMMENT$ VARCHAR2(4000) Y
SQL> set arraysize 1
SQL> col value$ format a40
SQL> select name,value$ from props$ where name=‘NLS_CHARACTERSET’;
NAME VALUE$
NLS_CHARACTERSET ZHS16GBK
SQL> select * from sys.props$;
NAME VALUE$
DICT.BASE 2
DBTIMEZONE 0:00
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET ZHS16GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI. SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.
SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT DD-MON- RR HH.MI. SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_NCHAR_CHARACTERSET ZHS16GBK
NLS_RDBMS_VERSION 8.1.6.0.0
NAME VALUE$
GLOBAL_DB_NAME SCPDB1
EXPORT_VIEWS_VERSION 8
22 rows selected
SQL>
從結(jié)果可以看出:
NLS_LANG = AMERICAN _ AMERICA. ZHS16GBK
雖然,數(shù)據(jù)庫(kù)的字符集是在create database的時(shí)候指定的,以后不允許改變,但在一個(gè)已經(jīng)建立好的數(shù)據(jù)庫(kù)上,我們可以通過(guò)修改SYS.PROPS$來(lái)修改主要是對(duì)應(yīng)客戶端的顯示,與存儲(chǔ)無(wú)關(guān)。
如:
SQL> conn / as sysdba
Connected.
SQL> SQL> select * from sys.props$
2 WHERE NAME=‘NLS_LANGUAGE’;
NAME VALUE$
NLS_LANGUAGE AMERICAN
SQL>
SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’
2 WHERE NAME=‘NLS_LANGUAGE’;
1 row updated
SQL>
SQL> select * from sys.props$
2 WHERE NAME=‘NLS_LANGUAGE’;
NAME VALUE$
NLS_LANGUAGE SIMPLIFIED CHINESE
SQL>
通常出現(xiàn)問(wèn)題的原因,可分為三種:
1. 服務(wù)器指定字符集與客戶字符集不同,而與加載數(shù)據(jù)字符集一致。
解決方法:對(duì)于這種情況,只需要設(shè)置客戶端字符集與服務(wù)器端字符集一致就可以了,具體操作如下:
* 查看當(dāng)前字符集:
SQL> select * from sys.props$
2 WHERE NAME=‘NLS_CHARACTERSET’;
NAME VALUE$
NLS_CHARACTERSET ZHS16GBK
SQL>
可以看出,現(xiàn)在服務(wù)器端Oracle數(shù)據(jù)庫(kù)的字符集為‘ZHS16GBK’
* 根據(jù)服務(wù)器的字符集在客戶端作相應(yīng)的配置或者安裝Oracle的客戶端軟件時(shí)指定:
如果還沒(méi)安裝客戶端,那么在安裝客戶端時(shí),指定與服務(wù)器相吻合的字符集即可;如果已經(jīng)安裝好了客戶端,并且客戶端為 sql*net 2.0 以下版本,進(jìn)入Windows的系統(tǒng)目錄,編輯oracle.ini文件,用US7ASCII替換原字符集,重新啟動(dòng)計(jì)算機(jī),設(shè)置生效;否則,如果,客戶 端為 sql*net 2.0 以上版本,在Win98 下 運(yùn)行REGEDIT,第一步選HKEY_LOCAL_MACHINE,第二步選擇SOFTWARE, 第三步選擇 Oracle, 第四步選擇 NLS_LANG, 鍵 入 與服 務(wù) 器 端 相 同 的 字 符 集
(本例為:HKEY_LOCAL_MACHINE\
SOFTWARE\ORACLE\NLS_LANG :AMERICAN _ AMERICA. ZHS16GBK)。
如果是UNIX客戶端,則:
SQL> conn / as sysdba
Connected.
SQL> SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’
2 WHERE NAME=‘NLS_LANGUAGE’;
1 row updated
SQL> COMMIT;
Commit complete
SQL>
2. 服務(wù)器指定字符集與客戶字符集相同,與加載數(shù)據(jù)字符集不一致。
解決方法:強(qiáng)制加載數(shù)據(jù)字符集與服務(wù)器端字符集一致。要做到這一點(diǎn),可以通過(guò)重新創(chuàng)建數(shù)據(jù)庫(kù),并選擇與原卸出數(shù)據(jù)一致的字符集,然后IMP數(shù)據(jù),這種情況僅僅適用于空庫(kù)和具有同一種字符集的數(shù)據(jù)。
解決這類問(wèn)題,也可以先將數(shù)據(jù)加載到具有相同字符集的服務(wù)器上,然后用轉(zhuǎn)換工具卸出為foxbase 格式或access格式數(shù)據(jù)庫(kù),再用轉(zhuǎn)換工具轉(zhuǎn)入到不同字符集的Oracle數(shù)據(jù)庫(kù)中,這樣就避免了Oracle字符集的困擾。目前數(shù)據(jù)庫(kù)格式轉(zhuǎn)換的工具 很多,像power builder5.0以上版本提供的pipeline及Microsoft Access數(shù)據(jù)庫(kù)提供的數(shù)據(jù)導(dǎo)入/導(dǎo)出功能等。
3. 服務(wù)器指定字符集與客戶字符集不同,與輸入數(shù)據(jù)字符集不一致。
對(duì)于這種情況,目前為止都還沒(méi)有太好的解決方法。
通過(guò)上面的了解,我們知道,導(dǎo)致在后期使用數(shù)據(jù)庫(kù)時(shí)出現(xiàn)種種關(guān)于字符集的問(wèn)題,多半是由于在數(shù)據(jù)庫(kù)設(shè)計(jì)、安裝之初沒(méi)有很好地考慮到以后的需要,所以,我們完全可以通過(guò)在服務(wù)器上和客戶端使用相同的字符集來(lái)避免由此類問(wèn)題引出的麻煩。
全文結(jié)束
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
