2013-05-29 2 views
0

В SQL, мне нужно создать XML-код, который выглядит следующим образом:Как я могу вызвать функцию db2 и вернуть ей несколько данных записи 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 State: 22023 Vendor Код: -802 Сообщение: [SQL0802] преобразования данных или данных об ошибке отображения. Причина. , , , , : Возникла ошибка типа 10. 10 - Пользовательская функция вернула ошибку сопоставления.

Я заметил, что когда я включаю дополнительный элемент телефонов, использующий xmlagg, как предлагается в нескольких ответах ниже, он возвращает результат xmlagg(). Однако у меня не может быть этого дополнительного элемента телефонов, потому что он противоречит стандарту, которому я должен придерживаться.

Есть ли способ вернуть xmlagg без дополнительного слоя?

ответ

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. 
+0

Это то, на что я надеялся, но стандарт, заданный вызывающей процедурой (который действительно создает большой XML-документ, который включает телефоны, которые Я надеялся построить с этой функцией) не позволяет мне использовать родителя, такого как «Телефоны». Он должен быть в таком формате: – user2414410

+0

Вы можете просто опустить внешний XMLELEMENT(), чтобы получить фрагмент XML, содержащий последовательность элементов телефона, хотя это не будет действительным XML-документом. – mustaccio

+0

Я отредактирую свой исходный вопрос с требуемым форматом, но есть ли способ объединить несколько строк в один оператор xml внутри функции? – user2414410

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; 
+0

A функция не может получить ResultSet. Однако вы можете создать функцию таблицы, которая извлекает вид таблицы, но только с помощью хранимой процедуры вы можете делать то, что хотите. – AngocA

+0

Или объединить два XML-документа в onem с общим родителем, например «телефоны» – AngocA

Смежные вопросы