在非 Unicode 資料庫中使用 XML 的準則

pureXML® 特性可讓您儲存及擷取資料庫中的 XML 資料,即使該資料庫不使用 Unicode 字碼頁也一樣。 本主題提供如何在此狀況下安全儲存 XML 資料的指引,以將資料毀損或遺失的任何可能性降至最低。

在關聯式資料庫表格中儲存 XML 文件時,為了確保資料完整性,您需要注意要儲存的 XML 文件的編碼,以及目標資料庫的編碼。 當這兩種編碼相符時,一律可以安全地插入資料。 如果這兩種編碼不相符,則可能需要字元轉換。 具體而言,在插入時, XML 文件中任何在目標資料庫字碼頁中沒有相符字碼點的字元都會被替換。 此外,在任何 XML 處理期間,例如在涉及 XML 資料的強制轉型或比較作業期間,也會發生第二個字元替代。 這些作業一律以 Unicode 格式進行管理,因此在作業期間,非 Unicode 資料庫中的字元必須轉換為 UTF-8 格式。 在任何需要字元替代的事件中,該資料上的作業可能會有非預期的結果,而從資料庫擷取的 XML 資料可能包含不正確的值。

下列討論說明在各種編碼實務下插入及查詢 XML 資料的方法,提供安全避免字碼頁轉換的方法,以確保所儲存 XML 資料及其相關作業的完整性。

內容

XML 文件插入及字碼頁轉換

每當透過具有字元資料類型 (不是 FOR BIT DATA 類型的 CHAR、VARCHAR 或 CLOB 資料類型) 的主變數或參數標記,將 XML 資料插入 Db2® 資料庫伺服器時,如果資料庫字碼頁與發出要求的用戶端或應用程式的字碼頁不同,則會進行字碼頁轉換。 當插入的字元資料從資料庫字碼頁轉換成 Unicode (在內部管理 XML 資料的格式) 時,會進行第二次轉換。

下表顯示資料庫與從用戶端或應用程式插入的 XML 文件字串之間的各種可能的編碼組合。 XML 文件編碼與用戶端字碼頁相同,因為用戶端透過字元資料類型插入 XML 資料。 對於每一個組合,會說明字碼頁轉換的含意,以及在 XML 文件插入期間產生字元替代的可能性。
表 1. 資料庫與所插入 XML 文件字串之間的編碼實務
實務範例 XML 文件編碼 資料庫編碼 字碼頁相符?
1. Unicode (UTF-8) Unicode (UTF-8)
2. 非 Unicode Unicode (UTF-8) no
3. 非 Unicode 非 Unicode
4。 Unicode (UTF-8) 非 Unicode no
5. 非 Unicode 非 Unicode no
  1. 在實務範例 1 中, XML 文件和資料庫共用 Unicode 編碼。 插入 XML 文件時不會發生字元轉換。 以這種方式插入 XML 資料一律是安全的。
  2. 在實務範例 2 中,非 Unicode XML 文件會轉換為 UTF-8 ,以插入 Unicode 資料庫中。 在此處理程序中不會發生字元替代。 以這種方式插入 XML 資料一律是安全的
  3. 在實務範例 3 中, XML 文件和資料庫共用相同的非 Unicode 編碼。 在此情況下, XML 文件只能包含屬於資料庫字碼頁的字碼點,因此在字碼頁轉換期間不會發生字元替代。 以這種方式插入 XML 資料一律是安全的
  4. 在實務範例 4 中, Unicode XML 文件會插入非 Unicode 資料庫中。 如果透過具有字元資料類型的主變數或參數標記,從 UTF-8 用戶端或應用程式插入 XML 文件,則會進行字碼頁轉換。 XML 文件中任何在資料庫字碼頁中沒有相符字碼點的字元都會替換。
  5. 在實務範例 5 中,會將 XML 文件插入資料庫伺服器中,其中兩個資料庫伺服器具有不同的編碼,這兩個編碼都不是 UTF-8。 在此情況下,如同在實務範例 4 中,如果使用字元資料類型插入 XML 文件,則在 XML 文件包含資料庫字碼頁中無效的字元的任何情況下,都會發生字元替代。

安全地將 XML 資料插入非 Unicode 資料庫

確保 XML 資料完整性最安全的方法是使用 Unicode 資料庫。 不過,如果無法這樣做,還有其他方法可防止字元替代發生。 不論是否使用 Unicode 資料庫,下列清單說明安全插入 XML 資料的各種方法:

使用 Unicode 資料庫,或確保資料庫和用戶端使用相同的編碼
表 1所示,在下列情況下,一律會避免 XML 資料的字碼頁轉換問題:
  • 資料庫是 Unicode
  • 不論是否為 Unicode ,資料庫和用戶端共用相同的編碼
避免使用具有字元資料類型的主變數或參數標記

當無法使用 Unicode 資料庫時,也可以使用 XML 類型或任何二進位資料類型的主變數或參數標記來連結 XML 資料,以避免 XML 資料的字碼頁轉換。 亦即,為 XML 資料指定 CHAR、VARCHAR 或 CLOB 以外的資料類型,可讓它直接從用戶端或應用程式字碼頁傳遞至 Unicode ,並略過對資料庫字碼頁的轉換。

ENABLE_XMLCHAR 配置參數可讓您控制是否容許透過字元資料類型插入。 將 ENABLE_XMLCHAR 設為 "NO" 會在 XML 文件插入期間封鎖字元資料類型的使用,防止可能的字元替代,並確保所儲存 XML 資料的完整性。 仍然容許 BLOB 及 FOR BIT DATA 類型,因為這些資料類型可免於字碼頁轉換。 依預設, ENABLE_XMLCHAR 會設為 "YES" ,因此容許插入字元資料類型。

當使用 Unicode 資料庫時,字碼頁轉換永遠不會有問題,因此在此情況下, ENABLE_XMLCHAR 配置參數沒有作用; 不論 ENABLE_XMLCHAR 的設定為何,都可以使用字元資料類型來插入 XML 文件。

對不在資料庫字碼頁中的字元使用字元實體參照
如果無法避免字碼頁轉換,且 XML 資料串流必須使用字元資料類型,最好是確保 XML 文件中的所有字元在資料庫字碼頁中都有相符的字碼點。 對於 XML 資料中在目標資料庫中沒有相符字碼點的任何字元,您可以使用字元實體參照來指定字元的 Unicode 字碼點。 字元實體參照一律會略過字碼頁轉換,以便在 XML 資料中保留正確的字元。 例如,字元實體參照 > 及 > 分別是大於符號 ("> ") 的十六進位及十進位對等項目。

查詢非 Unicode 資料庫中的 XML 資料

如同將 XML 資料插入資料庫,在涉及 XML 資料的查詢期間確保資料完整性最安全的方法是使用 Unicode 資料庫。 如果無法這樣做,請確定資料庫字碼頁中的所有 XML 資料都可呈現,或對不在資料庫字碼頁中的字元使用字元實體參照,以避免字元替代。

如果查詢包含的 XML 內容包含資料庫字碼頁中無法呈現的字元,則可能會發生下列兩種類型的字元替代,可能導致查詢出現非預期的結果:
依預設替代字元取代
會引進字碼頁的預設替代字元,以取代 XML 資料中不可比對的字元。 例如,如果將中文字元傳遞至 ASCII 編碼資料庫 (ISO-8859-1) ,則原始字元會替換為 ASCII 字碼點 0x1A,此控制字元在用戶端上顯示時通常會顯示為問號 ('?')。 當 XML 資料從資料庫字碼頁轉換成 Unicode 時,會保留替代字元。
以最接近的字元對等項目 ("摺疊") 取代
原始輸入字元會被目標字碼頁中與原始字元類似但不一定相同的字元所取代。 有時會有兩個以上具有不同 Unicode 字碼點的字元對映至資料庫字碼頁中的單一字碼點 (目標字碼頁中最接近的字元對等項目) ,因此在插入至資料庫之後,會失去值之間的區別。 範例 2 說明此實務範例。

範例

下列範例示範當使用具有 UTF-8 編碼的用戶端或應用程式來查詢非 Unicode 資料庫中的 XML 資料時,字碼頁轉換的可能效果。 在這些範例中,假設資料庫是使用字碼頁 ISO8859-7 (希臘文) 建立的。 XQuery 表示式用於比對儲存在表格 T1中的 XML 資料,其中儲存的 XML 資料包含 Unicode 希臘西格瑪字元 (ΣG) 和 Unicode 數學西格瑪字元 (ΣM)。 字碼點 0xD3 識別 ISO8859-7 資料庫中的 sigma 字元。

使用下列指令建立並移入表格 T1 :
CREATE TABLE T1 (DOCID BIGINT NOT NULL, XMLCOL XML);
INSERT INTO T1 VALUES (1, XMLPARSE(
       document '<?xml version="1.0" encoding="utf-8" ?> <Specialchars>
	<sigma>ΣG</sigma>
	<summation>ΣM</summation>
	</Specialchars>' 
       preserve whitespace));
範例 1: 成功的字碼頁轉換 (字元在資料庫字碼頁中可呈現)
XQUERY for $test in db2-fn:xmlcolumn("T1.XMLCOL")//*[. = "ΣG"] return $test
此表示式會產生想要的結果:
<sigma>ΣG</sigma>
在此情況下,表示式 ΣG 從用戶端開始作為希臘西格瑪字元 (U+03A3) 的 Unicode 字碼點,在希臘資料庫字碼頁 (0xD3) 中轉換為西格瑪字元,然後轉換回正確的 Unicode 字元以進行 XML 處理。 因為希臘西格瑪字元在資料庫字碼頁中可呈現,所以表示式會正確地比對。 下表顯示此字元轉換:
表 2. 字元資料轉換 (範例 1)
  用戶端 (UTF-8)   資料庫 (ISO8859-7)   XML 剖析器 (UTF-8)
字元 U+03A3 (希臘西格瑪) 0xD3 (希臘標準差) U+03A3 (希臘西格瑪)
範例 2: 不成功的字碼頁轉換 (字元在資料庫字碼頁中不可呈現)
XQUERY for $test in db2-fn:xmlcolumn("T1.XMLCOL")//*[. = "ΣM"] return $test
此表示式不會產生想要的結果:
<sigma>ΣG</sigma>
在此情況下,表示式 ΣM 從用戶端開始,作為數學符號 sigma (U+2211) 的 Unicode 字碼點,在希臘文資料庫字碼頁 (0xD3) 中轉換為 sigma 字元,然後在 XML 比較發生時比對 ΣG 字元。 對於 return 表示式,程序與範例 1 中的程序相同。 Unicode XML 字元 ΣG 首先轉換為希臘文資料庫字碼頁 (ΣA) 中的 sigma 字元,然後轉換回用戶端 UTF-8 字碼頁 (ΣG) 中的希臘文 sigma 字元。 下表顯示此字元轉換:
表 3. 字元資料轉換 (範例 2)
  用戶端 (UTF-8)   資料庫 (ISO8859-7)   XML 剖析器 (UTF-8)
字元 U+2211 (數學標準差) 0xD3 (希臘標準差) U+03A3 (希臘西格瑪)
範例 3: 使用字元實體參照來略過字碼頁轉換
XQUERY for $test in db2-fn:xmlcolumn("T1.XMLCOL")//*[. = "&#2211;"] 
   return $test
此表示式會產生想要的結果:
<summation>ΣM</summation>
In this case, the expression ΣM begins at the client as the Unicode code point for the mathematical symbol sigma (U+2211), and because it is escaped as character reference &#2211, the Unicode code point is preserved when it is passed to the XML parser, allowing for successful comparison against the stored XML value ΣM. 下表顯示略過字元轉換:
表 4. 字元資料轉換 (範例 3)
  用戶端 (UTF-8)   資料庫 (ISO8859-7)   XML 剖析器 (UTF-8)
字元 U+2211 (數學標準差的字元參照) "&#2211" (character reference for mathematical sigma) U+2211 (數學標準差)
範例 4: 不成功的字碼頁轉換 (在資料庫字碼頁中無法呈現字元)
此範例類似於範例 1 ,但這裡使用 ASCII 編碼資料庫,並在 XML 表示式中引進字碼頁的預設替代字元。
XQUERY for $test in db2-fn:xmlcolumn("T1.XMLCOL")//*[. = "ΣG"] return $test
此查詢無法符合表格 T1中的正確值。 在此情況下, Unicode 字元 U+2211 (希臘西格瑪) 在 ASCII 字碼頁中沒有相符的字碼點,因此會建立預設替代字元,在此情況下為問號字元 ('?')。 下表顯示此字元轉換:
表 5. 字元資料轉換 (範例 4)
  用戶端 (UTF-8)   資料庫 (ISO8859-1)   XML 剖析器 (UTF-8)
字元 U+2211 (數學標準差) 0x003F ('?') 0x003F ('?')