跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

在 DB2 SQL 函数中使用 XML

考察 DB2 SQL UDF 对 XML 的支持

刘长生, 软件工程师, IBM
刘长生的照片
刘长生,IBM CDL软件工程师,具有多年软件开发经验,曾从事组件库技术的研究,目前从事 DB2 pureXML 相关的开发工作。

简介: 目前有一些文章介绍如何在 SQL 存储过程中使用 XML,但没有介绍如何在 SQL 用户定义函数(UDF)中使用 XML 的。而 SQL 存储过程和 SQL UDF 是 DB2 应用开发中重要的数据库对象。本文将在介绍 DB2 SQL UDF 和 pureXML 技术的基础上,说明 SQL UDF 对 XML 的支持情况,并通过例子说明如何在 SQL 内联型(inline)函数中使用 XML。通过本文的介绍,用户对 DB2 数据库中 XML 的应用开发了解得更全面,了解如何在 SQL UDF 中使用 XML。

发布日期: 2012 年 1 月 30 日
级别: 初级
访问情况 : 1033 次浏览
评论: 


前言

作为 SQL/SQL PL 强大功能的一部分,DB2 用户可以编写 SQL 存储过程(Stored Procedure)、用户定义函数(User Defined Function,UDF)以及触发器(Trigger)等数据库服务器端应用,实现基于 SQL 语句的复杂逻辑功能。在 DB2 v9 以后引入了对 XML 原生态的支持,并在后续的版本中持续地加以改进。用户可以像使用其它传统的关系型数据类型一样使用 XML 数据类型来创建存储 XML 数据的表,使用传统的 SQL 语句插入 XML 文档和获取整个 XML 文档,也可以使用 SQL/XML 或 XQuery 查询获取 XML 片段和节点信息。XML 数据类型的支持也被自然地延伸到 SQL 存储过程和 SQL UDF 中,XML 可以作为输入、输出和返回的参数的数据类型,也可以用作局部变量的类型。对于 SQL 存储过程如何支持 XML,即怎样在 SQL 存储过程中使用 XML,已经有一些技术文章做了较为详细的介绍(参阅 http://www.ibm.com/developerworks/db2/library/techarticle/dm-0701oliva/index.html?S_TACT=105AGX52&S_CMP=cn-a-db2),但有关 SQL UDF 对 XML 支持的内容,却少有提及,本文将对这一主题作专门的介绍。

DB2 SQL 函数

1. 基本概念

在 SQL 标准中,对于函数有明确的定义:函数是 SQL 表达能力的扩展,由输入参数运算得到结果。DB2 支持函数,这些函数可以是系统内部函数,也可以是用户定义的函数。用户创建的 UDF 可以使用一般的高级编程语言,如 C/C++、Java 等,即使用这些高级语言实现特定的功能,包括对数据库中数据的读取和修改,然后将这些功能方法注册到数据库中,这样普通的 SQL 语句就可以引用他们。这一类函数就是所谓的“外部函数”。用户也可以直接将 SQL 语句按照一定的逻辑组织起来,完成一个相对完整的功能单元,并在不同的 SQL 上下文中调用,这一类函数就是 SQL UDF。

图 1 清楚地说明了 DB2 函数的基本体系以及 SQL 函数(SQL UDF)在该体系中的位置。对于 SQL 函数的进一步划分,在下一节中予以介绍。


图 1. DB2 函数的基本体系
图 1. DB2 函数的基本体系

2. SQL UDF 的分类

在 DB2 中,使用 CREATE FUNCTION 命令创建 SQL 函数,有关命令的详细参数,请参见 DB2 InfoCenter。SQL UDF 根据返回值类型的不同,可以分为标量函数、矢量函数和表函数;根据实际定义的逻辑是否在函数体内实现,可以分为普通函数和有源 / 模板函数;根据 SQL 语句在 DB2 内部执行机制和方式的不同,可以分为内联型(Inline)和编译型(Compiled)函数。

标量函数:SQL UDF 的返回值是单一值,可以是 UDF 支持的任一种 SQL 类型,如 INT、VARCHAR 等。清单 1 是一个 SQL 标量 UDF 的例子,将输入参数和返回值的类型都是 VARCHAR(500),其功能是实现英文字符串的反转。一般来说,标量函数可以在任何可使用 SQL 表达式的地方使用。


清单 1. SQL 标量 UDF 示例
				
 CREATE FUNCTION reverse_string_en(orig_string VARCHAR(500)) 
     RETURNS VARCHAR(500) 
     DETERMINISTIC NO EXTERNAL ACTION CONTAINS SQL 
     BEGIN ATOMIC 
     DECLARE reverse_string, rest_string VARCHAR(500) DEFAULT ''; 
     DECLARE len INT; 
     IF orig_string IS NULL THEN 
       RETURN NULL; 
     END IF; 
     SET rest_string = orig_string; 
     SET len = LENGTH(orig_string); 
     WHILE len > 0 DO 
       SET reverse_string = SUBSTR(rest_string, 1, 1) CONCAT reverse_string; 
       SET rest_string = SUBSTR(rest_string, 2, len-1); 
       SET len = len -1; 
     END WHILE; 
     RETURN reverse_string; 
 END

矢量函数:也称为行函数,SQL UDF 的返回值,简单地,可以理解为一行数据,一个元组或矢量,与数据表的一行在概念上有所区别。实际上,矢量函数被用来实现结构化数据类型的转换功能,输入是一个结构化的数据类型,输出是一行数据库内建类型的数据。比如清单 2 中,假设 EMPLOYEE 是一个已定义的复杂结构,其中包含供职单位 employer、薪水 salary 以及包括姓名 name、性别 gender、身高 length 和体重 weight 等在内的个人信息,函数 getNames 将把输入 EMPLOYEE 类型的参数 person 转换成表示个人信息的行(或称为元组和矢量)。


清单 2. SQL 矢量 UDF 示例
				
 CREATE TYPE employee AS ( 
        employer VARCHAR(20), 
        salary INT, 
        name VARCHAR(20), 
        gender VARCHAR(6), 
        length INT, 
        weight INT) 
        MODE DB2SQL; 

 CREATE FUNCTION getPersonals(person EMPLOYEE) 
     RETURNS ROW (name VARCHAR(20), gender VARCHAR(6), length INT, weight INT) 
     LANGUAGE SQL 
     CONTAINS SQL 
     NO EXTERNAL ACTION 
     DETERMINISTIC 
     RETURN VALUES (person..name, person..gender, person..length, person..weight);

表函数:顾名思义,SQL UDF 的返回值是一张数据表,或二维矩阵。它可以用在 SELECT 语句的 FROM 之后,即在数据表可以引用的地方都可以使用表函数,只是需要将表函数包装在 TABLE 函数中。清单 3 所示的是一个表函数及其调用,该函数从表 employee 中返回所有工作部门 department 与输入参数 deptNo 一致的员工信息,包含每个员工的 empNo、name 和 salary 构成的多行记录的返回值就是一张数据表。


清单 3. SQL 表函数 UDF 示例
				
 CREATE TABLE audit_table(user VARCHAR(20), operation VARCHAR(20), 
      object VARCHAR(50), optime TIME)@ 

 CREATE TABLE employee(empNo CHAR(10), name VARCHAR(20), salary INT, 
 department CHAR(10), manager CHAR(10))@ 

 CREATE FUNCTION getEmpByDept(deptNo CHAR(10)) 
     RETURNS TABLE (empNo   CHAR(10), 
                       name    VARCHAR(20), 
                       salary INT) 
     LANGUAGE SQL 
     MODIFIES SQL DATA 
     NO EXTERNAL ACTION 
     DETERMINISTIC 
     BEGIN ATOMIC 
       INSERT INTO audit_table(user, operation, object, optime) 
       VALUES (CURRENT USER, 'SELECT', 'Table: employee', CURRENT TIME); 
       RETURN 
         SELECT empNo, name, salary 
           FROM employee 
           WHERE employee.department = deptNo; 
 END@ 

 SELECT * FROM TABLE(getEmpByDept('DEP000-001'))@

有源 / 模板函数:这是一类特殊的函数,是在数据库中现有函数基础上构造出来的,其本质可以是标量、矢量或表函数。在调用这类函数时,输入参数被转换为底层源函数所需的参数类型,然后执行源函数本身,源函数对执行得到的结果进行必要的转换,返回给调用有源 / 模板函数的 SQL。清单 4 是一个简单的有源函数,AGE 是基于内置数据类型 INTEGER 创建的新的数据类型,如果需要对 AGE 求平均值,那么就可以基于内置聚合函数 AVG(INTEGER)创建有源函数 AVG(AGE),而不需要编写实现细节的逻辑。有源函数接受并返回 AGE 类型的值。


清单 4. 简单有源函数示例
				
 CREATE TYPE AGE AS INTEGER WITH COMPARISONS;
 CREATE FUNCTION AVG(AGE) RETURNS AGE SOURCE SYSIBM.AVG(INTEGER);

SQL 内联型函数:在包括 DB2 v9.5 以前的版本中,SQL UDF 函数体内的 SQL 复合语句是在 UDF 被调用时内联(inline)展开的,概念上与 C++ 语言中的内联函数相似,这种 UDF 被称为 SQL 内联型函数。SQL 语句中的函数调用部分,在执行时被展开成实际的函数逻辑。清单 1-3 创建的 UDF 实际上都是 SQL 内联函数。其中 SQL 复合语句包含在“BEGIN ATOMIC”和“END”之间。

SQL 编译型函数:在 DB2 v9.7 中,引入了一种新的 SQL UDF,它支持输出(OUT)和输入输出(INOUT)模式的参数,在其函数体中的复合 SQL 语句,在创建函数时被编译,并将编译得到的字节码存储到系统编目(catalog)中。这种函数被称为编译型 UDF。与内联型 UDF 想对应,在 SQL 编译型 UDF 创建命令中,所包含的复合 SQL 语句被嵌入在“BEGIN”和“END”之间,如清单 5 所示。


清单 5. SQL 编译型 UDF
				
 CREATE FUNCTION increment( 
  INOUT result INTEGER, 
  IN delta INTEGER) 
 RETURNS INTEGER 
 BEGIN 
  DECLARE code INTEGER DEFAULT 0; 
  DECLARE SQLCODE INTEGER; 
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN 
    SET code = SQLCODE; 
    RETURN code; 
  END; 
  SET result = result + delta; 
  RETURN code; 
 END@

目前,SQL 编译型 UDF 只能用来定义标量函数,只有在定义标量函数的编译型 UDF 中才能使用 OUT 和 INOUT 参数。

DB2 pureXML 概要回顾

DB2 v9 引入了 pureXML 特性,使得 DB2 对 XML 数据的管理日臻完美。简单地说,DB2 支持了一种新的数据类型 XML,它可以像 INT、CHAR 一样在创建表中使用,如清单 6 所示。


清单 6. 使用 XML 类型创建数据表
				
 db2 "create table customer(cid int, doc xml)"
 DB20000I  The SQL command completed successfully.

数据表建立后,可以使用 INSERT 语句将 XML 数据保存到表中,参见清单 7.


清单 7. 保存 XML 数据
				
 insert into customer values(1002, 
'<customerinfo><name>charles</name><phone>66668888</phone></customerinfo>') 
 DB20000I  The SQL command completed successfully. 

 insert into customer values(1004, 
'<customerinfo><name>Matthias</name><phone type="office">6565-8888</phone><phone 
 type="home">9999-6666</phone></customerinfo>') 
 DB20000I  The SQL command completed successfully.

然后,可以使用普通的 SELECT 语句查询获取整个 XML 文档,也可以通过 SQL/XML 或 XQuery 语句查询 XML 的片段或节点信息。更多 pureXML 的相关内容,请查阅 DB2 InfoCenter。

在 SQL UDF 中使用 XML

1. 内联型 UDF 对 XML 的支持

从 DB2 v9.7 开始,SQL 内联型 UDF 完全支持 XML。用户可以在 UDF 中像使用其他简单的内置数据类型一样使用 XML 数据类型。XML 可用作函数的参数数据类型,也可用作函数的返回数据类型,还可以是函数内部的局部变量。XML 变量可以传递给 XQuery/XPATH 表达式、XMLQUERY 和 XMLTABLE 等 SQL/XML 函数,也可以传递给 XMLEXISTS 谓词。而这些支持 XML 的 SQL 内联 UDF,可以是标量函数、矢量函数或表函数。

清单 8 中创建了一个 SQL 标量函数 getname,并在 SELECT 语句中调用该函数,得到查询结果。在函数中,输入参数为 XML 类型,并传入 XMLQUERY 函数中的 XPATH 表达式。调用函数 getname 是 SQL 所使用的表以及表中数据以清单 6 和清单 7 为基础。


清单 8. 使用 XML 参数的 SQL 标量函数
				
 CREATE FUNCTION getname(doc XML) 
 RETURNS VARCHAR(25) 
 BEGIN ATOMIC 
  RETURN XMLCAST(XMLQUERY('$d/customerinfo/name'
                           PASSING doc AS "d") 
             AS VARCHAR(25)); 
 END 
 DB20000I  The SQL command completed successfully. 

 SELECT getname(doc) AS name FROM customer WHERE cid = 1002 

 NAME 
 ------------------------- 
 charles 

  1 record(s) selected.

清单 9 是一个 SQL 表函数,其调用运行结果同样是基于清单 6 和清单 7 创建的表和数据。输入参数为 XML 类型,并传递到在 XMLTABLE 中,实现 XML 到关系表的转化。


清单 9. 使用 XML 参数的 SQL 表函数
				
 CREATE FUNCTION getphone(doc XML) 
 RETURNS TABLE(type VARCHAR(10), number VARCHAR(20)) 
 BEGIN ATOMIC 
  RETURN 
    SELECT type, number 
    FROM XMLTABLE('$d/customerinfo/phone' PASSING doc AS "d"
           COLUMNS 
              type   VARCHAR(10)  PATH '@type', 
              number VARCHAR(20)  PATH '.') ; 
 END 
 DB20000I  The SQL command completed successfully. 

 SELECT cid, p.type, p.number FROM customer, TABLE(getphone(doc)) p WHERE cid = 1004 

 CID         TYPE       NUMBER 
 ----------- ---------- -------------------- 
       1004 office     6565-8888 
       1004 home       9999-6666 

  2 record(s) selected.

实际上,不仅输入参数可以是 XML 类型的,返回值也可以是 XML 类型的,清单 10 创建了一个返回 XML 的函数,使用输入参数 id,name 和 phone 构建一个根元素为 customer 的 XML 文档,customer 元素包含属性 id,子元素 name 和 phone。如果 id,name 和 phone 是关系表中的列,如清单 10 中的表 my_customer,那么函数 customer_xml 则是将关系型的数据转换为 XML 信息,而这种转换是通过 XMLELEMENT 、XMLATTRIBUTES 等 XML 公布函数(XML Publishing Functions)实现的。XML 公布函数与清单 9 中的 XMLTABLE 共同搭起 XML 与关系型数据之间的桥梁,用户通过这些函数,很容易实现 XML 数据转化为关系型信息或者关系型转换为 XML。清单 10 同时显示了表 my_customer 被填充记录后,函数 customer_xml 运行的结果,即返回的 XML 数据。


清单 10. 返回 XML 的 SQL 标量函数
				
 CREATE FUNCTION customer_xml_info( id    INT, 
                                   name  VARCHAR(20), 
                                   phone VARCHAR(20) ) 
 RETURNS XML 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN ATOMIC 
 RETURN XMLELEMENT (NAME "customer", 
 XMLATTRIBUTES(id), 
 XMLELEMENT (NAME "name", name), 
 XMLELEMENT (NAME "phone", phone) 
 OPTION NULL ON NULL); 
 END 
 DB20000I  The SQL command completed successfully. 

 CREATE TABLE my_customer(id INT, name  VARCHAR(20), phone VARCHAR(20) ) 
 DB20000I  The SQL command completed successfully. 

 INSERT INTO my_customer values(1, 'csliu', '010-6666'), (2, 'charles', '021-8888') 
 DB20000I  The SQL command completed successfully. 

 SELECT customer_xml_info(id, name, phone) AS customer FROM my_customer 

 CUSTOMER                                                                    
 ------------------------------------------------ 
 <customer ID="1"><name>csliu</name><phone>010-6666</phone></customer> 
 <customer ID="2"><name>charles</name><phone>021-8888</phone></customer> 

  2 record(s) selected.

我们不仅可以使用 XML 作为变量函数的返回值,也可以在表函数中使用 XML 作为返回值的一部分,即返回表中可以含有 XML 列。清单 11 中,我们改写了清单 3 中的表函数,在返回信息中,包含字符型的 empNo 和 XML 类型的 empInfo。empInfo 列的 XML 文档中包含重要的员工信息,如 empNo、name 和 salary,其中 empNo 为根元素 employee 的属性,name 和 salary 是 employee 的两个子元素。函数调用后的运行结果也显示在清单 11 中。


清单 11. 返回含 XML 的 SQL 表函数
				
 CREATE FUNCTION getEmpXMLByDept(deptNo CHAR(10)) 
     RETURNS TABLE (empNo   CHAR(10), 
                       empInfo XML) 
     LANGUAGE SQL 
     MODIFIES SQL DATA 
     NO EXTERNAL ACTION 
     DETERMINISTIC 
     BEGIN ATOMIC 
       INSERT INTO audit_table(user, operation, object, optime) 
       VALUES (CURRENT USER, 'SELECT', 'Table: employee', CURRENT TIME); 
       RETURN 
         SELECT empNo, 
                XMLELEMENT (NAME "employee", 
                  XMLATTRIBUTES(empNo), 
                  XMLELEMENT (NAME "name", name), 
                  XMLELEMENT (NAME "salary", salary) 
                OPTION NULL ON NULL) 
         FROM employee 
         WHERE employee.department = deptNo; 
 END 
 DB20000I  The SQL command completed successfully. 

 insert into employee values('EMP000-001', 'Charles Lauye', 
 5000, 'DEP000-001', 'MGR000-001') 
 DB20000I  The SQL command completed successfully. 

 SELECT * FROM TABLE(getEmpXMLByDept('DEP000-001')) 
 EMPNO      EMPINFO 
 ------------------------------------- 
 EMP000-001 <employee EMPNO="EMP000-001"><name>Charles Lauye 
           </name><salary>5000</salary></employee> 

  1 record(s) selected.

XML 可以被用作 SQL 函数的参数和返回数据类型,它们都是在函数的输入输出中,也就是在函数体的外部。那么在函数体内部可以使用 XML 吗?当然可以。在函数中我们可以声明并使用局部的 XML 变量,它可以用来保存函数中运算的中间结果等等。在清单 10 的基础上,将其中函数改写如清单 12,在函数中声明 XML 类型的局部变量 temp_customer,根据输入的 id 的值,构建不同的 XML,当 id 为正值时,创建的 XML 包含有效的输入信息,当 id 为非正值时,输入信息无效,XML 中相应的属性和元素值为空。


清单 12. 函数中使用 XML 局部变量
				
 CREATE FUNCTION valid_customer_xml_info( id    INT, 
                                   name  VARCHAR(20), 
                                   phone VARCHAR(20) ) 
 RETURNS XML 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN ATOMIC 
 DECLARE temp_customer XML; 
 IF id <= 0 THEN 
 SET temp_customer = XMLELEMENT (NAME "customer", 
 XMLATTRIBUTES('invalid' AS "status", '' as id), 
 XMLELEMENT (NAME "name", ''), 
 XMLELEMENT (NAME "phone", '')); 
 ELSE 
 SET temp_customer = XMLELEMENT (NAME "customer", 
 XMLATTRIBUTES('valid' AS "status", id as "id"), 
 XMLELEMENT (NAME "name", name), 
 XMLELEMENT (NAME "phone", phone)); 
 END IF; 
 RETURN temp_customer; 
 END 
 DB20000I  The SQL command completed successfully. 

 CREATE TABLE my_customer(id INT, name  VARCHAR(20), phone VARCHAR(20) ) 
 DB20000I  The SQL command completed successfully. 

 INSERT INTO my_customer values(1, 'csliu', '010-6666'), 
 (2, 'charles', '021-8888'), (-1, 'charnson', '025-1111') 
 DB20000I  The SQL command completed successfully. 

 SELECT valid_customer_xml_info(id, name, phone) AS customer FROM my_customer 

 CUSTOMER                                                                    
 ------------------------------------------------ 
 <customer status="valid" id="1"><name>csliu</name><phone>010-666666</phone></customer> 
 <customer status="valid" id="2"><name>charles</name><phone>021-888888</phone></customer> 
 <customer status="invalid" ID=""><name/><phone/></customer> 


  3 record(s) selected.

清单 8-12 中的 SQL 函数都是仅从一个侧面体现了 DB2 SQLUDF 对于 XML 的支持,分别从 XML 参数、XML 返回值和 XML 局部变量的角度展示了用户可以怎样在 DB2 SQL 函数中使用 XML。其实,在一个函数中,用户可以综合的使用 XML,即根据需要同时使用 XML 作为参数类型、返回类型和局部变量的类型或其部分组合。在清单 13 中,我们创建了一个同时使用 XML 作为参数、局部变量和返回类型的函数 phone_number。在该函数中,XML 类型的输入参数 doc 传递给了 XMLQUERY 函数和 XMLEXISTS 谓词,局部变量 tmp_xml 用来保存 XMLQUERY 函数输出的 XML 值,并最终作为函数的返回值。函数调用的运行结果所依赖的数据同清单 8。


清单 13. 综合使用 XML 数据类型
				
 CREATE FUNCTION phone_number( doc XML ) 
 RETURNS XML 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN ATOMIC 
 DECLARE tmp_xml XML; 
 IF (XMLEXISTS('$test/customerinfo/phone' passing by ref doc as "test")) 
 THEN 
  SET tmp_xml = XMLQUERY('document 
       {<phone_list>{$doc/customerinfo/phone}</phone_list>}'
    PASSING doc as "doc"); 
 ELSE 
 SET tmp_xml = XMLPARSE(document '<phone_list><phone>N/A</phone></phone_list>'); 
 END IF; 
 RETURN tmp_xml; 
 END 
 DB20000I  The SQL command completed successfully. 

 SELECT phone_number(doc) AS phone_list FROM customer 

 PHONE_LIST 
 ------------------------------------------------------------------- 
 <phone_list><phone>66668888</phone></phone_list> 
 <phone_list><phone type="office">6565-8888</phone><phone type="home">9999 
 -6666</phone></phone_list> 

  2 record(s) selected.

2. 编译型 UDF 对 XML 的支持

在 SQL 编译型 UDF 中,参数可以是 IN、OUT 和 IOUT 类型。与 SQL 内联型 UDF 相似,考察 SQL 编译型 UDF 中函数输入输出参数、返回类型和函数内局部变量使用 XML 数据类型的支持情况。

清单 14 中,试图使用 XML 作为 IN、OUT 和 IOUT 类型的参数创建 SQL 编译型函数,不幸的是,DB2 返回了错误 SQL0789N,表明 SQL 编译型 UDF 的参数尚不支持 XML 数据类型。


清单 14. 函数参数不支持 XML 类型
				
 --use xml as the input parameter 
 CREATE FUNCTION getname_compiled(doc XML) 
 RETURNS VARCHAR(25) 
 BEGIN 
  RETURN XMLCAST(XMLQUERY('$d/customerinfo/name'
          PASSING doc AS "d")AS VARCHAR(25)); 
 END 
 DB21034E  The command was processed as an SQL statement because it was not a valid
Command Line Processor command.  During SQL processing it returned: 
 SQL0789N  The data type for parameter or SQL variable "DOC" is not supported 
 in the routine, compound SQL statement, or parameter list of a cursor value constructor. 
 LINE NUMBER=2.  SQLSTATE=429BB 

 --use xml as the output parameter 
 CREATE FUNCTION xml_of_phone(IN phoneNo VARCHAR(20), 
                                   IN regionNo VARCHAR(8), 
                                   OUT full_phone_xml XML) 
 RETURNS VARCHAR(28) 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN 
 SET full_phone_xml = XMLELEMENT (NAME "phone", regionNo || phoneNo); 
 RETURN regionNo || phoneNo; 
 END 
 DB21034E  The command was processed as an SQL statement because it was not a valid 
 Command Line Processor command.  During SQL processing it returned: 
 SQL0789N  The data type for parameter or SQL variable "FULL_PHONE_XML" is not supported
 in the routine,compound SQL statement,or parameter list of a cursor value constructor.
 LINE NUMBER=4.  SQLSTATE=429BB 

 --use xml as the input/output parameter 
 CREATE FUNCTION xml_of_phone(IN regionNo VARCHAR(8), 
                                   INOUT phone_xml XML) 
 RETURNS VARCHAR(28) 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN 
 DECLARE tmp_full_phone VARCHAR(28); 
 SET tmp_full_phone = regionNo || XMLCAST(XMLQUERY('$p/phone'
                         PASSING phone_xml AS "p") AS VARCHAR(20)); 
 SET phone_xml = XMLELEMENT (NAME "phone", tmp_full_phone); 
 RETURN tmp_full_phone; 
 END 
 DB21034E  The command was processed as an SQL statement because it was not a valid
 Command Line Processor command.  During SQL processing it returned: 
 SQL0789N  The data type for parameter or SQL variable "PHONE_XML" is not supported in the
 routine, compound SQL statement, or parameter list of a cursor value constructor.  
 LINE NUMBER=3.  SQLSTATE=429BB

清单 15 中的函数使用 XML 作为返回的数据类型,清单 16 中的函数内部声明了一个 XML 类型的局部变量,与清单 14 类似,这些特性也尚未得到支持。


清单 15. 函数返回类型不支持 XML
				
 CREATE FUNCTION xml_of_phone( phone VARCHAR(20) ) 
 RETURNS XML 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN 
 RETURN XMLELEMENT (NAME "phone", phone); 
 END 
 DB21034E  The command was processed as an SQL statement because it was not a valid 
 Command Line Processor command.  During SQL processing it returned: 
 SQL0789N  The data type for parameter or SQL variable "RETURNS" is not supported in the 
 routine, compound SQL statement, or parameter list of a cursor value constructor.  
 LINE NUMBER=2.  SQLSTATE=429BB


清单 16. 局部变量不支持 XML 类型
				
 CREATE FUNCTION xml_of_phone( phone VARCHAR(20) ) 
 RETURNS VARCHAR(28) 
 LANGUAGE SQL 
 NO EXTERNAL ACTION 
 BEGIN 
 DECLARE tmp_xml XML; 
 SET tmp_xml = XMLELEMENT (NAME "phone", phone); 
 RETURN '010' || phone; 
 END 
 DB21034E  The command was processed as an SQL statement because it was not a valid 
 Command Line Processor command.  During SQL processing it returned: 
 SQL0789N  The data type for parameter or SQL variable "TMP_XML" is not supported in the 
 routine, compound SQL statement, or parameter list of a cursor value constructor.  
 LINE NUMBER=6.  SQLSTATE=429BB

总结

本文梳理了 DB2 SQL 用户定义函数 UDF 的基本知识,并在简单回顾 pureXML 特性的基础上,结合实例考察了 SQL UDF 对 XML 的支持情况。在 SQL 内联型 UDF 中,对 XML 类型的支持是全面的。用户可以使用 XML 类型的输入参数,函数可以返回 XML 类型,也可以在函数内声明 XML 类型的局部变量,而这些 UDF 可以是标量函数、矢量函数和表函数。但是在 SQL 编译型 UDF 中,XML 的支持还没有得到支持,不论是函数 IN/OUT/INOUT 参数、返回类型,还是函数内局部变量。本文所有示例都是在 DB2 v9.7fixpack4 上运行的,在 DB2 以后的版本中,SQL 编译型 UDF 对 XML 的支持应该会得到增强和完善。


参考资料

学习

获得产品和技术

讨论

关于作者

刘长生的照片

刘长生,IBM CDL软件工程师,具有多年软件开发经验,曾从事组件库技术的研究,目前从事 DB2 pureXML 相关的开发工作。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management, XML
ArticleID=790181
ArticleTitle=在 DB2 SQL 函数中使用 XML
publish-date=01302012

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。