如何调用db2函数并让它返回多个xml记录数据?

时间:2013-05-29 15:20:30

标签: sql xml db2

在SQL中,我需要创建如下所示的xml代码:

    <Phone>
       <PhoneTypeCode tc="12">Mobile</PhoneTypeCode>
       <Area>801</Area>
       <DialNumber>9996666</DialNumber>
    </Phone>
    <Phone>
       <PhoneTypeCode tc="2">Business</PhoneTypeCode>
       <Area>801</Area>
       <DialNumber>1113333</DialNumber>
    </Phone>

当我运行这个sql时,我正确地获得了两行数据,正如我所期望的那样:

select
  xmlelement( 
     Name "Phone", 
     xmlelement( 
       name "PhoneTypeCode", 
       xmlattributes( 
         trim(p1.phtype) as "tc" 
       ), 
       trim(p1.desc) 
     ), 
     xmlelement(name "AreaCode", p1.area), 
     xmlelement(name "DialNumber", p1.phone)                   
  ) as xml 
from phone as p1 where p1.entityid = 256285;

这是我收到的两行数据,完全符合我的预期:

    <Phone><PhoneTypeCode tc="12">Mobile</PhoneTypeCode><AreaCode>351</AreaCode>       <DialNumber>4443333</DialNumber></Phone> 

    <Phone><PhoneTypeCode tc="2">Business</PhoneTypeCode><AreaCode>351</AreaCode><DialNumber>3911111</DialNumber></Phone>

但是,当我尝试在函数中放入相同的代码并调用此函数时,我收到此错误:

SQL状态:21000 供应商代码:-811 消息:[SQL0811] SELECT多行的结果。原因。 。 。 。 。 :SELECT INTO语句的结果表,子查询或SET语句的子选择包含多行。错误类型为2.如果错误类型为1,则SELECT INTO语句尝试返回多行。如果错误类型为2,则基本谓词的子选择产生多个行。只允许一行。恢复。 。 。 :更改选择,以便只返回一个结果行,然后再次尝试请求。必须使用DECLARE CURSOR,OPEN和FETCH语句来处理多个结果行。对于子查询,IN,EXISTS,ANY或ALL谓词可用于处理多个结果行。如果预期有一行,则可能存在导致返回多行的数据错误(例如重复行)。

**如何修复此函数,以便它将所有数据行作为我期望的xml代码块返回?

    CREATE or replace FUNCTION xml_entity_phones ( 
    #Entity_ID bigint) 
    RETURNS xml 

    LANGUAGE SQL 
    NOT DETERMINISTIC 
    reads SQL DATA 
    RETURNS NULL ON NULL INPUT 
    NO EXTERNAL ACTION 
    ALLOW PARALLEL 
    NOT FENCED 

    begin 
    return ( 
    select 
        xmlelement( 
          Name "Phone", 
          xmlelement( 
            name "PhoneTypeCode", 
            xmlattributes( 
              trim(p.phtype) as "tc" 
            ), 
            trim(p.desc) 
          ), 
          xmlelement(name "AreaCode", p.area), 
          xmlelement(name "DialNumber", p.phone)                   
        ) as xml 
    from phone p where p.entityid = #entity_id 
    ); 
    end 
    ;

调用此函数的过程是构建一个包含不同类型电话的xml文件,我想用上述函数构建它。

最终目标是拥有一个xml文档(有效与否),如下所示:

    <TXLife>
       <TXLifeRequest>
          <OLife>
             <Person>
                <Phone>
                   <PhoneTypeCode tc="12">Mobile...
                   <Area...
                   <DialNumber...
                </Phone>
                <Phone>
                   <PhoneTypeCode tc="2">Business...
                   <Area...
                   <DialNumber...
                </Phone> 
                ...

我希望用函数调用构建整个手机部分xml:xml_entity_phones(bigint(e.entityid))。


好的,我用xmlagg()改变了这个函数:

begin               
    return (
        select
            xmlagg(
                xmlelement(
                    Name "Phone", 
                    xmlelement(
                        name "PhoneTypeCode", 
                        xmlattributes(
                        trim(p.phtype) as "tc"
                        ), 
                    trim(p.desc)
                    ),
                xmlelement(name "AreaCode", p.area),
                xmlelement(name "DialNumber", p.phone)                   
                )
            ) as xml
        from phone p 
        where p.entityid = #entity_id   
    );
end

但是现在当我用值(xml_entity_phones(256285));来调用函数时,我得到+++++++++++++++++++++++当我调用调用此函数的过程时,我收到此错误:

SQL状态:22023 供应商代码:-802 消息:[SQL0802]数据转换或数据映射错误。原因。 。 。 。 。 :错误类型10已发生10 - 用户定义的函数返回映射错误。

我注意到当我在下面的几个答案中建议使用xmlagg添加一个额外的Phones元素时,它确实成功返回了xmlagg()结果。但是我不能拥有Phones的额外元素,因为它违背了我需要遵守的标准。

有没有办法在没有额外图层的情况下返回xmlagg?

2 个答案:

答案 0 :(得分:0)

当您发出SQL select时,您正在检索结果集(以某种方式检索游标)。你拥有的不是XML,它是一个有两个XML文档或两行的结果集。 XML文档只有一个父文件,这里有两个父母(电话)

您可以通过存储过程检索类似于您的光标。

create procedure x ()
P1:BEGIN
DECLARE cursor1 CURSOR WITH RETURN TO CLIENT FOR
  xmlelement( 
     Name "Phone", 
     ...
     xmlelement(name "DialNumber", p1.phone)                   
  ) as xml 
  from phone as p1 where p1.entityid = 256285;
open cursor1;
END P1;

答案 1 :(得分:0)

这是您使用XMLAGG()的地方:

begin 
return ( 
select 
    xmlelement(name "Phones", xmlagg(
    xmlelement( 
      Name "Phone", 
      xmlelement( 
        name "PhoneTypeCode", 
        xmlattributes( 
          trim(p.phtype) as "tc" 
        ), 
        trim(p.desc) 
      ), 
      xmlelement(name "AreaCode", p.area), 
      xmlelement(name "DialNumber", p.phone)                   
    )
   )) as xml 
from phone p where p.entityid = #entity_id 
); 
end 

显然,我没有您的数据,但这个简单的例子表明该方法有效:

$ db2 "create or replace function t () returns xml language sql begin \
return (select xmlagg(xmlelement(name \"tab\", tabname )) from syscat.tables \
where tabname like '%AUTH%' and tabschema = 'SYSCAT'); end"
DB20000I  The SQL command completed successfully.
$ db2 "values t()"

1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
----------------------------------------------------------------------------
<tab>COLAUTH</tab><tab>DBAUTH</tab><tab>INDEXAUTH</tab><tab>LIBRARYAUTH</tab>
<tab>MODULEAUTH</tab><tab>PACKAGEAUTH</tab><tab>PASSTHRUAUTH</tab><tab>ROLEAUTH
</tab><tab>ROUTINEAUTH</tab><tab>SCHEMAAUTH</tab><tab>SEQUENCEAUTH</tab>tab>
SURROGATEAUTHIDS    </tab><tab>TABAUTH</tab><tab>TBSPACEAUTH</tab><tab>
VARIABLEAUTH</tab><tab>WORKLOADAUTH</tab><tab>XSROBJECTAUTH</tab>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

  1 record(s) selected.