數(shù)據(jù)庫不同字符集遷移
?
一.引言
ORACLE
數(shù)據(jù)庫字符集,即Oracle全球化支持(Globalization Support),或即國家語言支持(NLS)其作用是用本國語言和格式來存儲、處理和檢索數(shù)據(jù)。利用全球化支持,ORACLE為用戶提供自己熟悉的數(shù)據(jù)庫母語環(huán)境,諸如日期格式、數(shù)字格式和存儲序列等。Oracle可以支持多種語言及字符集,其中oracle8i支持48種語言、76個國家地域、229種字符集,而oracle9i則支持57種語言、88個國家地域、235種字符集。由于oracle字符集種類多,且在存儲、檢索、遷移oracle數(shù)據(jù)時多個環(huán)節(jié)與字符集的設置密切相關(guān),因此在實際的應用中,數(shù)據(jù)庫開發(fā)和管理人員經(jīng)常會遇到有關(guān)oracle字符集方面的問題。本文通過以下幾個方面闡述,對oracle字符集做簡要分析
二.字符集基本知識
2.1
字符集實質(zhì)就是按照一定的字符編碼方案,對一組特定的符號,分別賦予不同數(shù)值編碼的集合。Oracle數(shù)據(jù)庫最早支持的編碼方案是US7ASCII。
Oracle
的字符集命名遵循以下命名規(guī)則:
即:? <語言><比特位數(shù)><編碼>
比如: ZHS16GBK表示采用GBK編碼格式、16位(兩個字節(jié))簡體中文字符集
2.2
字符編碼方案
2.2.1
單字節(jié)編碼(1)單字節(jié)7位字符集,可以定義128個字符,最常用的字符集為US7ASCII
(2)單字節(jié)8位字符集,可以定義256個字符,適合于歐洲大部分國家例如:WE8ISO8859P1(西歐、8位、ISO標準8859P1編碼)
2.2.2
多字節(jié)編碼(1)變長多字節(jié)編碼某些字符用一個字節(jié)表示,其它字符用兩個或多個字符表示,變長多字節(jié)編碼常用于對亞洲語言的支持,?? 例如日語、漢語、印地語等例如:AL32UTF8(其中AL代表ALL,指適用于所有語言)、zhs16cgb231280
(2)定長多字節(jié)編碼每一個字符都使用固定長度字節(jié)的編碼方案,目前oracle唯一支持的定長多字節(jié)編碼是AF16UTF16,也是僅用于國家字符集
2.2.3 unicode
編碼
Unicode
是一個涵蓋了目前全世界使用的所有已知字符的單一編碼方案,也就是說Unicode為每一個字符提供唯一的編碼。UTF-16是unicode的16位編碼方式,是一種定長多字節(jié)編碼,用2個字節(jié)表示一個unicode字符,AF16UTF16是UTF-16編碼字符集。
UTF-8
是unicode的8位編碼方式,是一種變長多字節(jié)編碼,這種編碼可以用1、2、3個字節(jié)表示一個unicode字符,AL32UTF8,UTF8、UTFE是UTF-8編碼字符集
2.4
數(shù)據(jù)庫字符集(oracle服務器端字符集)數(shù)據(jù)庫字符集在創(chuàng)建數(shù)據(jù)庫時指定,在創(chuàng)建后通常不能更改。在創(chuàng)建數(shù)據(jù)庫時,可以指定字符集(CHARACTER SET)和國家字符集(NATIONAL CHARACTER
SET)。
2.5
客戶端字符集(NLS_LANG參數(shù))
2.5.1
客戶端字符集含義客戶端字符集定義了客戶端字符數(shù)據(jù)的編碼方式,任何發(fā)自或發(fā)往客戶端的字符數(shù)據(jù)均使用客戶端定義的字符集編碼,客戶端可以看作是能與數(shù)據(jù)庫直接連接的各種應用,例如sqlplus,exp/imp等??蛻舳俗址峭ㄟ^設置NLS_LANG參數(shù)來設定的。
2.5.2 NLS_LANG
參數(shù)格式
NLS_LANG=_.
Language:
顯示oracle消息,校驗,日期命名
Territory
:指定默認日期、數(shù)字、貨幣等格式
Client character set
:指定客戶端將使用的字符集例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN
是語言,AMERICA是地區(qū),US7ASCII是客戶端字符集
三.導入/導出與字符集轉(zhuǎn)換
3.1 EXP/IMP
Export
和 Import 是一對讀寫Oracle數(shù)據(jù)的工具。Export 將Oracle 數(shù)據(jù)庫中的數(shù)據(jù)輸出到操作系統(tǒng)文件中, Import 把這些文件中的數(shù)據(jù)讀到Oracle 數(shù)據(jù)庫中,由于使用exp/imp進行數(shù)據(jù)遷移時,數(shù)據(jù)從源數(shù)據(jù)庫到目標數(shù)據(jù)庫的過程中有四個環(huán)節(jié)涉及到字符集,如果這四個環(huán)節(jié)的字符集不一致,將會發(fā)生字符集轉(zhuǎn)換。
四個字符集是(1)源數(shù)據(jù)庫字符集(2)Export過程中用戶會話字符集(通過NLS_LANG設定)(3)Import過程中用戶會話字符集(通過NLS_LANG設定)(4)目標數(shù)據(jù)庫字符集
3.2
導出的轉(zhuǎn)換過程在Export過程中,如果源數(shù)據(jù)庫字符集與Export用戶會話字符集不一致,會發(fā)生字符集轉(zhuǎn)換,并在導出文件的頭部幾個字節(jié)中存儲Export用戶會話字符集的ID號。在這個轉(zhuǎn)換過程中可能發(fā)生數(shù)據(jù)的丟失。例:如果源數(shù)據(jù)庫使用ZHS16GBK,而Export用戶會話字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,這個轉(zhuǎn)換過程中,中文字符在US7ASCII中不能夠找到對等的字符,所以所有中文字符都會丟失而變成“?? ”形式,這樣轉(zhuǎn)換后生成的Dmp文件已經(jīng)發(fā)生了數(shù)據(jù)丟失。因此如果想正確導出源數(shù)據(jù)庫數(shù)據(jù),則Export過程中用戶會話字符集應等于源數(shù)據(jù)庫字符集或是源數(shù)據(jù)庫字符集的超集
3.3
導入的轉(zhuǎn)換過程(1)確定導出數(shù)據(jù)庫字符集環(huán)境通過讀取導出文件頭,可以獲得導出文件的字符集設置(2)確定導入session的字符集,即導入Session使用的NLS_LANG環(huán)境變量(3)IMP讀取導出文件讀取導出文件字符集ID,和導入進程的NLS_LANG進行比較(4)如果導出文件字符集和導入Session字符集相同,那么在這一步驟內(nèi)就不需要轉(zhuǎn)換,如果不同,就需要把數(shù)據(jù)轉(zhuǎn)換為導入Session使用的字符集??梢钥闯?,導入數(shù)據(jù)到數(shù)據(jù)庫過程中發(fā)生兩次字符集轉(zhuǎn)換第一次:導入文件字符集與導入Session使用的字符集之間的轉(zhuǎn)換,如果這個轉(zhuǎn)換過程不能正確完成,Import向目標數(shù)據(jù)庫的導入過程也就不能完成。第二次:導入Session字符集與數(shù)據(jù)庫字符集之間的轉(zhuǎn)換。然而,oracle8i的這種轉(zhuǎn)換只能在單字節(jié)字符集之間進行,oracle8i導入Session不支持多字節(jié)字符集之間的轉(zhuǎn)換,因此為了避免第一次轉(zhuǎn)換,導入Session使用的NLS_LANG與導出文件字符集相同,第二次轉(zhuǎn)換(通過SQL*Net)支持任何兩種字符集。以上情況在Oracle9i中略有不同
Server
1
SQL> SELECT * FROMNls_database_parameters WHERE Parameter in ('NLS_CHARACTERSET
PARAMETER
------------------------------
VALUE
--------------------------------------------------------------------------------
NLS_CHARACTERSET
ZHS16GBK
NLS_NCHAR_CHARACTERSET
AL16UTF16
Server
2
SQL> SELECT * FROMNls_database_parameters WHERE Parameter in ('NLS_CHARACTERSET
','NLS_NCHAR_CHARACTERSET');
PARAMETER
------------------------------
VALUE
--------------------------------------------------------------------------------
NLS_CHARACTERSET
AL32UTF8
NLS_NCHAR_CHARACTERSET
AL16UTF16
Server
1,2
SQL> create user wzx_test identified byoracle;
用戶已創(chuàng)建。
SQL> grant dba to wzx_test;
授權(quán)成功。
Server
1
Connect wzx_test/oracle
Create table t(id int,name varchar2(20));
Insert into t values(1,'振興中華振興中華振興') ;
Insert into t values(1,'振興中華') ;
C:\Users\Administrator>setNLS_LANG=american_america.AL32UTF8
C:\Users\Administrator>expdp
wzx_test/oracle schemas=wzx_test directory=DATA_PUMP_DIR dumpfile=wzx_20170912
logfile=wzx_expdp_20170912
Export:
Release 11.2.0.3.0 - Production on Tue Sep 12 13:30:35 2017
Copyright(c) 1982, 2011, Oracle and/or its affiliates.?All rights reserved.
Connected
to: Oracle Database 11g Release 11.2.0.3.0 - 64bit Production
FLASHBACK
automatically enabled to preserve database integrity.
Starting"WZX_TEST"."SYS_EXPORT_SCHEMA_01":? wzx_test/******** schemas=wzx_test directory=
12
Estimate
in progress using BLOCKS method...
Processing
object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total
estimation using BLOCKS method: 64 KB
Processing
object type SCHEMA_EXPORT/USER
Processing
object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing
object type SCHEMA_EXPORT/ROLE_GRANT
Processing
object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing
object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing
object type SCHEMA_EXPORT/TABLE/TABLE
Processing
object type SCHEMA_EXPORT/TABLE/COMMENT
Processing
object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing
object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing
object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
. .exported "WZX_TEST"."T"????????????????????????????? 5.453 KB?????? 2 rows
Master
table "WZX_TEST"."SYS_EXPORT_SCHEMA_01" successfully
loaded/unloaded
******************************************************************************
Dump
file set for WZX_TEST.SYS_EXPORT_SCHEMA_01 is:
?D:\APP\ADMINISTRATOR\ADMIN\SFISMAO\DPDUMP\WZX_20170912.DMP
Job
"WZX_TEST"."SYS_EXPORT_SCHEMA_01" successfully completed at
13:30:49
Server
2
C:\Users\Administrator>setNLS_LANG=american_america.AL32UTF8
C:\Users\Administrator>impdpwzx_test/oracle schemas=wzx_test directory=DATA_PUM
P_DIR dumpfile=wzx_20170912logfile=wzx_impdp_20170912
Import:
Release 11.2.0.4.0 - Production on Tue Sep 12 13:34:30 2017
Copyright(c) 1982, 2011, Oracle and/or its affiliates.?All rights reserved.
Connected
to: Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
Master
table "WZX_TEST"."SYS_IMPORT_SCHEMA_01" successfully
loaded/unloaded
Starting"WZX_TEST"."SYS_IMPORT_SCHEMA_01":? wzx_test/******** schemas=wzx_test
directory=DATA_PUMP_DIR
dumpfile=wzx_20170912 logfile=wzx_impdp_20170912
Processing
object type SCHEMA_EXPORT/USER
ORA-31684:
Object type USER:"WZX_TEST" already exists
Processing
object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing
object type SCHEMA_EXPORT/ROLE_GRANT
Processing
object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing
object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing
object type SCHEMA_EXPORT/TABLE/TABLE
Processing
object type SCHEMA_EXPORT/TABLE/TABLE_DATA
ORA-02374: conversion errorloading table "WZX_TEST"."T"
ORA-12899: value too large forcolumn NAME (actual: 30, maximum: 20)
ORA-02372: data for row: NAME :0X'D5F1D0CBD6D0BBAAD5F1D0CBD6D0BBAAD5F1D0CB'
. .imported "WZX_TEST"."T"????????????????????????????? 5.453 KB?????? 1 out of
?2 rows
Job
"WZX_TEST"."SYS_IMPORT_SCHEMA_01" completed with 1 error(s)
at Tue Sep 12 13
:34:33
2017 elapsed 0 00:00:02
Server
1
C:\Users\Administrator>sqlpluswzx_test/oracle@172.20.1.170:1521/wzxtest
SQL*Plus:
Release 11.2.0.3.0 Production on Tue Sep 12 13:41:34 2017
Copyright(c) 1982, 2011, Oracle.? All rights reserved.
Connected
to:
Oracle
Database 11g Release 11.2.0.4.0 - 64bit Production
SQL>
select * from t;
??????? ID NAME
----------
----------------------------------------
???????? 1振興中華
為了避免在數(shù)據(jù)庫遷移過程中由于字符集不同導致的數(shù)據(jù)損失,oracle提供了字符集掃描工具(character set scanner),通過這個工具我們可以測試在數(shù)據(jù)遷移過程中由于字符集轉(zhuǎn)換可能帶來的問題,然后根據(jù)測試結(jié)果,確定數(shù)據(jù)遷移過程中最佳字符集解決方案。