DBA:实例讲解非“Unicode”数据库中的XML
|
源代码网整理以下 本文解释如何在 DB2® Viper 2 中的非 Unicode 数据库中使用 XML 本地数据类型。发现避免替换字符、查询结构指针和字符引用的使用的技巧,以及对产品附带的新的实用用户定义函数(UDF)的解释。 V9 中的 XML 支持 在 DB2 9 中,将 XML 数据包括在数据库中的惟一方法是让数据库使用 UTF-8 码集。即使 XML 数据中只包含 ASCII 代码点,这个限制也仍然有效。XML 是以二进制格式存储在数据库中的,文本节点被存储为 UTF-8 代码点。在 DB2 9 中,不会对 XML 文档进行转换,因此必须以一系列的 UTF-8 字节的形式将 XML 文档插入到数据库中。 DB2 Viper 2 版解除了这一限制,即所有使用 pureXML 特性的数据库必须以 Unicode 方式创建。本文解释非 Unicode 数据库中的 XML 支持,以及如何在保证数据完整性的情况下安全地插入和查询 XML 文档。 例子场景:在不必迁移至 Unicode 码集的情况下迁移至 pureXML 假设您是一个已有的非 Unicode DB2 数据库的数据库管理员(DBA),该数据库包含一个用于编目图书馆中的书籍的表。目前,这个表具有以下形式: 清单 1. 示例关系模式
然而,在非 Unicode 关系表中,对于表中的数据有一些限制。如果书的题目或文本包含当前数据库的字符集以外的字符会怎样?为什么要将这个表限制为每本书只有两个关键字?如果对于一个新的条目,关键字太大怎么办?如果一本书有一个未知的出版日期,或者有多个作者,怎么办? 这个模式有太多的限制,所以您决定探索如何以 XML 的形式存储数据,但是又不想将现有的数据库迁移至 UTF-8。 假设这个书籍数据库还要接纳来自世界各地的新书,这些书可能用中文、俄语和其他语言编写。您希望用英语和本地语言存储关于书的元数据(题目、作者、第一段)。每本书可以建模为一个 XML 文档,取决于这本书的语言,这个 XML 文档的编码方式可能不同。那么,如何在非 Unicode pureXML 数据库中插入、存储和查询这些文档呢? 非Unicode 数据库中对 XML 的新的支持 在 DB2 Viper 2 中,用户现在可以在任何新的或已有的数据库中,在新的或已有的表中创建 XML 列。现在不再要求使用 Unicode 码集。创建 XML 类型的列的格式是: CREATE TABLE 请注意 CREATE TABLE 的语法仍然和以前一样。 例子: 清单2. 创建 XML 类型的列 CREATE TABLE xmlbookcat ( ISBN BIGINT NOT NULL PRIMARY KEY, BOOK XML ); 为了修改一个表以添加一个 XML 列,必须能够合法地添加一个列到表中(即表中不能有不带 DEFAULT 子句的 NOT NULL 列,并且表中行的大小必须能够容纳新的 XML 列,这个列长度为 80 字节)。 DB2 允许用户在 CREATE TABLE 或 ALTER TABLE 的列声明中使用 CCSID UNICODE 或 CCSID ASCII 子句,以创建以不同于数据库其他部分的字符码集标识符(CCSID)存储的表。在非 Unicode 数据库中,将 XML 列添加到具有 CCSID UNICODE 属性的表中是非法的。那样的表不存储在数据库代码页中,在这些表中 XML 不受支持。如果尝试这么做,会产生 a -873(代码页不匹配)错误。在非 Unicode 数据库中创建一个新的用于存储 XML 数据的表。 例子: CREATE TABLE untable(a VARCHAR(20)) CCSID UNICODE; ALTER TABLE untable ADD xmlcol XML; 这将产生错误 SQL0873N Objects encoded with different encoding schemes cannot be referenced in the same SQL statement。 XML数据的存储 这些 XML 文档必须具有类似于下面的结构: 清单3. XML 文档的结构
由于不同的书籍可能用不同的语言编写,因此需要在同一个 DB2 列中存储包含不同字符集的 XML 文档。下面的例子显示,为了提高可读性,元素的名称采用 ASCII,但是元素中的值可以由任何有效的 Unicode 代码点组成。下面是这些 XML 文档的示例数据: 清单4. XML 文档的示例数据
清单5. XML 文档的示例数据
清单 6. XML 文档的示例数据
在了解如何在非 Unicode 数据库中安全地存储这些数据之前,需要研究解析和查询执行期间 XML 数据在 DB2 中的流程,包括从客户机到服务器,以及从服务器到 pureXML 特性。 XML数据流 DB2的XML组件在 Unicode 代码页范围内操作。因此,所有 XML 解析、串行化、查询执行和压缩都必须在 Unicode 代码页范围内进行。当数据库是 UTF-8 数据库时,可以在数据库代码页中操纵数据。如果数据库采用非 Unicode 代码页(例如 ISO-8859-1),那么所有 XML 文档、XQUERY 字符串和片段都必须经过代码页转换,从数据库代码页转换为 Unicode(特别地,转换为 UTF-8,代码页 1208)。 DB2 的 SQL 组件在数据库代码页中操作。所有 SQL 比较、SQL 查询执行以及 SQL 类型转换都必须在数据库代码页中进行。如果查询由一些 XML 活动和一些 SQL 活动组成,那么要在 “XML” 和 “SQL” 这两个 “世界” 之间进行转换,因为每个世界的数据必须在正确的代码页中。 将数据从数据库代码页转换为 UTF-8 代码页称为转换到 “XML 世界”,而将数据从 UTF-8 转换到数据库代码页则称为转换到 “SQL 世界”。这是服务器上 SQL/XML 或 XQUERY 执行期间惟一的两种代码页转换形式。 为了使非 Unicode 数据库支持 XML,建议使用一个 Unicode 客户机,因为客户机必须能够呈现输入 XML 和结果 XML 文档中的所有字符。如果哦客户机代码页和数据库代码页相同,那么客户机与服务器之间就不存在转换,于是客户机就可以呈现输入 XML 和结果 XML 文档中的所有字符。 客户机可以临时使用 DB2CODEPAGE 环境变量覆盖代码页。如果将这个变量设置为 1208 (UTF-8),那么 DB2 就可以像在代码页 1208 中那样与客户机通信。用这种方法覆盖客户机代码页可能导致不正确的输出或者不能打印的字符(例如将 Kanji 数据从一个 943 数据库发送到一个已经覆盖了 DB2CODEPAGE 的 ASCII 客户机)。在 Windows 中,可以在 Windows 控制面板中修改语言和环境设置,以覆盖客户机环境的代码页。 什么东西要经过转换?
![]() 每当从 DB2 客户机发生任何请求到 DB2 服务器,所有字符数据(例如查询或 CHAR 主机变量)都要从客户机代码页转换为数据库代码页。不管请求中是否牵涉到 XML,这个过程都会发生。 查询的 XML 部分被转换到 XML 世界,以便 XML 解析器进行解析以及 XML 值的输出(串行化)。结果则被转换到 SQL 世界。这两个转换都可能引入替换字符,即当目标代码页不能呈现代码点时插入到字符流中的替换代码点。替换字符会导致服务器上损失数据完整性。本文将寻找避免替换字符的方法。 SQL 查询的结果和串行化 XML 在传回客户机之前被转换到 SQL 世界。在这个时候,如果串行化 XML 包含数据库代码页中不能表示的字符,或者在客户机代码页中不能表示的字符,就可能引入替换字符。下面讨论避免这两种替换字符陷阱的方法。 插入XML 文档 至此,您已经知道了数据如何转换到正确的代码页,那么,这对于插入 XML 文档有何影响呢?为了将一个 XML 文档插入到表中,可以使用一个包含 XML 数据的字符串: 清单 7. 包含XML数据的字符串
整个 INSERT 语句被从客户机代码页转换到数据库代码页,然后 XMLPARSE 文档字符串被转换到 UTF-8,以便解析为 XML。这些转换并没有引入替换字符,并且是可逆转的,所以在这个场景中可以安全地插入 XML 数据。插入用数据库代码页编码,并且只包括在数据库代码页中可以表示的字符的 XML 文档总是安全的。即使对于非 Unicode 数据库,这一点仍然适用。但是,如果想在同一个环境中插入中文 XML 文档,情况会怎样呢? 源代码网供稿. |

