在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?
答案 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.