ORACLE 支持國(guó)家語(yǔ)言的體系結(jié)構(gòu)允許你使用本地化語(yǔ)言來(lái)存儲(chǔ),處理,檢索數(shù)據(jù)。它使數(shù)據(jù)庫(kù)工具,錯(cuò)誤消息,排序次序,日期,時(shí)間,貨幣,數(shù)字,和日歷自動(dòng)適應(yīng)本地化語(yǔ)言和平臺(tái)。 影響oracle數(shù)據(jù)庫(kù)字符集最重要的參數(shù)是NLS_LANG參數(shù)。它的格式如下: NLS_LANG = language_territory.charset 它有三個(gè)組成部分(語(yǔ)言、地域和字符集),每個(gè)成分控制了NLS子集的特性。其中: Language 指定服務(wù)器消息的語(yǔ)言,territory 指定服務(wù)器的日期和數(shù)字格式,charset 指定字符集。如:AMERICAN _ AMERICA. ZHS16GBK 從NLS_LANG的組成我們可以看出,真正影響數(shù)據(jù)庫(kù)字符集的其實(shí)是第三部分。所以?xún)蓚€(gè)數(shù)據(jù)庫(kù)之間的字符集只要第三部分一樣就可以相互導(dǎo)入導(dǎo)出數(shù)據(jù),前面影響的只是提示信息是中文還是英文。 二、 很多人都碰到過(guò)因?yàn)樽址煌箶?shù)據(jù)導(dǎo)入失敗的情況。這涉及三方面的字符集,一是oracel server端的字符集,二是oracle client端的字符集;三是dmp文件的字符集。在做數(shù)據(jù)導(dǎo)入的時(shí)候,需要這三個(gè)字符集都一致才能正確導(dǎo)入。
日土網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)于2013年開(kāi)始到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
實(shí)現(xiàn)思路:
第一步:先將所有子集數(shù)據(jù)進(jìn)行分組。
sql:select classname from tablename1 group by classname;
第二步:將需要統(tǒng)計(jì)的結(jié)果用count函數(shù)進(jìn)行計(jì)數(shù)即可。
sql:select classname, count( username) from tablename1 group by classname;
解釋?zhuān)阂陨险Z(yǔ)句就是統(tǒng)計(jì)出某個(gè)班級(jí)的所有同學(xué)的個(gè)數(shù)。
Oracle數(shù)據(jù)庫(kù)查看和修改服務(wù)器端的字符集的方法是本文主要要介紹的內(nèi)容,接下來(lái)救讓我們一起來(lái)了解一下這部分內(nèi)容。
A、oracle server 端字符集查詢(xún) select userenv('language') from dual 其中NLS_CHARACTERSET 為server端字符集 NLS_LANGUAGE 為 server端字符顯示形式
B、查詢(xún)oracle client端的字符集 $echo $NLS_LANG 如果發(fā)現(xiàn)你select 出來(lái)的數(shù)據(jù)是亂碼,請(qǐng)把client端的字符集配置成與linux操作系統(tǒng)相同的字符集。如果還是有亂碼,則有可能是數(shù)據(jù)庫(kù)中的數(shù)據(jù)存在問(wèn)題,或者是oracle服務(wù)端的配置存在問(wèn)題。
C、server端字符集修改 將數(shù)據(jù)庫(kù)啟動(dòng)到RESTRICTED模式下做字符集更改: SQL conn /as sysdba Connected. SQL shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL startup mount ORACLE instance started. Total System Global Area 236000356 bytes Fixed Size 451684 bytes Variable Size 201326592 bytes Database Buffers 33554432 bytes Redo Buffers 667648 bytes Database mounted. 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. SQL alter database open; Database altered. SQL ALTER DATABASE CHARACTER SET ZHS16GBK; ALTER DATABASE CHARACTER SET ZHS16GBK ERROR at line 1: ORA-12712: new character set must be a superset of old character set 提示我們的字符集:新字符集必須為舊字符集的超集,這時(shí)我們可以跳過(guò)超集的檢查做更改: SQL ALTER DATABASE character set INTERNAL_USE ZHS16GBK; Database altered. SQL select * from v$nls_parameters; 略 19 rows selected. 重啟檢查是否更改完成: SQL shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL startup ORACLE instance started. Total System Global Area 236000356 bytes Fixed Size 451684 bytes Variable Size 201326592 bytes Database Buffers 33554432 bytes Redo Buffers 667648 bytes Database mounted. Database opened. SQL select * from v$nls_parameters; 略 19 rows selected. 我們看到這個(gè)過(guò)程和之前ALTER DATABASE CHARACTER SET操作的內(nèi)部過(guò)程是完全相同的,也就是說(shuō)INTERNAL_USE提供的幫助就是使Oracle數(shù)據(jù)庫(kù)繞過(guò)了子集與超集的校驗(yàn)。 這一方法在某些方面是有用處的,比如測(cè)試;應(yīng)用于產(chǎn)品環(huán)境大家應(yīng)該格外小心,除了你以外,沒(méi)有人會(huì)為此帶來(lái)的后果負(fù)責(zé)。 結(jié)語(yǔ)(我們不妨再說(shuō)一次): 對(duì)于DBA來(lái)說(shuō),有一個(gè)很重要的原則就是:不要把你的數(shù)據(jù)庫(kù)置于危險(xiǎn)的境地! 這就要求我們,在進(jìn)行任何可能對(duì)數(shù)據(jù)庫(kù)結(jié)構(gòu)發(fā)生改變的操作之前,先做有效的備份,很多DBA沒(méi)有備份的操作中得到了慘痛的教訓(xùn)。
D、client端字符集修改 在 /home/oracle與 /root用戶(hù)目錄下的。bash_profile中 添加或修改 export NLS_LANG="AMERICAN_AMERICA.UTF8" 語(yǔ)句
希望可以幫到您,謝謝!
需要用exp和imp命令,具體用法如下:
1. 獲取幫助
imp help=y
2. 導(dǎo)入一個(gè)完整數(shù)據(jù)庫(kù)
imp system/manager file=bible_db log=dible_db full=y ignore=y
3. 導(dǎo)入一個(gè)或一組指定用戶(hù)所屬的全部表、索引和其他對(duì)象
imp system/manager file=seapark log=seapark fromuser=seapark
imp system/manager file=seapark log=seapark fromuser=(seapark,amy,amyc,harold)
4. 將一個(gè)用戶(hù)所屬的數(shù)據(jù)導(dǎo)入另一個(gè)用戶(hù)
imp system/manager file=tank log=tank fromuser=seapark touser=seapark_copy
imp system/manager file=tank log=tank fromuser=(seapark,amy)
touser=(seapark1, amy1)
5. 導(dǎo)入一個(gè)表
imp system/manager file=tank log=tank fromuser=seapark TABLES=(a,b)
6. 從多個(gè)文件導(dǎo)入
imp system/manager file=(paycheck_1,paycheck_2,paycheck_3,paycheck_4)
log=paycheck, filesize=1G full=y
7. 使用參數(shù)文件
imp system/manager parfile=bible_tables.par
bible_tables.par參數(shù)文件:
#Import the sample tables used for the Oracle8i Database Administrator's
Bible. fromuser=seapark touser=seapark_copy file=seapark log=seapark_import
8. 增量導(dǎo)入
imp system./manager inctype= RECTORE FULL=Y FILE=A
-------------------------------------------------------------------------------------------------------------------------------------------
1. 獲取幫助
exp help=y
2. 導(dǎo)出一個(gè)完整數(shù)據(jù)庫(kù)
exp system/manager file=bible_db log=dible_db full=y
3. 導(dǎo)出數(shù)據(jù)庫(kù)定義而不導(dǎo)出數(shù)據(jù)
exp system/manager file=bible_db log=dible_db full=y rows=n
4. 導(dǎo)出一個(gè)或一組指定用戶(hù)所屬的全部表、索引和其他對(duì)象
exp system/manager file=seapark log=seapark owner=seapark
exp system/manager file=seapark log=seapark owner=(seapark,amy,amyc,harold)
注意:在導(dǎo)出用戶(hù)時(shí),盡管已經(jīng)得到了這個(gè)用戶(hù)的所有對(duì)象,但是還是不能得到這些對(duì)象引用的任何同義詞。解決方法是用以下的SQL*Plus命令創(chuàng)建一個(gè)腳本文件,運(yùn)行這個(gè)腳本文件可以獲得一個(gè)重建seapark所屬對(duì)象的全部公共同義詞的可執(zhí)行腳本,然后在目標(biāo)數(shù)據(jù)庫(kù)上運(yùn)行該腳本就可重建同義詞了。
SET LINESIZE 132
SET PAGESIZE 0
SET TRIMSPOOL ON
SPOOL c:\seapark.syn
SELECT 'Create public synonym '||synonym_name
||' for '||table_owner||'.'||table_name||';'
FROM dba_synonyms
WHERE table_owner = 'SEAPARK' AND owner = 'PUBLIC';
SPOOL OFF
5. 導(dǎo)出一個(gè)或多個(gè)指定表
exp seapark/seapark file=tank log=tank tables=tank
exp system/manager file=tank log=tank tables=seapark.tank
exp system/manager file=tank log=tank tables=(seapark.tank,amy.artist)
6. 估計(jì)導(dǎo)出文件的大小
全部表總字節(jié)數(shù):
SELECT sum(bytes)
FROM dba_segments
WHERE segment_type = 'TABLE';
seapark用戶(hù)所屬表的總字節(jié)數(shù):
SELECT sum(bytes)
FROM dba_segments
WHERE owner = 'SEAPARK'
AND segment_type = 'TABLE';
seapark用戶(hù)下的aquatic_animal表的字節(jié)數(shù):
SELECT sum(bytes)
FROM dba_segments
WHERE owner = 'SEAPARK'
AND segment_type = 'TABLE'
AND segment_name = 'AQUATIC_ANIMAL';
7. 導(dǎo)出表數(shù)據(jù)的子集(oracle8i以上)
NT系統(tǒng):
exp system/manager query='Where salad_type='FRUIT'' tables=amy.salad_type
file=fruit log=fruit
UNIX系統(tǒng):
exp system/manager query=\"Where salad_type=\'FRUIT\'\" tables=amy.salad_type
file=fruit log=fruit
8. 用多個(gè)文件分割一個(gè)導(dǎo)出文件
exp system/manager
file=(paycheck_1,paycheck_2,paycheck_3,paycheck_4)
log=paycheck, filesize=1G tables=hr.paycheck
9. 使用參數(shù)文件
exp system/manager parfile=bible_tables.par
bible_tables.par參數(shù)文件:
#Export the sample tables used for the Oracle8i Database Administrator's Bible.
file=bible_tables
log=bible_tables
tables=(
amy.artist
amy.books
seapark.checkup
seapark.items
)
10. 增量導(dǎo)出
“完全”增量導(dǎo)出(complete),即備份整個(gè)數(shù)據(jù)庫(kù)
exp system/manager inctype=complete file=990702.dmp
“增量型”增量導(dǎo)出(incremental),即備份上一次備份后改變的數(shù)據(jù)
exp system/manager inctype=incremental file=990702.dmp
“累計(jì)型”增量導(dǎo)出(cumulative),即備份上一次“完全”導(dǎo)出之后改變的數(shù)據(jù)
exp system/manager inctype=cumulative file=990702.dmp
可以先把日期類(lèi)型通過(guò) TO_CHAR方法轉(zhuǎn)換為字符串,之后在進(jìn)行月份查詢(xún)。
sql:select * from tablename WHERE TO_CHAR( dateTime, 'YYYY-MM') = '2015-06';
解釋?zhuān)阂陨险Z(yǔ)句就是查詢(xún)查2015年06月份的所有數(shù)據(jù)記錄。
理解ORACLE數(shù)據(jù)庫(kù)字符集
一.引言
ORACLE數(shù)據(jù)庫(kù)字符集,即Oracle全球化支持(Globalization Support),或即國(guó)家語(yǔ)言支持(NLS)其作用是用本國(guó)語(yǔ)言和格式來(lái)存儲(chǔ)、處理和檢索數(shù)據(jù)。利用全球化支持,ORACLE為用戶(hù)提供自己熟悉的數(shù)據(jù)庫(kù)母語(yǔ)環(huán)境,諸如日期格式、數(shù)字格式和存儲(chǔ)序列等。Oracle可以支持多種語(yǔ)言及字符集,其中oracle8i支持48種語(yǔ)言、76個(gè)國(guó)家地域、229種字符集,而oracle9i則支持57種語(yǔ)言、88個(gè)國(guó)家地域、235種字符集。由于oracle字符集種類(lèi)多,且在存儲(chǔ)、檢索、遷移oracle數(shù)據(jù)時(shí)多個(gè)環(huán)節(jié)與字符集的設(shè)置密切相關(guān),因此在實(shí)際的應(yīng)用中,數(shù)據(jù)庫(kù)開(kāi)發(fā)和管理人員經(jīng)常會(huì)遇到有關(guān)oracle字符集方面的問(wèn)題。本文通過(guò)以下幾個(gè)方面闡述,對(duì)oracle字符集做簡(jiǎn)要分析
二.字符集基本知識(shí)
2.1字符集
實(shí)質(zhì)就是按照一定的字符編碼方案,對(duì)一組特定的符號(hào),分別賦予不同數(shù)值編碼的集合。Oracle數(shù)據(jù)庫(kù)最早支持的編碼方案是US7ASCII。
Oracle 的字符集命名遵循以下命名規(guī)則 :
即: 語(yǔ)言比特位數(shù)編碼
比如: ZHS16GBK表示采用GBK編碼格式、16位(兩個(gè)字節(jié))簡(jiǎn)體中文字符集
2.2字符編碼方案
2.2.1 單字節(jié)編碼
(1)單字節(jié)7位字符集,可以定義128個(gè)字符,最常用的字符集為 US7ASCII
(2)單字節(jié)8位字符集,可以定義256個(gè)字符,適合于歐洲大部分國(guó)家
例如:WE8ISO8859P1(西歐、8位、ISO標(biāo)準(zhǔn)8859P1編碼 )
2.2.2 多字節(jié)編碼
(1)變長(zhǎng)多字節(jié)編碼
某些字符用一個(gè)字節(jié)表示,其它字符用兩個(gè)或多個(gè)字符表示,變長(zhǎng)多字節(jié)編碼常用于對(duì)亞洲語(yǔ)言的支持, 例如日語(yǔ)、漢語(yǔ)、印地語(yǔ)等
例如:AL32UTF8(其中AL代表ALL,指適用于所有語(yǔ)言)、 zhs16cgb231280
(2)定長(zhǎng)多字節(jié)編碼
每一個(gè)字符都使用固定長(zhǎng)度字節(jié)的編碼方案,目前oracle唯一支持的定長(zhǎng)多字節(jié)編碼是AF16UTF16,也是僅用于國(guó)家字符集
2.2.3 unicode 編碼
Unicode 是一個(gè)涵蓋了目前全世界使用的所有已知字符的單一編碼方案,也就是說(shuō)Unicode為每一個(gè)字符提供唯一的編碼。UTF-16是unicode的16位編碼方式,是一種定長(zhǎng)多字節(jié)編碼,用2個(gè)字節(jié)表示一個(gè)unicode字符,AF16UTF16是UTF-16編碼字符集。
UTF-8 是unicode的8位編碼方式,是一種變長(zhǎng)多字節(jié)編碼,這種編碼可以用1、2、3個(gè)字節(jié)表示一個(gè)unicode字符,AL32UTF8,UTF8、UTFE是UTF-8編碼字符集
2.3 字符集超級(jí)
當(dāng)一種字符集(字符集A)的編碼數(shù)值包含所有另一種字符集(字符集B)的編碼數(shù)值,并且兩種字符集相同編碼數(shù)值代表相同的字符時(shí),則字符集A是字符集B的超級(jí),或稱(chēng)字符集B是字符集A的子集。
Oracle8i 和oracle9i官方文檔資料中備有子集-超級(jí)對(duì)照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle數(shù)據(jù)庫(kù)編碼格式,因此有許多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
2.4 數(shù)據(jù)庫(kù)字符集(oracle服務(wù)器端字符集)
數(shù)據(jù)庫(kù)字符集在創(chuàng)建數(shù)據(jù)庫(kù)時(shí)指定,在創(chuàng)建后通常不能更改。在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),可以指定字符集(CHARACTER SET)和國(guó)家字符集(NATIONAL CHARACTER SET)。
2.4.1 字符集
(1) 用來(lái)存儲(chǔ)CHAR, VARCHAR2, CLOB, LONG等類(lèi)型數(shù)據(jù)
(2) 用來(lái)標(biāo)示諸如表名、列名以及PL/SQL變量等
(3) 用來(lái)存儲(chǔ)SQL和PL/SQL程序單元等
2.4.2 國(guó)家字符集:
(1) 用以存儲(chǔ)NCHAR, NVARCHAR2, NCLOB等類(lèi)型數(shù)據(jù)
(2) 國(guó)家字符集實(shí)質(zhì)上是為oracle選擇的附加字符集,主要作用是為了增強(qiáng)oracle的字符處理能力,因?yàn)镹CHAR數(shù)據(jù)類(lèi)型可以提供對(duì)亞洲使用定長(zhǎng)多字節(jié)編碼的支持,而數(shù)據(jù)庫(kù)字符集則不能。國(guó)家字符集在oracle9i中進(jìn)行了重新定義,只能在unicode編碼中的AF16UTF16和UTF8中選擇,默認(rèn)值是 AF16UTF16
2.4.3查詢(xún)字符集參數(shù)
可以查詢(xún)以下數(shù)據(jù)字典或視圖查看字符集設(shè)置情況
nls_database_parameters 、props$、 v$nls_parameters
查詢(xún)結(jié)果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示國(guó)家字符集
2.4.4 修改數(shù)據(jù)庫(kù)字符集
按照上文所說(shuō),數(shù)據(jù)庫(kù)字符集在創(chuàng)建后原則上不能更改。如果需要修改字符集,通常需要導(dǎo)出數(shù)據(jù)庫(kù)數(shù)據(jù),重建數(shù)據(jù)庫(kù),再導(dǎo)入數(shù)據(jù)庫(kù)數(shù)據(jù)的方式來(lái)轉(zhuǎn)換,或通過(guò)ALTER DATABASE CHARACTER SET語(yǔ)句修改字符集,但創(chuàng)建數(shù)據(jù)庫(kù)后修改字符集是有限制的,只有新的字符集是當(dāng)前字符集的超集時(shí)才能修改數(shù)據(jù)庫(kù)字符集,例如UTF8是US7ASCII的超集,修改數(shù)據(jù)庫(kù)字符集可使用ALTER DATABASE CHARACTER SET UTF8。
2.5 客戶(hù)端字符集(NLS_LANG參數(shù))
2.5.1 客戶(hù)端字符集含義
客戶(hù)端字符集定義了客戶(hù)端字符數(shù)據(jù)的編碼方式,任何發(fā)自或發(fā)往客戶(hù)端的字符數(shù)據(jù)均使用客戶(hù)端定義的字符集編碼,客戶(hù)端可以看作是能與數(shù)據(jù)庫(kù)直接連接的各種應(yīng)用,例如sqlplus,exp/imp等??蛻?hù)端字符集是通過(guò)設(shè)置NLS_LANG參數(shù)來(lái)設(shè)定的。
2.5.2 NLS_LANG 參數(shù)格式
NLS_LANG=_.
Language: 顯示oracle消息,校驗(yàn),日期命名
Territory :指定默認(rèn)日期、數(shù)字、貨幣等格式
Client character set :指定客戶(hù)端將使用的字符集
例如: NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是語(yǔ)言,AMERICA是地區(qū),US7ASCII是客戶(hù)端字符集
2.5.3 客戶(hù)端字符集設(shè)置方法
1)UNIX 環(huán)境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
編輯oracle用戶(hù)的profile文件
2)Windows 環(huán)境
編輯注冊(cè)表
Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME0
2.5.4 NLS 參數(shù)查詢(xún)
Oracle 提供若干NLS參數(shù)定制數(shù)據(jù)庫(kù)和用戶(hù)機(jī)以適應(yīng)本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通過(guò)查詢(xún)以下數(shù)據(jù)字典或v$視圖查看。
NLS_DATABASE_PARAMETERS-- 顯示數(shù)據(jù)庫(kù)當(dāng)前NLS參數(shù)取值,包括數(shù)據(jù)庫(kù)字符集取值
NLS_SESSION_PARAMETERS-- 顯示由NLS_LANG 設(shè)置的參數(shù),或經(jīng)過(guò)alter session 改變后的參數(shù)值(不包括由NLS_LANG 設(shè)置的客戶(hù)端字符集)
NLS_INSTANCE_PARAMETE-- 顯示由參數(shù)文件init.ora 定義的參數(shù)V$NLS_PARAMETERS--顯示數(shù)據(jù)庫(kù)當(dāng)前NLS參數(shù)取值
2.5.5 修改NLS參數(shù)
使用下列方法可以修改NLS參數(shù)
(1)修改實(shí)例啟動(dòng)時(shí)使用的初始化參數(shù)文件
(2)修改環(huán)境變量 NLS_LANG
(3)使用ALTER SESSION語(yǔ)句,在oracle會(huì)話(huà)中修改
(4)使用某些SQL函數(shù)
NLS 作用優(yōu)先級(jí)別:Sql functionalter session環(huán)境變量或注冊(cè)表參數(shù)文件數(shù)據(jù)庫(kù)默認(rèn)參數(shù)
三.導(dǎo)入/導(dǎo)出與字符集轉(zhuǎn)換
3.1 EXP/IMP
Export 和 Import 是一對(duì)讀寫(xiě)Oracle數(shù)據(jù)的工具。Export 將 Oracle 數(shù)據(jù)庫(kù)中的數(shù)據(jù)輸出到操作系統(tǒng)文件中, Import 把這些文件中的數(shù)據(jù)讀到Oracle 數(shù)據(jù)庫(kù)中,由于使用exp/imp進(jìn)行數(shù)據(jù)遷移時(shí),數(shù)據(jù)從源數(shù)據(jù)庫(kù)到目標(biāo)數(shù)據(jù)庫(kù)的過(guò)程中有四個(gè)環(huán)節(jié)涉及到字符集,如果這四個(gè)環(huán)節(jié)的字符集不一致,將會(huì)發(fā)生字符集轉(zhuǎn)換。
EXP
____________ _________________ _____________
|imp導(dǎo)入文件|--
------------ ----------------- -------------
IMP
____________ _________________ _____________
|imp導(dǎo)入文件|-|環(huán)境變量NLS_LANG|-|數(shù)據(jù)庫(kù)字符集|
------------ ----------------- -------------
四個(gè)字符集是
(1)源數(shù)據(jù)庫(kù)字符集
(2)Export過(guò)程中用戶(hù)會(huì)話(huà)字符集(通過(guò)NLS_LANG設(shè)定)
(3)Import過(guò)程中用戶(hù)會(huì)話(huà)字符集(通過(guò)NLS_LANG設(shè)定)
(4)目標(biāo)數(shù)據(jù)庫(kù)字符集
3.2導(dǎo)出的轉(zhuǎn)換過(guò)程
在Export過(guò)程中,如果源數(shù)據(jù)庫(kù)字符集與Export用戶(hù)會(huì)話(huà)字符集不一致,會(huì)發(fā)生字符集轉(zhuǎn)換,并在導(dǎo)出文件的頭部幾個(gè)字節(jié)中存儲(chǔ)Export用戶(hù)會(huì)話(huà)字符集的ID號(hào)。在這個(gè)轉(zhuǎn)換過(guò)程中可能發(fā)生數(shù)據(jù)的丟失。
例:如果源數(shù)據(jù)庫(kù)使用ZHS16GBK,而Export用戶(hù)會(huì)話(huà)字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,這個(gè)轉(zhuǎn)換過(guò)程中,中文字符在US7ASCII中不能夠找到對(duì)等的字符,所以所有中文字符都會(huì)丟失而變成“?? ”形式,這樣轉(zhuǎn)換后生成的Dmp文件已經(jīng)發(fā)生了數(shù)據(jù)丟失。
因此如果想正確導(dǎo)出源數(shù)據(jù)庫(kù)數(shù)據(jù),則Export過(guò)程中用戶(hù)會(huì)話(huà)字符集應(yīng)等于源數(shù)據(jù)庫(kù)字符集或是源數(shù)據(jù)庫(kù)字符集的超集
3.3導(dǎo)入的轉(zhuǎn)換過(guò)程
(1)確定導(dǎo)出數(shù)據(jù)庫(kù)字符集環(huán)境
通過(guò)讀取導(dǎo)出文件頭,可以獲得導(dǎo)出文件的字符集設(shè)置
(2)確定導(dǎo)入session的字符集,即導(dǎo)入Session使用的NLS_LANG環(huán)境變量
(3)IMP讀取導(dǎo)出文件
讀取導(dǎo)出文件字符集ID,和導(dǎo)入進(jìn)程的NLS_LANG進(jìn)行比較
(4)如果導(dǎo)出文件字符集和導(dǎo)入Session字符集相同,那么在這一步驟內(nèi)就不需要轉(zhuǎn)換,如果不同,就需要把數(shù)據(jù)轉(zhuǎn)換為導(dǎo)入Session使用的字符集。可以看出,導(dǎo)入數(shù)據(jù)到數(shù)據(jù)庫(kù)過(guò)程中發(fā)生兩次字符集轉(zhuǎn)換
第一次:導(dǎo)入文件字符集與導(dǎo)入Session使用的字符集之間的轉(zhuǎn)換,如果這個(gè)轉(zhuǎn)換過(guò)程不能正確完成,Import向目標(biāo)數(shù)據(jù)庫(kù)的導(dǎo)入過(guò)程也就不能完成。
第二次:導(dǎo)入Session字符集與數(shù)據(jù)庫(kù)字符集之間的轉(zhuǎn)換。
然而,oracle8i的這種轉(zhuǎn)換只能在單字節(jié)字符集之間進(jìn)行,oracle8i導(dǎo)入Session不支持多字節(jié)字符集之間的轉(zhuǎn)換,因此為了避免第一次轉(zhuǎn)換,導(dǎo)入Session使用的NLS_LANG與導(dǎo)出文件字符集相同,第二次轉(zhuǎn)換(通過(guò)SQL*Net)支持任何兩種字符集。以上情況在Oracle9i中略有不同
四.亂碼問(wèn)題
oracle在數(shù)據(jù)存儲(chǔ)、遷移過(guò)程中經(jīng)常發(fā)生字符亂碼問(wèn)題,歸根到底是由于字符集使用不當(dāng)引起。下面以使用客戶(hù)端sqlplus向數(shù)據(jù)庫(kù)插入數(shù)據(jù)和導(dǎo)入/導(dǎo)出(EXP/IMP)過(guò)程為例,說(shuō)明亂碼產(chǎn)生的原因。
4.1使用客戶(hù)端sqlplus向數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù)
這個(gè)過(guò)程存在3個(gè)字符集設(shè)置
(1)客戶(hù)端應(yīng)用字符集
(2)客戶(hù)端NLS_LANG參數(shù)設(shè)置
(3)服務(wù)器端數(shù)據(jù)庫(kù)字符集(Character Set)設(shè)置
客戶(hù)端應(yīng)用sqlplus中能夠顯示什么樣的字符取決于客戶(hù)端操作系統(tǒng)語(yǔ)言環(huán)境(客戶(hù)端應(yīng)用字符集),但在應(yīng)用中錄入這些字符后,這些字符能否在數(shù)據(jù)庫(kù)中正常存儲(chǔ),還與另外兩個(gè)字符集設(shè)置緊密相關(guān),其中客戶(hù)端NLS_LANG參數(shù)主要用于字符數(shù)據(jù)傳輸過(guò)程中的轉(zhuǎn)換判斷。常見(jiàn)的亂碼大致有兩種情形:
(1)漢字變成問(wèn)號(hào)“?”;
當(dāng)從字符集A 轉(zhuǎn)換成字符集B時(shí),如果轉(zhuǎn)換字符之間不存在對(duì)應(yīng)關(guān)系,NLS_LANG使用替代字符“?”替代無(wú)法映射的字符
(2)漢字變成未知字符(雖然有些是漢字,但與原字符含義不同)
轉(zhuǎn)換存在對(duì)應(yīng)關(guān)系,但字符集A 中的字符編碼與字符集B 中的字符編碼代表不同含義
4.2發(fā)生亂碼原因
亂碼產(chǎn)生是由于幾個(gè)字符集之間轉(zhuǎn)換不匹配造成,分以下幾種情況:
(注:字符集之間如果不存在子集、超集對(duì)應(yīng)關(guān)系時(shí)的情況不予考慮,因?yàn)檫@種情況下字符集之間轉(zhuǎn)換必產(chǎn)生亂碼)
1)服務(wù)器端數(shù)據(jù)庫(kù)字符集與客戶(hù)端應(yīng)用字符集相同,與客戶(hù)端NLS_LANG參數(shù)設(shè)置不同
如果客戶(hù)端NLS_LANG字符集是其它兩種字符集的子集,轉(zhuǎn)換過(guò)程將出現(xiàn)亂碼。
解決方法:將三種字符集設(shè)置成同一字符集,或NLS_LANG字符集是其它兩種字符集的超集
2 )服務(wù)器端數(shù)據(jù)庫(kù)字符集與客戶(hù)端NLS_LANG參數(shù)設(shè)置相同,與客戶(hù)端應(yīng)用字符集不同
如果客戶(hù)端應(yīng)用字符集是其它兩種字符集的超集時(shí),轉(zhuǎn)換過(guò)程將出現(xiàn)亂碼,但對(duì)于單字節(jié)編碼存儲(chǔ)中文問(wèn)題,可參看本文第5章節(jié)的分析
3 )客戶(hù)端應(yīng)用字符集、客戶(hù)端NLS_LANG參數(shù)設(shè)置、服務(wù)器端數(shù)據(jù)庫(kù)字符集互不相同
此種情況較為復(fù)雜,但三種字符集之間只要有不能轉(zhuǎn)換的字符,則必產(chǎn)生亂碼
4.3導(dǎo)入/導(dǎo)出過(guò)程出現(xiàn)亂碼原因
這個(gè)過(guò)程存在4個(gè)字符集設(shè)置,在3.1章節(jié)中已分析
(1)源數(shù)據(jù)庫(kù)字符集
(2)EXP過(guò)程中NLS_LANG參數(shù)
(3)IMP過(guò)程中NLS_LANG參數(shù)
(4)目標(biāo)數(shù)據(jù)庫(kù)字符集
出現(xiàn)亂碼原因
1 )當(dāng)源數(shù)據(jù)庫(kù)字符集不等于EXP過(guò)程中NLS_LANG參數(shù),且源數(shù)據(jù)庫(kù)字符集是EXP過(guò)程中NLS_LANG的子集,才能保證導(dǎo)出文件正確,其他情況則導(dǎo)出文件字符亂碼
2 )EXP過(guò)程中NLS_LANG字符集不等于IMP過(guò)程中NLS_LANG字符集,且EXP過(guò)程中NLS_LANG字符集是IMP過(guò)程中NLS_LANG字符集的子級(jí), 才能保證第一次轉(zhuǎn)換正常,否則第一次轉(zhuǎn)換中出現(xiàn)亂碼。
3 )如果第一次轉(zhuǎn)換正常,IMP過(guò)程中NLS_LANG字符集是目標(biāo)數(shù)據(jù)庫(kù)字符集的子集或相同,才能保證第二次轉(zhuǎn)換正常,否則則第二次轉(zhuǎn)換中出現(xiàn)亂碼
五.單字節(jié)編碼存儲(chǔ)中文問(wèn)題
由于歷史的原因,早期的oracle沒(méi)有中文字符集(如oracle6、oracle7、oracle7.1),但有的用戶(hù)從那時(shí)起就使用數(shù)據(jù)庫(kù)了,并用US7ASCII字符集存儲(chǔ)了中文,或是有的用戶(hù)在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),不考慮清楚,隨意選擇一個(gè)默認(rèn)的字符集,如WE8ISO8859P1或US7ASCII,而這兩個(gè)字符集都沒(méi)有漢字編碼,雖然有些時(shí)候選用這種字符集好象也能正常使用,但用這種字符集存儲(chǔ)漢字信息從原則上說(shuō)就是錯(cuò)誤的,它會(huì)給數(shù)據(jù)庫(kù)的使用與維護(hù)帶來(lái)一系列的麻煩。
正常情況下,要將漢字存入數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)字符集必須支持中文,而將數(shù)據(jù)庫(kù)字符集設(shè)置為US7ASCII等單字節(jié)字符集是不合適的。US7ASCII字符集只定義了128個(gè)符號(hào),并不支持漢字。另外,如果在SQL*PLUS中能夠輸入中文,操作系統(tǒng)缺省應(yīng)該是支持中文的,但如果在NLS_LANG中的字符集設(shè)置為US7ASCII,顯然也是不正確的,它沒(méi)有反映客戶(hù)端的實(shí)際情況。但在實(shí)際應(yīng)用中漢字顯示卻是正確的,這主要是因?yàn)镺racle檢查數(shù)據(jù)庫(kù)與客戶(hù)端的字符集設(shè)置是同樣的,那么數(shù)據(jù)在客戶(hù)與數(shù)據(jù)庫(kù)之間的存取過(guò)程中將不發(fā)生任何轉(zhuǎn)換,但是這實(shí)際上導(dǎo)致了數(shù)據(jù)庫(kù)標(biāo)識(shí)的字符集與實(shí)際存入的內(nèi)容是不相符的。而在SELECT的過(guò)程中,Oracle同樣檢查發(fā)現(xiàn)數(shù)據(jù)庫(kù)與客戶(hù)端的字符集設(shè)置是相同的,所以它也將存入的內(nèi)容原封不動(dòng)地傳送到客戶(hù)端,而客戶(hù)端操作系統(tǒng)識(shí)別出這是漢字編碼所以能夠正確顯示。
在這個(gè)例子中,數(shù)據(jù)庫(kù)與客戶(hù)端都沒(méi)有設(shè)置成中文字符集,但卻能正常顯示中文,從應(yīng)用的角度看好象沒(méi)問(wèn)題。然而這里面卻存在著極大的隱患,比如在應(yīng)用length或substr等字符串函數(shù)時(shí),就可能得到意外的結(jié)果。
對(duì)于早期使用US7ASCII字符集數(shù)據(jù)庫(kù)的數(shù)據(jù)遷移到oracle8i/9i中(使用zhs16gbk),由于原始數(shù)據(jù)已經(jīng)按照US7ASCII格式存儲(chǔ),對(duì)于這種情況,可以通過(guò)使用Oracle8i的導(dǎo)出工具,設(shè)置導(dǎo)出字符集為US7ASCII,導(dǎo)出后使用UltraEdit等工具打開(kāi)dmp文件,修改第二、三字符,修改 0001 為0354,這樣就可以將US7ASCII字符集的數(shù)據(jù)正確導(dǎo)入到ZHS16GBK的數(shù)據(jù)庫(kù)中。
六.結(jié)束語(yǔ)
為了避免在數(shù)據(jù)庫(kù)遷移過(guò)程中由于字符集不同導(dǎo)致的數(shù)據(jù)損失,oracle提供了字符集掃描工具(character set scanner),通過(guò)這個(gè)工具我們可以測(cè)試在數(shù)據(jù)遷移過(guò)程中由于字符集轉(zhuǎn)換可能帶來(lái)的問(wèn)題,然后根據(jù)測(cè)試結(jié)果,確定數(shù)據(jù)遷移過(guò)程中最佳字符集解決方案。
參考文獻(xiàn)
[1]Biju Thomas , Bob Bryla 《oracle9i DBA基礎(chǔ)I 學(xué)習(xí)指南》電子工業(yè)出版社 2002