0

在 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

但是现在当我用 values(xml_entity_phones(256285)); 调用函数时,我得到 ++++++++++++++++。当我调用调用这个函数的过程时,我得到这个错误:

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

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

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

4

2 回答 2

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.
于 2013-05-29T15:51:07.343 回答
0

当您发出 SQL 选择时,您正在检索结果集(以某种方式是游标)。您所拥有的不是 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;
于 2013-05-29T15:49:32.010 回答