LOAD 與 IMPORT 中的 codepage 轉換

引言

在 DB2 中,LOAD 與 IMPORT 作爲重要的導入數據的工具,有着很重要的作用。理想情況下,爲了獲得最佳性能,應用程序與從該應用程序調用的語句始終應使用相同的代碼頁。在一些場景中,我們需要導入一些和數據庫本身的 codepage 不一致的數據,這個時候就需要 codepage 轉換了。DB2 產品支持代碼頁轉換,從而允許應用程序和數據庫使用不同的代碼頁。那麼什麼是 codepage ? DB2 支持那些 codepage 轉化? 如何進行 codepage 轉換呢?

Codepage 介紹

計算機處理文本時,把一門語言中每個字符都賦以特定的值,這種字符與數值的對照表就叫 codepage( 代碼頁 ) 。例如 ASCII 就是把英文字母表和一些控制字符映射到一些特定的數值上去。

DB2 支持的 codepage 列表

關於 DB2 支持的 codepage 可以在 DB2 信息中心中查看:

http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.admin.nls.doc/doc/r0004565.html

在表中,每個 codepage 都有相對應的組,地域代碼,代碼集等。如果兩個 codepage 屬於同一個組,則它們可以互相轉換,否則不可以互相轉換。值得注意的是單字節(S)組可以轉換成中性(N)組,雙字節(D)組也可以轉換爲中性(N)組。但是 N 組不一定能轉成 S 組,N 組也不一定成轉成 D 組。

製造不同 CODEPAGE 數據的方式

製造不同 codepage 數據的方法有很多種。以下列出 4 種:

1. 使用 db2 export。DB2 本身 EXPORT 支持導出各種不同 codepage 的 DEL 格式的文件,例如導出 codepage 爲 819 和 1386 的文件,如清單 1 所示。

清單 1. 導出 codepage 爲 819 和 1386 的文件
1
2
3
4
5
db2 "export to data819.del of del modified by codepage=819
select * from tab1"
 
db2 "export to data1386.del of del modified by codepage=1386
select * from tab1"

注意 export 不能直接導出 asc 格式的文件。

2. 使用 UltraEdit 來編輯,先得到各種不同 codepage 數據的十六進制代碼(可以從網上搜索或者 GVT 網站上查取),然後編輯保存就可以了。

例如: 「你」 在 GBK(1386) 中是 X ’ C4E3 ’ , 在 UTF-8(1208)中是 X ’ E4BDA0 ’

圖 1. 編輯‘你’的 GBK 代碼
圖 1. 編輯‘你’的 GBK 代碼

3. 使用 Windows 操作系統下的 Microsoft Word 來製作數據,方式如下

設置 –〉控制面板—〉區域和語言選項,設置你需要的語言,然後可以使用 WORD 來另存爲純文本,選擇其它編碼來指定其編碼。

4. 使用 vi 來設置 fileencoding 來達到目的

例如準備 codepage 爲 1208 的數據:

1
set fileencoding=utf-8
圖 2. 設定 fileencoding
圖 2. 設定 fileencoding

提示:準備數字和字母這些比較方便,但是準備中文,日文等就不是很方便了。建議使用 UltraEdit 來準備這些諸如中文,日文語言的 codepage。

LOAD 與 IMPORT 不同轉換方式

缺省情況下,LOAD 認爲輸入文件是用數據庫代碼頁編碼的,直接將文件轉化爲數據庫 codepage 編碼。如果輸入文件不是以數據庫 codepage 編碼的,可以通過 codepage 修飾符來導入正確文件。而缺省情況下 DB2 IMPORT 實用程序認爲輸入文件中的數據是用當前系統的代碼頁編碼的。當將數據文件導入到數據庫時,DB2 會自動將數據文件從當前系統代碼頁轉換成數據庫代碼頁。如果輸入文件不是當前系統的代碼頁編碼的。也可以通過 codepage 修飾符來輕鬆導入正確文件。

所以一般來說,LOAD 直接把源數據的 codepage 轉化爲數據庫的 codepage,而 IMPORT 則先將源數據的 codepage 轉換爲應用程序的 codepage,然後將應用程序的 codepage 再轉換爲數據庫的 codepage。

LOAD 實例分析

這些例子都是在 DB2 V97 中實現的,以下實例用的是同一個數據庫 db1386, 兩個數據文件 data1386.del,data1208.del。

data1386.del 和 data1208.del 包含同樣的數據第一列爲 1,第二列爲你,第三列爲繜。但是編碼方式不同。data1386.del 以 codepage 1386 編碼,而 data1208 以 codepage 1208 編碼。

Linux 上當前系統代碼頁可以通過 db2set db2codepage 來設置。另外需要 db2 terminate,使設置生效。

db codepage 是建 DB 時由 codeset,territory 決定的。例如:

1
db2 create db db1386 using codeset GBK territory CN

可以通過以下命令查看 db 的 codepage。

1
db2 get db cfg for dbname |grep 'Database code page'

數據 codepage 和 db codepage 一致時的 LOAD

缺省情況下 LOAD 認爲數據 codepage 和 db codepage 一致,在這個例子中,導入成功。

清單 2. LOAD 清單 1
1
2
3
4
5
6
7
db2 create db db1386 using codeset GBK territory CN
db2set db2codepage=1386
db2 terminate
db2 connect to db1386
db2 "create table t1(a int, b varchar(7),c varchar(10))"
db2 load from data1386.del of del replace into t1
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 3 所示。

圖 3. 查詢結果 1
圖 3. 查詢結果 1

數據 codepage 和 db codepage 不一致時的 LOAD

這個例子屬於不正確的 LOAD,沒有做 codepage 轉換,data1208.del 被當成 db codepage 編碼存進了 db。

清單 3. LOAD 清單 2
1
2
3
4
5
db2set db2codepage=1386
db2 terminate
db2 connect to db1386
db2 load from data1208.del of del replace into t1
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 4 所示。

圖 4. 查詢結果 2
圖 4. 查詢結果 2

LOAD 時數據 codepage 不會轉成應用程序的 codepage

data1208.del 不會轉成應用程序的 codepage,而是直接當成 db codepage 編碼存進 db。

清單 4. LOAD 清單 3
1
2
3
4
5
db2set db2codepage=1208
db2 terminate
db2 connect to db1386
db2 load from data1208.del of del replace into t1 
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 5 所示。

圖 5. 查詢結果 3
圖 5. 查詢結果 3

數據 codepage 和 db codepage 不一致時正確的 LOAD

在這種情況下正確的 load,數據的 codepage 和 modified by codepage 一致,如清單 5 所示。

清單 5. LOAD 清單 4
1
2
3
4
5
6
7
db2set db2codepage=1208
db2 terminate
db2 connect to db1386
db2 load from data1208.del of del modified by codepage=1208
replace into t1
 
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 6 所示。

圖 6. 查詢結果 4
圖 6. 查詢結果 4

LMPORT 實例分析

以下例子所用數據同上面 load 實例數據。

數據 codepage 和應用程序 codepage, db codepage 一致時的 IMPORT

缺省情況下認爲應用程序 codepage 就是數據的 codepage。

清單 6. IMPORT 清單 1
1
2
3
4
5
db2set db2codepage=1386
db2 terminate
db2 connect to db1386
db2 import from data1386.del of del replace into t1
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 7 所示。

圖 7. 查詢結果 5
圖 7. 查詢結果 5

數據 codepage 和應用程序 codepage 一致 , 但和 db codepage 不一致時的 IMPORT

缺省情況下認爲應用程序 codepage 就是數據的 codepage,可以正確的導入。

清單 7. IMPORT 清單 2
1
2
3
4
5
db2set db2codepage=1208
db2 terminate
db2 connect to db1386
db2 import from data1208.del of del replace into t1
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 8 所示。

圖 8. 查詢結果 6
圖 8. 查詢結果 6

數據 codepage 和應用程序 codepage 不一致時利用 modified by codepage 成功實現 import 的 codepage 轉換

清單 8. IMPORT 清單 3
1
2
3
4
5
6
7
db2set db2codepage=1386
db2 terminate
db2 connect to db1386
db2 import from data1208.del of del modified by codepage=1208
replace into t1
 
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 9 所示。

圖 9. 查詢結果 7
圖 9. 查詢結果 7

數據 codepage 和應用程序 codepage 不一致時不正確的 import,沒有實現 codepage 轉換

把 data1208.del 當成應用程序 codepage 1386 編碼的,數據庫 codepage 也是 1386,不進行 codepage 轉換。

清單 9. IMPORT 清單 4
1
2
3
4
5
db2set db2codepage=1386
db2 terminate
db2 connect to db1386
db2 import from data1208.del of del replace into t1
db2 "select hex(b) as b ,hex(c) as c from t1"

結果如圖 10 所示。

圖 10. 查詢結果 8    
圖 10. 查詢結果 8    

結束語

本文介紹了 LOAD,IMPORT 在不同情況下的 codepage 轉換,以便使用戶更好的理解 codepage 轉換。