2005 年 6 月 27 日
學(xué)習(xí) DB2 Universal Database(DB2 UDB)如何處理字符轉(zhuǎn)換。本文首先將討論字符代碼的基本概念,包括代碼頁、代碼點(diǎn)和編碼模式,接著將更為詳細(xì)地解釋如何設(shè)置代碼頁以及如何發(fā)生字符轉(zhuǎn)換。為了易于理解,本文還展示了一些通用的場景和示例。
在當(dāng)今世界中,許多數(shù)據(jù)庫應(yīng)用程序都在多個(gè)平臺上使用多個(gè)數(shù)據(jù)庫組件。數(shù)據(jù)庫應(yīng)用程序可以在 Windows 系統(tǒng)上運(yùn)行,但卻通過 AIX 上所運(yùn)行的 DB2 Connect 服務(wù)器與 DB2 UDB for z/OS 數(shù)據(jù)庫進(jìn)行交互。在這些不同服務(wù)器之間流動的信息可能經(jīng)歷多次字符轉(zhuǎn)換,而且大多數(shù)情況下,這些轉(zhuǎn)換對用戶是透明的。
然而,偶爾也需要進(jìn)行一些配置。在這些情況中,理解這些轉(zhuǎn)換如何工作以及哪個(gè)組件處理它們就十分有用。例如,請考慮以下情況:
“我在 SPUFI 中 DB2 UDB for OS/390 表的一列里存儲了感嘆號(?。?。當(dāng)我從 DB2 UDB for Linux,UNIX and Windows 命令行處理器(CLP)檢索同一列時(shí),感嘆號就轉(zhuǎn)換成為一個(gè)方括號(])。”
“我的 DB2 UDB for Linux,UNIX and Windows 數(shù)據(jù)庫中有西班牙語(Spanish)信息。Java 應(yīng)用程序檢索這些西班牙語數(shù)據(jù)(重音符號),但它們都遭到了損壞,即使我可以用 CLP 看到正確內(nèi)容?!?div style="height:15px;">
這些例子都是來自于 DB2 UDB 客戶的疑問和問題。本文通過描述 DB2 UDB 字符轉(zhuǎn)換過程,解決了所有這些以及類似的問題。
本文重點(diǎn)關(guān)注下列產(chǎn)品和版本:DB2 UDB for Linux, UNIX, and Windows version 8.2、DB2 UDB for iSeries 5.3 和 DB2 UDB for z/OS version 8。本文可能也適用于這些產(chǎn)品的早期版本。
為了理解字符轉(zhuǎn)換過程如何工作,您需要理解一些關(guān)鍵概念。圖 1、2 和 3 提供了其中一些概念的概述。
在這些圖中,每個(gè)頁碼中的實(shí)線陰影邊框表示的是十六進(jìn)制數(shù)。
代碼頁(code page)可以定義為字母數(shù)字代碼及其二進(jìn)制表示的映射表。
圖 1 展示了幾個(gè)用于不同語言和平臺的代碼頁。在本圖中,對于代碼頁 1252,字母“K”可以用二進(jìn)制數(shù)“01001011”(或十六進(jìn)制表示法:“4B”)表示。而在另一代碼頁中,則可能用不同的二進(jìn)制表示來表示這同一字符。
代碼點(diǎn)(code point)是字符在代碼頁中的位置。在
圖 1 中,代碼頁 1252 中的代碼點(diǎn)“4B”對應(yīng)字符“K”。
字符集(character set)是一個(gè)定義的字符集。例如,一個(gè)字符集可以由大寫字母 A 到 Z、小寫字母 a 到 z 以及數(shù)字 0 到 9 組成。該字符集可以在多個(gè)代碼頁中重復(fù)。例如,在
圖 1 和
圖 2 中,不同代碼頁中帶點(diǎn)背景的單元格都表示同一字符集。
代碼頁可以分成下列幾類:
單字節(jié)代碼頁(有時(shí)稱作單字節(jié)字符集或 SBCS)是一個(gè)最多可以容納 256 (28) 個(gè)代碼點(diǎn)的代碼頁。SBCS 中代碼點(diǎn)的實(shí)際數(shù)目可能要少一些。例如,對于地域標(biāo)識符 US 和代碼集 ISO 8859-1,AIX 上的地區(qū) en_US 就是 SBCS 代碼頁 819。
雙字節(jié)代碼頁(有時(shí)稱作雙字節(jié)字符集或 DBCS)是一個(gè)最多可以容納 65536 (216) 個(gè)代碼點(diǎn)的代碼頁。DBCS 中代碼點(diǎn)的實(shí)際數(shù)目可能要少一些。例如,對于地域標(biāo)識符 JP 和代碼集 IBM-932,AIX 上的地區(qū) Ja_JP 就是 DBCS 代碼頁 932。
復(fù)合或混合代碼頁包含不止一個(gè)代碼頁。例如,Extended UNIX Code(EUC)代碼頁可以包含多達(dá)四個(gè)不同的代碼頁,其中第一個(gè)代碼頁總是單字節(jié)的。例如,用于日語的 IBM-eucJP(代碼頁 954)根據(jù) EUC 編碼規(guī)則引用日本工業(yè)標(biāo)準(zhǔn)(Japanese Industrial Standard)字符的編碼。
在大型機(jī)(z/OS, OS/390)和 iSeries(i5/OS、OS/400)領(lǐng)域中,使用術(shù)語編碼字符集標(biāo)識符(Coded Character Set Identifier,CCSID)來代替代碼頁。CCSID 是一個(gè) 16 位的無符號整數(shù),惟一地標(biāo)識一個(gè)特定的代碼頁。例如,在大型機(jī)上,US-English 代碼頁由 CCSID 37 表示。German 代碼頁是 CCSID 273。其中一些代碼頁包含了其語言中特定字符的代碼點(diǎn);一些代碼頁具有相同的字符,但由不同 CCSID 中的不同代碼點(diǎn)來表示。CCSID 是基于字符數(shù)據(jù)表示架構(gòu)(Character Data Representation Architecture,CDRA)的,這是一個(gè) IBM 架構(gòu),其中定義了一組標(biāo)識符、資源、服務(wù)和約定以在異構(gòu)環(huán)境中取得圖形字符數(shù)據(jù)的一致表示、處理和交換。OS/400 完全支持 CDRA。OS/390 支持 CDRA 的部分元素。
編碼模式(encoding scheme)是為在特定計(jì)算平臺上所使用的不同語言提供的代碼頁集合。常見的編碼模式有:
American Standard Code for Information Interchange(ASCII),用于基于 Intel 的平臺(如 Windows)和基于 UNIX 的平臺,如 AIX。
圖 1 展示了 ASCII 編碼模式的簡化表示。
Extended Binary Coded Decimal Information Code(EBCDIC),這是由 IBM 設(shè)計(jì)的編碼模式。它通常用于 z/OS 和 iSeries 上。
圖 2 展示了 EBCDIC 編碼模式的簡化表示。
Unicode 字符編碼標(biāo)準(zhǔn)是固定長度的字符,它為世界上的每一個(gè)字符都提供了一個(gè)惟一的代碼點(diǎn),無論平臺、程序或語言如何。它包含近 100,000 個(gè)字符,并且還在增加。Unicode 標(biāo)準(zhǔn)已經(jīng)為很多行業(yè)巨頭所采用,如 IBM、Microsoft 以及其他許多公司。諸如 XML、Java、LDAP、CORBA 3.0 等現(xiàn)代標(biāo)準(zhǔn)都要求使用 Unicode,它還是實(shí)現(xiàn) ISO/IEC 10646 的官方方式。
圖 3 展示了 Unicode 編碼模式的簡化表示。
通過前面的討論,應(yīng)該已經(jīng)清楚“代碼頁”的概念對于理解字符轉(zhuǎn)換至關(guān)重要。可以在不同級別上定義代碼頁:
在應(yīng)用程序所運(yùn)行的操作系統(tǒng)上
在應(yīng)用程序級別上,根據(jù)編程語言使用特定語句
在數(shù)據(jù)庫所運(yùn)行的操作系統(tǒng)上
在數(shù)據(jù)庫級別上
在 Windows 上,代碼頁派生于 Windows 注冊表中的 ANSI 代碼頁設(shè)置。您可以從 Regional Settings 控制面板查看您的設(shè)置。
圖 4 展示了一臺 Windows XP 機(jī)器上的區(qū)域設(shè)置。
在基于 UNIX 的環(huán)境中,代碼頁派生于地區(qū)(locale)設(shè)置。命令 locale 可以用于確定該值,如
圖 5 中所示。命令 localedef 可以編譯新的 locale 文件,而 /etc/environment 中的 LANG 變量可以用新的 locale 進(jìn)行更新。
對于 iSeries 和 z/OS,請與您的系統(tǒng)管理員聯(lián)系。
本文沒有詳細(xì)討論應(yīng)用程序代碼頁的設(shè)置,因?yàn)橹攸c(diǎn)主要是在數(shù)據(jù)庫方面。然而,本文提到了一些可能十分有用的概念。
默認(rèn)情況下,應(yīng)用程序代碼頁派生于它所運(yùn)行的操作系統(tǒng)。對于嵌入式 SQL 程序而言,應(yīng)用程序代碼頁在預(yù)編譯/綁定時(shí)以及執(zhí)行時(shí)確定。在預(yù)編譯和綁定時(shí),代碼頁派生于用于預(yù)編譯語句和 SQLCA 中返回的所有字符數(shù)據(jù)的數(shù)據(jù)庫連接。在執(zhí)行時(shí),當(dāng)建立數(shù)據(jù)庫連接時(shí),確定用戶應(yīng)用程序代碼頁,而且它只在連接期間有效。所有數(shù)據(jù),包括動態(tài) SQL 語句、用戶輸入數(shù)據(jù)、用戶輸出數(shù)據(jù)以及 SQLCA 中的字符字段,都是基于該代碼頁進(jìn)行解釋的。因此,如果程序包含常量字符串,您就應(yīng)該使用相同的代碼頁預(yù)編譯、綁定、編譯和執(zhí)行該應(yīng)用程序。
對于 Unicode 數(shù)據(jù)庫,您應(yīng)使用主機(jī)變量來代替字符串常量。該建議的理由就是服務(wù)器可能在綁定和執(zhí)行階段都進(jìn)行數(shù)據(jù)轉(zhuǎn)換;如果程序中使用了常量字符串,這可能是一個(gè)憂慮。在綁定時(shí),將基于在綁定期間有效的代碼頁轉(zhuǎn)換這些嵌入的字符串。7 位 ASCII 字符通用于 DB2 Universal Databas 所支持的所有代碼頁,并且不會產(chǎn)生問題。對于非 ASCII 字符,用戶應(yīng)該確保具有相同活動代碼頁的綁定和執(zhí)行使用相同的轉(zhuǎn)換表。
對于 ODBC 或 CLI 應(yīng)用程序,您或許可以在 odbc.ini 文件或 db2cli.ini 文件中使用不同的關(guān)鍵字來調(diào)整應(yīng)用程序代碼頁。例如,Windows ODBC 應(yīng)用程序可以使用關(guān)鍵字 TRANSLATEDLL 來表示 DB2TRANS.DLL 的位置,該文件包含代碼頁映射表,以及使用關(guān)鍵字 TRANSLATEOPTION 來定義數(shù)據(jù)庫的代碼頁數(shù)目。DISABLEUNICODE 關(guān)鍵字可以用于顯式地啟用或禁用 Unicode。默認(rèn)情況下,沒有設(shè)置該關(guān)鍵字,這意味著如果目標(biāo)數(shù)據(jù)庫支持 Unicode,DB2 CLI 應(yīng)用程序就將使用 Unicode 進(jìn)行連接。否則,DB2 CLI 應(yīng)用程序?qū)⑹褂脩?yīng)用程序代碼頁進(jìn)行連接。當(dāng)您顯式地設(shè)置 DISABLEUNICODE=0 時(shí),DB2 CLI 應(yīng)用程序?qū)⒖偸怯?Unicode 進(jìn)行連接,無論目標(biāo)數(shù)據(jù)庫是否支持 Unicode。當(dāng) DISABLEUNICODE=1 時(shí),DB2 CLI 應(yīng)用程序則總是用應(yīng)用程序代碼頁進(jìn)行連接,無論目標(biāo)數(shù)據(jù)庫是否支持 Unicode。
使用 Java Universal Type 4 驅(qū)動程序的 Java 應(yīng)用程序不需要在客戶端機(jī)器上安裝 DB2 UDB 客戶機(jī)。通用 JDBC 驅(qū)動程序客戶端將數(shù)據(jù)作為 Unicode 發(fā)送給數(shù)據(jù)庫服務(wù)器,而數(shù)據(jù)庫服務(wù)器則將數(shù)據(jù)從 Unicode 轉(zhuǎn)換成所支持的代碼頁。從數(shù)據(jù)庫服務(wù)器發(fā)送給客戶端的字符數(shù)據(jù)是使用諸如 sun.io.* 轉(zhuǎn)換例程的 Java 的內(nèi)置字符轉(zhuǎn)換器(converter)進(jìn)行轉(zhuǎn)換的。DB2 Universal JDBC Driver 支持的轉(zhuǎn)換限于底層 Java Runtime Environment(JRE)實(shí)現(xiàn)所支持的那些。對于 CLI 和遺留(legacy)JDBC 驅(qū)動程序,要使用代碼頁轉(zhuǎn)換表。
z/OS 上運(yùn)行的應(yīng)用程序使用 DB2 UDB for z/OS 安裝面板上指定的應(yīng)用程序編碼 CCSID 值。此外,應(yīng)用程序編碼綁定(bind)選項(xiàng)也可以為程序中的主機(jī)變量定義 CCSID。對于動態(tài) SQL 應(yīng)用程序而言,就要使用 APPLICATION ENCODING 專用寄存器來覆蓋 CCSID。還可以通過在 DECLARE VARIABLE 語句中使用 CCSID 子句,在更細(xì)粒度的級別上指定 CCSID。(例如:EXEC SQL DECLARE :TEST VARIABLE CCSID UNICODE;)
本小節(jié)的討論與
上面的闡述完全相同。
根據(jù) DB2 UDB 平臺,按不同方式定義代碼頁。
數(shù)據(jù)庫可以只有一個(gè)代碼頁,它是在您通過 CREATE DATABASE 命令首次創(chuàng)建數(shù)據(jù)庫時(shí)使用 CODESET 和 TERRORITY 子句設(shè)置的。例如,下列命令創(chuàng)建了數(shù)據(jù)庫“spaindb”,使用代碼集 1252 和地域 ID 34,這確定了 Windows 平臺上用于西班牙語的代碼頁。(關(guān)于不同國家的代碼集和地域 ID 列表,請查閱
支持的地域代碼和代碼頁。)
CREATE DATABASE spaindb USING CODESET 1252 TERRITORY es
創(chuàng)建數(shù)據(jù)庫之后,您就可以通過發(fā)出圖 6 中所示的命令 get db cfg for spaindb 查看該代碼頁的設(shè)置。
表 1 提供了圖 6 中每個(gè)字段的描述。
字段名稱描述
Database territory確定一個(gè)國家的地域標(biāo)識符。
Database code page指定用于創(chuàng)建該數(shù)據(jù)庫的代碼頁。
Database country/region code指定用于創(chuàng)建該數(shù)據(jù)庫的地域代碼。
Database collating sequence指定用于進(jìn)行字符數(shù)據(jù)排序的方法。
Alternate collating sequence指定在非 Unicode 數(shù)據(jù)庫中用于 Unicode 表的排序序列。在設(shè)置該參數(shù)以前,都無法在非 Unicode 數(shù)據(jù)庫中創(chuàng)建 Unicode 表和例程。
排序序列將在小節(jié)
其他注意事項(xiàng)中進(jìn)行更詳細(xì)的討論。如果您使用默認(rèn)值創(chuàng)建數(shù)據(jù)庫,那么所使用的代碼頁就來自于操作系統(tǒng)的信息。一旦用給定的代碼頁創(chuàng)建了數(shù)據(jù)庫,您就無法修改它,除非導(dǎo)出數(shù)據(jù)、刪除數(shù)據(jù)庫后,再用正確的代碼頁重新創(chuàng)建該數(shù)據(jù)庫并導(dǎo)入數(shù)據(jù)。
在 DB2 UDB for iSeries 上,數(shù)據(jù)庫中的每個(gè)物理文件或表都可以指定一個(gè)代碼頁。因此,一個(gè) iSeries 數(shù)據(jù)庫可以容納多個(gè)代碼頁,甚至是 ASCII 代碼頁,這取決于指定的代碼頁。
為了指定用于物理文件或表的代碼頁,要使用下面兩種方法之一:
創(chuàng)建一個(gè)物理文件,并使用 CCSID 子句。例如,下列命令使用 Data Description Source(DDS)通過 CCSID 62251 創(chuàng)建一個(gè)單成員(one-member)文件,并將其置于名為 DSTPRODLB 的庫中。
CRTPF FILE(DSTPRODLB/ORDHDRP) TEXT(‘Order header physical file‘) CCSID(62251)
這假定 DDS 源存在,并已經(jīng)正確定義。請注意,CCSID 值僅僅對于源物理文件 FILETYPE(*SRC) 有效。iSeries 表存儲在數(shù)據(jù)物理文件 FILETYPE(*DATA) 中,因此,您必須按那樣使用 DDS,并指定 CCSID。
使用帶有 CCSID 子句的 CREATE TABLE SQL 語句。例如,下列 SQL 語句創(chuàng)建了表 DEPARTMENT(并對兩列指定了 CCSID 37):
CREATE TABLE DEPARTMENT (DEPTNO CHAR(3) CCSID 37 NOT NULL, DEPTNAME VARCHAR(36) CCSID 37 NOT NULL, PRENDATE DATE DEFAULT NULL)
為了在作業(yè)級查看代碼頁的當(dāng)前值,您可以從 OS/400 命令行鍵入下列命令:DSPJOB OPTION(*DFNA)。
如果您向下滾動到第三頁,就可以看到代碼頁設(shè)置,例如:
Language identifier . . . . . . . . . . . . . . . : ENU
Country or region identifier . . . . . . . . . . : CA
Coded character set identifier . . . . . . . . . : 37
Default coded character set identifier . . . . . : 37
如果未指定 CCSID,所使用的代碼頁就是下列三層之一所指定的:
分布式數(shù)據(jù)庫管理(Distributed Data Management,DDM)
作業(yè)(即在 OS 級)
用戶配置文件(即在系統(tǒng)級)
客戶機(jī)將在 DDM 請求(DDM 層)中發(fā)送其代碼頁。在 OS400 級上,CCSID 是按下列優(yōu)先級確定的:
使用字段定義中的 CCSID。
如果字段定義中沒有 CCISD,就使用文件級的 CCSID。
如果未指定文件級的 CCSID,就使用當(dāng)前作業(yè)的 CCSID。
作業(yè)的 CCSID 是按下列方式確定的:
檢查用戶配置文件,并從中獲得 CCSID。
如果用戶配置文件未指定 CCSID,就通過系統(tǒng)值 QCCSID 確定該值。
在 DB2 UDB for z/OS 上,CCSID(代碼頁)需要當(dāng)安裝 DB2 UDB for z/OS 子系統(tǒng)時(shí)在面板 DSNTIPF 上指定。如
圖 7 中所示。
DSNTIPF INSTALL DB2 - APPLICATION PROGRAMMING DEFAULTS PANEL 1 ===> _ Enter data below: 1 LANGUAGE DEFAULT ===> IBMCOB ASM,C,CPP,IBMCOB,FORTRAN,PLI 2 DECIMAL POINT IS ===> . . or , 3 STRING DELIMITER ===> DEFAULT DEFAULT, " or ‘ (COBOL or COB2 only) 4 SQL STRING DELIMITER ===> DEFAULT DEFAULT, " or ‘ 5 DIST SQL STR DELIMTR ===> ‘ ‘ or " 6 MIXED DATA ===> NO NO or YES for mixed DBCS data 7 EBCDIC CCSID ===> CCSID of SBCS or mixed data. 1-65533. 8 ASCII CCSID ===> CCSID of SBCS or mixed data. 1-65533. 9 UNICODE CCSID ===> 1208 CCSID of UNICODE UTF-8 data. 10 DEF ENCODING SCHEME ===> EBCDIC EBCDIC, ASCII, or UNICODE 11 APPLICATION ENCODING ===> EBCDIC EBCDIC, ASCII, UNICODE, cssid (1-65533) 12 LOCALE LC_CTYPE ===> PRESS: ENTER to continue RETURN to exit HELP for more information
表 2 提供了圖 7 中每個(gè)相關(guān)字段的描述。
字段名稱描述
MIXED DATA指定 EBCDIC CCSID 和 ASCII CCSID 字段是否包含混合型數(shù)據(jù)。
EBCDIC CCSID指定 EBCDIC 編碼數(shù)據(jù)的默認(rèn) CCSID。
ASCII CCSID指定 ASCII 編碼字符數(shù)據(jù)的默認(rèn) CCSID。
UNICODE CCSID指定 Unicode 的默認(rèn) CCSID。DB2 UDB for z/OS 當(dāng)前僅僅支持 CCSID 1208 用于 Unicode。
DEF ENCODING SCHEME指定在 DB2 中存儲數(shù)據(jù)的默認(rèn)格式。
APPLICATION ENCODING指定影響 DB2 UDB for z/OS 如何解釋進(jìn)入 DB2 的數(shù)據(jù)的系統(tǒng)默認(rèn)應(yīng)用程序編碼模式。
LOCALE LC_CTYPE指定系統(tǒng) LOCALE_LC_CTYPE。地區(qū)(locale)是系統(tǒng)環(huán)境中的一部分,取決于語言和文化習(xí)俗。LC_TYPE 是應(yīng)用于字符函數(shù)的地區(qū)(locale)子集。例如,在美國指定 En_US 用于英語,或在加拿大指定 Fr_CA 用于法語。
如果語言僅僅使用單字節(jié)的 CCSID,那么 CCSID 中的混合型和雙字節(jié) CCSID 就默認(rèn)設(shè)置為預(yù)留的 CCSID 65534。由于諸如中文和日語等一些語言字符的復(fù)雜性和繁多,這些字符集就使用雙字節(jié)和混合型字符集。所有單字節(jié)和混合型 CCSID 都存儲在 DB2 UDB for z/OS 子系統(tǒng)參數(shù)作業(yè)中稱作 DSNHDECP 的宏中。此外,DB2 UDB for z/OS 目錄表 SYSIBM.SYSSTRINGS 必須為所有必要的代碼頁轉(zhuǎn)換指出轉(zhuǎn)換表。
DB2 UDB for z/OS 使用 ASCII CCSID 值來執(zhí)行從 ASCII 外部源(包括其他數(shù)據(jù)庫)收到的字符數(shù)據(jù)的轉(zhuǎn)換。您必須為 ASCII CCSID 字段指定一個(gè)值,即使您不必或不打算創(chuàng)建 ASCII 編碼的對象。
為了在表中存儲 ASCII 格式的數(shù)據(jù),您可以在表、表空間或數(shù)據(jù)庫級上使用帶有 CCSID ASCII 子句的 CREATE 語句。例如,在表級別上,按下列方式使用 CREATE TABLE 語句:
CREATE TABLE T1 (C1 int CCSID ASCII, C2 char(10) CCSID ASCII)
來自于上面 CREATE TABLE 語句的 CCSID ASCII 值是從面板 DSNTIPF 中獲得的。
下列語句使用面板 DSNTIPF 中指定的默認(rèn)編碼模式:
CREATE DATABASE
CREATE DISTINCT TYPE
CREATE FUNCTION
CREATE GLOBAL TEMPORARY TABLE
DECLARE GLOBAL TEMPORARY TABLE
CREATE TABLESPACE(在 DSNDB04 數(shù)據(jù)庫中)
如果 DSNTIPF 面板字段中的 CCSID 值不正確,字符轉(zhuǎn)換也將產(chǎn)生不正確的結(jié)果。正確的 CCSID 指定您站點(diǎn)的 I/O 設(shè)備、諸如 IMS 和 QMF 等本地應(yīng)用程序以及諸如 CICS Transaction Server 等遠(yuǎn)程應(yīng)用程序所支持的編碼字符集。
若沒有 IBM DB2 UDB Technical Support 的特定指導(dǎo),永遠(yuǎn)不要修改現(xiàn)有 DB2 UDB for z/OS 系統(tǒng)的 CCSID;否則,您可能損壞數(shù)據(jù)!
前面的小節(jié)展示了在不同的平臺中如何可以為應(yīng)用程序或數(shù)據(jù)庫確定和修改代碼頁值。本小節(jié)將通過兩個(gè)通用場景描述字符轉(zhuǎn)換過程。(它假定已經(jīng)為應(yīng)用程序和數(shù)據(jù)庫確定了代碼頁值)。轉(zhuǎn)換過程的基本規(guī)則就是接收系統(tǒng)將總是執(zhí)行代碼頁的轉(zhuǎn)換。
圖 8 中所展示的通用場景代表了下列情形:
Linux, UNIX, or Windows 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for Linux, UNIX, and Windows 服務(wù)器
iSeries 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for Linux, UNIX, and Windows 服務(wù)器
iSeries 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for iSeries 服務(wù)器
iSeries 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for z/OS 服務(wù)器
z/OS 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for Linux, UNIX, and Windows 服務(wù)器
z/OS 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for iSeries 服務(wù)器
z/OS 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for z/OS 服務(wù)器
圖 9 中所展示的通用場景代表了下列情形:
Linux, UNIX, or Windows 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for iSeries
Linux, UNIX, or Windows 客戶機(jī)上運(yùn)行的應(yīng)用程序到 DB2 UDB for z/OS
在圖 8 和 圖9 中,當(dāng)應(yīng)用程序所運(yùn)行的操作系統(tǒng)是 Linux、UNIX 或 Windows 時(shí),就可能需要安裝 DB2 UDB for Linux, UNIX, and Windows 客戶機(jī)。如果應(yīng)用程序是在 Java 中使用 JDBC Type 4 驅(qū)動程序編寫的,就不需要 DB2 UDB for Linux, UNIX, and Windows 客戶機(jī)。
在這兩個(gè)通用場景中,如果用于所有系統(tǒng)的代碼頁相同,就不會發(fā)生代碼頁轉(zhuǎn)換。當(dāng)您處理訪問 DB2 UDB for iSeries 或 z/OS 數(shù)據(jù)(使用 EBCDIC 編碼模式)的 Linux、UNIX 或 Windows 應(yīng)用程序(使用 ASCII 編碼模式)時(shí),這就不可能,除非所有這些系統(tǒng)都使用 Unicode。
下列例子說明了字符轉(zhuǎn)換的過程。讓我們假定您具有下列配置:
一個(gè) ODBC 應(yīng)用程序運(yùn)行在 Windows 機(jī)器上,默認(rèn)情況下,該應(yīng)用程序使用操作系統(tǒng)的代碼頁,本例子中就是 1252(Windows,English)。
將運(yùn)行 DB2 Connect 的 AIX 服務(wù)器設(shè)置為使用 Unicode。
iSeries 服務(wù)器使用代碼頁 66535,并具有一個(gè)包含表 DEPARTMENT 的數(shù)據(jù)庫,表 DEPARTMENT 的定義如下:
CREATE TABLE DEPARTMENT (DEPTNO CHAR(3) NOT NULL, DEPTNAME VARCHAR(36) CCSID 37 NOT NULL, PRENDATE DATE DEFAULT NULL)
列 DEPTNO 和 PRENDATE 將使用 iSeries 代碼頁 66535 作為默認(rèn)值。
當(dāng) Windows 應(yīng)用程序發(fā)出諸如下面的請求時(shí):
SELECT DEPTNO FROM DEPARTMENT
將發(fā)生下列轉(zhuǎn)換:
Windows 通過代碼頁 1252 向 DB2 Connect 服務(wù)器發(fā)送請求。
DB2 Connect 服務(wù)器將之轉(zhuǎn)換成代碼頁 1208(Unicode),然后發(fā)送給 iSeries 服務(wù)器。
iSeries 服務(wù)器將之轉(zhuǎn)換成 CCSID 66535,并訪問 DEPARTMENT 表中的數(shù)據(jù)。
因?yàn)閺谋碇蝎@得的數(shù)據(jù)是在 CCSID 66535 中,所以將在該代碼頁中,將數(shù)據(jù)發(fā)送給請求者(本例中,DB2 Connect 服務(wù)器)。
DB2 Connect 服務(wù)器將數(shù)據(jù)轉(zhuǎn)換成代碼頁 1208,然后發(fā)送給 Windows 應(yīng)用程序。
Windows 操作系統(tǒng)將代碼頁 1208 轉(zhuǎn)回到 1252。
在代碼頁轉(zhuǎn)換期間,源代碼頁 X 中的字符也許不存在于目標(biāo)代碼頁 Y 中。例如,讓我們假定一家跨國公司存儲了日語和德語這兩種語言的信息。一個(gè)相應(yīng)的日語應(yīng)用程序?qū)?shù)據(jù)插入這個(gè)使用 German 代碼頁創(chuàng)建的 DB2 UDB 數(shù)據(jù)庫中。在這樣的情形中,許多字符在 DB2 所使用的 CCSID 中沒有代碼點(diǎn)。這種情形下,解決該問題的一種方法就是通過僅將源 CCSID 中的字符映射到目標(biāo) CCSID 中的相應(yīng)字符。那些沒有映射的字符將通過預(yù)留的代碼點(diǎn)來代替。(每一個(gè)代碼頁至少預(yù)留了一個(gè)代碼點(diǎn),以便進(jìn)行替代。)那些無法映射到目標(biāo)代碼頁的字符將永遠(yuǎn)丟失。該方法稱作強(qiáng)制子集轉(zhuǎn)換。
另一種轉(zhuǎn)換方法稱作往返轉(zhuǎn)換。兩個(gè) CCSID 之間的往返轉(zhuǎn)換確保所有進(jìn)行“往返”的字符都以初始的樣子到達(dá),即使接收 CCSID 不支持某一給定字符。往返轉(zhuǎn)換確保從 CCSID X 轉(zhuǎn)換成 CCSID Y,并返回為 CCSID X 的代碼點(diǎn)的過程得到保護(hù),即使 CCSID Y 無法完全表示這些代碼點(diǎn)。這是通過使用轉(zhuǎn)換表實(shí)現(xiàn)的。
當(dāng)您需要使用轉(zhuǎn)換表的不同版本時(shí),如 Microsoft 版本,就必須手工替換默認(rèn)的轉(zhuǎn)換表(.cnv)文件,該文件駐留在 UNIX 和 Linux 平臺的 .../sqllib/conv 目錄或 Windows 上的 ...\sqllib\conv 中。這些表是用于在不同代碼頁之間轉(zhuǎn)換值的外部代碼頁轉(zhuǎn)換表。在替換 sqllib/conv 目錄中現(xiàn)有的代碼頁轉(zhuǎn)換表之前,您應(yīng)該備份該文件。
在所有平臺上,DB2 UDB 都支持 International Standards Organization(ISO)/International Electrotechnical Commission(IEC)標(biāo)準(zhǔn) 10646(ISO/IEC 標(biāo)準(zhǔn) 10646)Universal 2-Octect Coded Character Set(UCS-2)。UCS-2 是用 Unicode Transformation Format 8 位編碼格式(UTF-8)實(shí)現(xiàn)的。UTF-8 是為了易于使用現(xiàn)有基于 ASCII 的系統(tǒng)而設(shè)計(jì)的。UTF-8 格式中數(shù)據(jù)的代碼頁/CCSID 值是 1208。用于 UCS-2 的 CCSID 值是 1200。UTF-8 被選擇為字符數(shù)據(jù)列的默認(rèn)格式,其中 UTF-16 用于圖形數(shù)據(jù)列。
使用默認(rèn)值創(chuàng)建的 DB2 UDB for Linux, UNIX, and Windows 數(shù)據(jù)庫將在 ASCII 中創(chuàng)建表。為了創(chuàng)建 Unicode 數(shù)據(jù)庫,要使用帶有 CODESET 和 TERRITORY 子句的 CREATE DATABASE,如下:
CREATE DATABASE unidb USING CODESET UTF-8 TERRITORY US
這個(gè) Unicode 數(shù)據(jù)庫中的表都將默認(rèn)為代碼頁 1208。您無法在 Unicode 數(shù)據(jù)庫中用 ASCII 代碼頁定義表。然而,反過來則可以;即您可以在非 Unicode 的數(shù)據(jù)庫中創(chuàng)建 Unicode 表。這可以通過調(diào)用使用了 CCSID UNICODE 子句的 CREATE TABLE 語句來執(zhí)行。例如:
CREATE TABLE unitbl (col1 char(10), col3 int) CSSID UNICODE
為了使之工作,您首先需要激活數(shù)據(jù)庫配置參數(shù) alt_collate。一旦設(shè)置好了,該參數(shù)就無法進(jìn)行修改或重新設(shè)置。
UPDATE DB CFG FOR nonunidb USING ALT_COLLATE IDENTITY_16BIT
在 DB2 UDB for iSeries 中,CCSID 子句可以用于單獨(dú)的列上。例如,下列 SQL 語句創(chuàng)建表 U_TABLE。U_TABLE 包含一個(gè)名為 EMPNO 的字符列,以及兩個(gè) Unicode 圖形列。NAME 是一個(gè)固定長度的 Unicode 圖形列,而 DESCRIPTION 是一個(gè)可變長度的 Unicode 圖形列。EMPNO 字段僅僅包含數(shù)字,且不需要 Unicode 支持。NAME 和 DESCRIPTION 字段則都是 Unicode 字段。這兩個(gè)字段可能包含不止一個(gè) EBCDIC 代碼頁中的數(shù)據(jù)。
CREATE TABLE U_TABLE (EMPNO CHAR(6) NOT NULL, NAME GRAPHIC(30) CCSID 1200, DESCRIPTION VARGRAPHIC(500) CCSID 1200)
關(guān)于 iSeries 中有效的 CCSID 值列表,請查閱
Supported CCSID mappings。
與 DB2 UDB for Linux, UNIX, and Windows 相似,在 DB2 UDB for z/OS 中,如果您在對象定義上使用了 CCSID UNICODE 子句,就可以存儲并檢索 Unicode 數(shù)據(jù),例如:
CREATE TABLE DBTBDWR.WBMTEBCD (CUSTNO CHAR(8), CUSTBU CHAR(6), CUSTEXT CHAR(3), CNAME VARCHAR(80) FOR MIXED DATA) IN TEST.CUSTTS CCSID UNICODE
DB2 UDB for z/OS 使用 LE(語言環(huán)境)的 ICONV 執(zhí)行字符轉(zhuǎn)換,除非安裝了 z/OS Unicode Conversion Services。為了了解如何設(shè)置用于 DB2 的 z/OS Unicode Conversion Services,請查看信息 APAR II13048 和 II13049。為了查看是否安裝了轉(zhuǎn)換,請通過控制臺使用命令 /d uni, all,如圖 10 中所示。
例如,圖 10 展示了有從 1252 到 1208 以及 1208 到 1252(即從 Windows English 到 Unicode 以及反向進(jìn)行)的轉(zhuǎn)換。
在所有系統(tǒng)之間使用 Unicode 編碼模式將避免進(jìn)行字符轉(zhuǎn)換,并提高性能。
排序序列是字符集的一種次序,確定每個(gè)字符與另一字符相比排列更高、更低或相同。排序序列將代碼點(diǎn)映射至每個(gè)字符在已排序序列中的期望位置。例如,ASCII 中的排序序列是:空格、數(shù)字值、大小字符、小寫字符。另一方面,EBCDIC 中的排序序列則是:空格、小寫字符、大寫字符和數(shù)字值。
如果在 EBCDIC 數(shù)據(jù)庫上使用設(shè)計(jì)于操作 ASCII 數(shù)據(jù)庫的應(yīng)用程序,就可能產(chǎn)生問題,因?yàn)槠渑判蛐蛄胁煌?。您可以?chuàng)建定制的排序序列。關(guān)于更多細(xì)節(jié),請查閱 Application Development Guide: Programming Client Applications 手冊(參見
參考資料)。
聯(lián)邦系統(tǒng)不支持某些數(shù)據(jù)映射。例如,DB2 UDB 聯(lián)邦服務(wù)器不支持?jǐn)?shù)據(jù)類型 LONG VARCHAR 的映射。因此,所討論的場景可能不起作用。關(guān)于更多細(xì)節(jié),請查看 Federated Systems Guide(參見
參考資料)。
您無法用給定的代碼頁備份數(shù)據(jù)庫,并用不同的代碼頁將之恢復(fù)為另一種。在 DB2 UDB for Linux, UNIX, and Windows 上,您應(yīng)使用 export 或 db2move 實(shí)用程序,用新要求的代碼頁創(chuàng)建新的數(shù)據(jù)庫,并對數(shù)據(jù)進(jìn)行 import 或反向 db2move。在使用該方法時(shí),DB2 UDB 將正確地執(zhí)行字符轉(zhuǎn)換。
通過 BLOB 數(shù)據(jù)類型或使用 FOR BIT DATA 子句定義的列將以二進(jìn)制形式從源傳遞到目標(biāo),所使用的代碼頁是零。這表示不會發(fā)生任何代碼頁轉(zhuǎn)換。
當(dāng)您碰到字符轉(zhuǎn)換方面的問題時(shí),首先要識別應(yīng)用程序和所涉及的 DB2 UDB 數(shù)據(jù)庫服務(wù)器使用哪些代碼頁。
除了前面所討論的用于確定操作系統(tǒng)或 DB2 UDB 數(shù)據(jù)庫服務(wù)器的代碼頁值的方法之外,下列方法將向您展示目標(biāo)和源中的代碼頁。本小節(jié)中的討論適用于 DB2 UDB for Linux, UNIX, and Windows。
使用帶有“-a”選項(xiàng)的 CLP 來顯示 SQLCA 信息
當(dāng)您使用 CLP 的“-a”選項(xiàng)來顯示 SQLCA 信息時(shí),將展示源應(yīng)用程序(本例中,CLP)和目標(biāo)數(shù)據(jù)庫的代碼頁。圖 11 展示了一個(gè)從 Windows 上 CLP 連接到 Windows 上數(shù)據(jù)庫的例子。
在圖 11 中,請注意下行:
sqlerrmc: 1 1252 ARFCHONG SAMPLE QDB2/NT 557 557 0 1252 1
第一個(gè)實(shí)例“1252”指明目標(biāo)上所使用的代碼頁,即 Windows US-English。第二個(gè)實(shí)例指明源上所使用的代碼頁,同樣也是 Windows US-English。
圖 12 展示了另一例子,這次是從 Windows CLP(其中安裝了 DB2 Connect)連接到 DB2 UDB for z/OS 目標(biāo)數(shù)據(jù)庫。
在圖 12,請注意下行:
sqlerrmc: 1208 TS56692 HOSTV8 QDB2 1252
1208 指明目標(biāo) DB2 UDB for z/OS 子系統(tǒng)使用 Unicode。
1252 指明源 CLP 應(yīng)用程序使用 Windows US-English。
為 CLI、ODBC 或 JDBC Type 2 應(yīng)用程序使用 CLI 跟蹤
為了標(biāo)識 CLI 和 JDBC type 2 應(yīng)用程序的代碼頁,您可以使用 DB2 CLI on Linux, UNIX, and Windows 所提供的跟蹤工具。默認(rèn)情況下,該跟蹤工具是禁用的,并且不使用任何附加的計(jì)算資源。啟用時(shí),無論應(yīng)用程序何時(shí)訪問 CLI 驅(qū)動程序,都將生成文本日志文件。您可以通過在 db2cli.ini 文件中添加下列 DB2 CLI 關(guān)鍵字來打開 CLI 跟蹤,如下:
[COMMON] trace=1 TraceFileName=\temp\clitrace.txt TraceFlush=1
\temp\clitrace.txt 可以是任意的名稱,用來做為跟蹤存儲的目錄和文件名。
您可以在跟蹤輸出文件中從 SQLConnect() 或 SQLDriverConnectW() 調(diào)用找到應(yīng)用程序和數(shù)據(jù)庫代碼頁。例如,應(yīng)用程序和數(shù)據(jù)庫服務(wù)器在下列消息中使用相同的代碼頁(1252):
(Application Codepage=1252, Database Codepage=1252, Char Send/Recv Codepage=1252, GraphicSend/Recv Codepage=1200, Application CharCodepage=1252, Application Graphic Codepage=1200
在大多數(shù)情況下,沒有定義源和目標(biāo)代碼頁之間的轉(zhuǎn)換表或定義。DB2 UDB for Linux, UNIX, and Windows 中的轉(zhuǎn)換表存儲在 sqllib/conv 目錄下,它們通常處理大多數(shù)轉(zhuǎn)換場景。
在 iSeries 上,IBM 提供的表可以在 QUSRSYS 庫中找到。您還可以使用 Create Table(CRTTBL)命令創(chuàng)建自己的轉(zhuǎn)換表。iSeries Information Center 中的 Globalization 主題包括了轉(zhuǎn)換表列表(參見
參考資料)。
您還可以運(yùn)行下列查詢來查看字符集名稱列表:
SELECT character_set_name from sysibm.syscharsets
在 DB2 UDB for z/OS 上,如
圖 10 中所示,您可能需要發(fā)出 /d uni, all 命令來顯示已經(jīng)安裝了的轉(zhuǎn)換。如果該命令的輸出沒有列出您所需要的轉(zhuǎn)換,例如從 1252 到 1208,您就要向 Unicode Conversion Services 添加一個(gè)轉(zhuǎn)換條目(示例 JCL hlq.SCUNJCL(CUNJIUTL)),例如:CONVERSION 1252,1208,ER
您還要在 DB2 UDB for z/OS 目錄表 SYSIBM.SYSTRINGS 中驗(yàn)證存在給定的轉(zhuǎn)換條目。例如,查看該表中的條目列表,就要發(fā)出該查詢:
SELECT inccsid, outccsid FROM sysibm.sysstrings
如果這些還沒有解決您的問題,
請聯(lián)系 DB2 UDB Technical Support。您可能被要求收集 DB2 跟蹤,并用 fmt -c 選項(xiàng)(以前稱作 DDCS 跟蹤)將其格式化。該跟蹤將展示源和目標(biāo)之間傳遞和檢索了什么。
本文提供了對于 DB2 UDB 數(shù)據(jù)庫內(nèi)部以及數(shù)據(jù)庫之間發(fā)生的字符轉(zhuǎn)換過程的概述。它首先解釋了諸如代碼頁、代碼點(diǎn)和編碼模式等關(guān)鍵概念,并說明了如何查看它們的當(dāng)前值以及如何更新該值。接著,提供了通用場景以展示字符轉(zhuǎn)換的過程。本文闡述了轉(zhuǎn)換期間的一些特殊注意事項(xiàng),并提供了一個(gè)兩步確定導(dǎo)致轉(zhuǎn)換問題原因的方法。
理想情況下,您應(yīng)通過在轉(zhuǎn)換的源和目標(biāo)之間使用相同的代碼頁,盡力避免字符轉(zhuǎn)換以提高性能。但是如果您的數(shù)據(jù)庫場景十分復(fù)雜,您無法避免字符轉(zhuǎn)換,那么本文的知識將幫助您盡可能順利地完成該過程。