数据库资讯

用DB2 pureXML执行不区分大小写的高效搜索

根据定义,XML 元素和属性的值是区分大小写的。例如,如果搜索值为 “Paris” 的 元素,那么不会找到 “PARIS” 或 “paris”。可以使用 fn:upper-case() 等 XQuery 函数解决这个问题,但是使用这些函数时不能使用 XML 索引,所以性能可能不好。本文解释如何使用 DB2® pureXML™ 创建不区分大小写的数据库以及让 XML 查询和 XML 索引发挥预期的作用。用大写和小写函数执行不区分大小写的搜索

下面的示例帮助您更清楚地理解不区分大小写的搜索。清单 1 定义一个包含一个 INTEGER 列和一个 XML 列的表,并在表中插入 7 行。每行包含一个小的客户文档,其中包含 XML 元素

此元素中的值在大小写方面并不一致。一些值是全大写的,一些是全小写的,其他是大小写混合的(首字母大写)。如果数据来自不同的应用程序,而这些应 用程序采用不同的大小写数据输入规则,就会出现这种情况。

清单 1. 示例表和数据

CREATE TABLE customer (id INTEGER, xmldoc XML);

INSERT INTO customer (id, xmldoc)
VALUES (1,'<Customer id="1"><city>PARIS</city></Customer>'),
       (2,'<Customer id="2"><city>Tokyo</city></Customer>'),
       (3,'<Customer id="3"><city>tokyo</city></Customer>'),
       (4,'<Customer id="4"><city>PARIS</city></Customer>'),
       (5,'<Customer id="5"><city>paris</city></Customer>'),
       (6,'<Customer id="6"><city>Delhi</city></Customer>'),
       (7,'<Customer id="7"><city>Paris</city></Customer>'); 

如果一个应用程序查询这些 XML 文档,寻找某一城市的客户,那么很可能需要不区分大小写的搜索。例如,可能希望找到 Paris 的所有客户,也就是希望获取第 1、4、5 和 7 行。但是,如果搜索值 “Paris”,那么只会返回第 7 行。要想获取所需的所有四行,可以使用 XQuery 函数 fn:upper-case() 把 city 元素值转换为大写并与 “PARIS” 做比较。清单 2 中的查询就采用这种方式,它会返回 Paris 的所有四个客户。

清单 2. 选择 Paris 的客户

    
SELECT id, XMLCAST( XMLQUERY('$XMLDOC/Customer/city') AS VARCHAR(15)) AS city
FROM customer
WHERE XMLEXISTS('$XMLDOC/Customer[fn:upper-case(city) = "PARIS"]'); 

如果查询通过一个参数标志提供搜索值,那么这个参数也应该转换为大写,见 清单 3。这个参数标志(“?”)的类型为 VARCHAR(15) 并作为变量 “c” 传递给 XQuery 谓词。

清单 3. 使用参数标志选择客户

   
SELECT id, XMLCAST( XMLQUERY('$XMLDOC/Customer/city') AS VARCHAR(15)) AS city
FROM customer
WHERE XMLEXISTS('$XMLDOC/Customer[fn:upper-case(city) = fn:upper-case($c)]'
PASSING CAST(? AS VARCHAR(15)) AS "c"); 


图 1 显示以上示例查询的输出。

图 1. 示例查询的结果

如果只查询少量数据,或者查询还包含其他选择性谓词,使得大写谓词只应用于很小的中间结果集,那么这种方式效果还不错。问题是如果使用包含 fn:upper-case() 函数的谓词,就不会使用 DB2 中的 XML 索引。因此,这种方式不适用于大量数据。

要想避免使用 fn:upper-case() 函数并利用 XML 索引加快查询,就需要创建不区分大小写的数据库。

创建不区分大小写的 DB2 数据库

DB2 从 Version 9.5 Fixpack 1 开始支持感知地区的 Unicode 排序规则。这使我们能够忽略大小写和/或重音符号。要想创建对于所有字符串比较不区分大小写的数据库,需要使用排序规则 UCA500R1,见 清单 4。

清单 4. 创建不区分大小写的数据库

   
CREATE DATABASE testdb
USING CODESET UTF-8 TERRITORY US
COLLATE USING UCA500R1_LEN_S2; 

字符串 UCA500R1_LEN_S2 究竟意味着什么?UCA500R1 指定此数据库使用基于 Unicode 5.0.0 标准的默认 Unicode Collation Algorithm(UCA)。因为默认的 UCA 不能同时覆盖 Unicode 支持的每种语言的排序规则序列,所以可以使用可选属性定制字符的次序。属性以下划线(_)分隔。UCA500R1 关键字加上所有属性构成一个 UCA 排序规则名。

希望看到您的想法,请您发表评论x