Home » SQL & PL/SQL » SQL & PL/SQL » Creating boundaries in between xml elements (Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production)
Creating boundaries in between xml elements [message #632267] Wed, 28 January 2015 09:06 Go to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Taking 'EMP' table as an example, I have a requirement to generate xml file.
Please check the code below for the expected result. I should have those boundaries in between every employee and also I should identify the content length of every employee xmldata.
My question is, can i achieve this using a single query(which will be ideal for my performance) or should I only use cursor? (which will impact a lot on performance)


--sql query
select xmlagg(xmlconcat(xmlelement("empno",empno), xmlelement("ename",ename))) 
from scott.emp where rownum<3;
--result
<empno>7369</empno><ename>SMITH</ename><empno>7499</empno><ename>ALLEN</ename>


--Expected Result

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7499@xx.com
Content-Length: 78

<?xml version="1.0" encoding="UTF-8"?>
<empno>7369</empno><ename>SMITH</ename>

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7499@xx.com
Content-Length: 78

<?xml version="1.0" encoding="UTF-8"?>
<empno>7499</empno><ename>ALLEN</ename>

--yytet00pubSubBoundary00tetyy



Please help.
Re: Creating boundaries in between xml elements [message #632268 is a reply to message #632267] Wed, 28 January 2015 09:16 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
is the boundary and oontent_id always the same?
Re: Creating boundaries in between xml elements [message #632269 is a reply to message #632268] Wed, 28 January 2015 09:18 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Boundary is always the same, but content id is actually dependent on employee id and content length is the length of the each employee xmldata.
Re: Creating boundaries in between xml elements [message #632276 is a reply to message #632269] Wed, 28 January 2015 10:07 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
Sounds like you need to wrap the xml query in an outer select that concatenates the xml string to the boundary, content id and content length (just use length function).
Seems very straight forwards.
Re: Creating boundaries in between xml elements [message #632277 is a reply to message #632276] Wed, 28 January 2015 10:18 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Yes you are right cookiemonster. But is there any way I can get this from single sql query?
Re: Creating boundaries in between xml elements [message #632279 is a reply to message #632277] Wed, 28 January 2015 10:29 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

SQL> set sqlblanklines on
SQL> with 
  2    lines as (
  3      select '
  4  --yytet00pubSubBoundary00tetyy
  5  Content-ID: xx.#ID@xx.com
  6  Content-Length: #LG
  7  
  8  <?xml version="1.0" encoding="UTF-8"?>
  9  ' lines
 10      from dual
 11    )
 12  select replace(replace(lines, '#ID', empno), '#LG', length(empdata))||empdata res
 13  from lines, 
 14        (select empno, xmlconcat(xmlelement("empno",empno), xmlelement("ename",ename)) empdata
 15         from emp
 16         where rownum < 3)
 17  /
RES
-------------------------------------------------------------------------------------------------

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7369@xx.com
Content-Length: 39

<?xml version="1.0" encoding="UTF-8"?>
<empno>7369</empno><ename>SMITH</ename>

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7499@xx.com
Content-Length: 39

<?xml version="1.0" encoding="UTF-8"?>
<empno>7499</empno><ename>ALLEN</ename>

2 rows selected.

Re: Creating boundaries in between xml elements [message #632281 is a reply to message #632279] Wed, 28 January 2015 10:39 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Thanks a lot Michel Cadot. That is perfect result.
As I am using this sql query in a procedure, I want this whole data in single clob variable.Can I run this in plsql procedure inserting into a clob variable or xmltype variable?
Re: Creating boundaries in between xml elements [message #632283 is a reply to message #632281] Wed, 28 January 2015 10:44 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
You can use this to get a CLOB with all the rows:
SQL> with
  2    lines as (
  3      select '
  4  --yytet00pubSubBoundary00tetyy
  5  Content-ID: xx.#ID@xx.com
  6  Content-Length: #LG
  7
  8  <?xml version="1.0" encoding="UTF-8"?>
  9  ' lines
 10      from dual
 11    )
 12  select listagg(to_clob(replace(replace(lines, '#ID', empno), '#LG', length(empdata))||empdata))
 13            within group (order by empno) res
 14  from lines,
 15        (select empno, xmlconcat(xmlelement("empno",empno), xmlelement("ename",ename)) empdata
 16         from emp
 17         where rownum < 3)
 18  /
RES
-----------------------------------------------------------------------------------------------------

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7369@xx.com
Content-Length: 39

<?xml version="1.0" encoding="UTF-8"?>
<empno>7369</empno><ename>SMITH</ename>
--yytet00pubSubBoundary00tetyy
Content-ID: xx.7499@xx.com
Content-Length: 39

<?xml version="1.0" encoding="UTF-8"?>
<empno>7499</empno><ename>ALLEN</ename>

1 row selected.

Re: Creating boundaries in between xml elements [message #632284 is a reply to message #632283] Wed, 28 January 2015 11:00 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
However,

<?xml version="1.0" encoding="UTF-8"?>
<empno>7499</empno><ename>ALLEN</ename>

isn't a well-formed xml.

SY.
Re: Creating boundaries in between xml elements [message #632289 is a reply to message #632284] Wed, 28 January 2015 11:32 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Hi Solomon Yakobson,

It was just an example I mentioned in my question. You can consider it as follows

<?xml version="1.0" encoding="UTF-8"?>
<main>
<empno>7499</empno><ename>ALLEN</ename>
</main>

Thanks,
Manu
Re: Creating boundaries in between xml elements [message #632290 is a reply to message #632289] Wed, 28 January 2015 11:54 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Like:
SQL> set sqlblanklines on
SQL> with
  2    lines as (
  3      select '
  4  --yytet00pubSubBoundary00tetyy
  5  Content-ID: xx.#ID@xx.com
  6  Content-Length: #LG
  7
  8  <?xml version="1.0" encoding="UTF-8"?>
  9  ' lines
 10      from dual
 11    )
 12  select listagg(to_clob(replace(replace(lines, '#ID', empno), '#LG', length(empdata))||empdata),'
 13                 ') within group (order by empno) res
 14  from lines,
 15        (select empno,
 16                xmlelement("employee",xmlconcat(xmlelement("empno",empno), xmlelement("ename",ename))) empdata
 17         from emp
 18         where rownum < 3)
 19  /
RES
-----------------------------------------------------------------------------------------------------------------

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7369@xx.com
Content-Length: 60

<?xml version="1.0" encoding="UTF-8"?>
<employee><empno>7369</empno><ename>SMITH</ename></employee>

--yytet00pubSubBoundary00tetyy
Content-ID: xx.7499@xx.com
Content-Length: 60

<?xml version="1.0" encoding="UTF-8"?>
<employee><empno>7499</empno><ename>ALLEN</ename></employee>

1 row selected.

Re: Creating boundaries in between xml elements [message #632293 is a reply to message #632289] Wed, 28 January 2015 13:09 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Thanks Michael.
When I use that query with a huge record of employee data, I am facing ORA-19011 issue.

[Updated on: Wed, 28 January 2015 13:10]

Report message to a moderator

Re: Creating boundaries in between xml elements [message #632294 is a reply to message #632293] Wed, 28 January 2015 13:16 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Please post the query.
And also, please, always post the complete error message, we don't know all of them by heart.

Re: Creating boundaries in between xml elements [message #632295 is a reply to message #632293] Wed, 28 January 2015 13:20 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
wantmannu wrote on Wed, 28 January 2015 11:09
Thanks Michael.
When I use that query with a huge record of employee data, I am facing ORA-19011 issue.



we don't know what you actually did.
we do know you did it wrong

19011, 00000, "Character string buffer too small" 
// *Cause:  The string result asked for is too big to return back
// *Action:  Get the result as a lob instead
Re: Creating boundaries in between xml elements [message #632296 is a reply to message #632294] Wed, 28 January 2015 13:24 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Sorry about that. The complete error message is
'ORA-19011: Character string buffer too small'. The code I am running is as follows. I have created a test table 'xx_test1c' with clob data column.


create table xx_test1c(xxml clob);
/
SET serveroutput ON;
/
DECLARE
  xxml CLOB;
BEGIN
  --set sqlblanklines on
WITH lines AS
  (SELECT '            

--yytet00pubSubBoundary00tetyy    
Content-ID: PIM.82.#ID@master.com    
Content-Type: application/x.xxl.pimdata+xml    
Content-Length: #LG      

<?xml version="1.0" encoding="UTF-8"?>    
' lines
  FROM dual
  )
SELECT listagg(to_clob(REPLACE(REPLACE(lines, '#ID',item_number), '#LG', LENGTH(proddata))
  ||proddata)) within GROUP (
ORDER BY item_number)
INTO xxml
FROM lines,
  (SELECT '10' item_number,
    xmlagg(xmlconcat(XMLELEMENT("SyncItemPrimaryAttribute", XMLELEMENT("ItemIdentification", XMLELEMENT("Identification", xmlforest(msiv.inventory_item_id AS "ItemID", msiv.organization_id AS "OrgID", orgdef.organization_code AS "OrgCode", orgdef.organization_name AS "OrgName", kfv.concatenated_segments AS "ItemNumber", msiv.description AS "Description") )), XMLELEMENT("ItemBase", XMLforest(mic.segment1 AS "Catalog", NULL AS "Spoke", NULL AS "PubSeqId", msiv.long_description AS "LongDescription", lc.element_number AS "LifeCycle", lp.element_number AS "LifeCyclePhase",msiv.approval_status AS "ApprovalStatus", msiv.inventory_item_status_code AS "Status", msiv.item_type AS "TypeCode", msiv.eng_item_flag AS "EngineeringItemFlag", msiv.primary_uom_code AS "BaseUOMCode", msiv.secondary_uom_code AS "SecondaryUOMCode", msiv.creation_date "CreationDate", msiv.last_update_date AS "LastUpdateDate" ))),
    (SELECT xmlagg(xmlconcat(XMLELEMENT("AttributeGroup",XMLELEMENT("ID",eag.attr_group_id),XMLELEMENT("Name",eag.attr_group_name) ,
      (SELECT xmlagg(XMLELEMENT("Attribute", XMLFOREST(attr_val.attribute_name AS "Name",DECODE(attr_val.data_type_code,'C',attr_val.attribute_char_value,'N',TO_CHAR (attr_val.attribute_number_value),'X',attr_val.attribute_date_value) AS "Value")))
      FROM ego_all_attr_base_v attr_val
      WHERE 1                   =1
      AND attr_val.extension_id = ems.extension_id
      )) ))
    FROM ego_attr_groups_v eag,
      ego_mtl_sy_items_ext_b ems
    WHERE ems.attr_group_id    = eag.attr_group_id
    AND eag.attr_group_type    = 'EGO_ITEMMGMT_GROUP'
    AND msiv.inventory_item_id = ems.inventory_item_id
    AND ems.organization_id    = MSIV.ORGANIZATION_ID
    ))) proddata
  FROM mtl_system_items_vl msiv,
    org_organization_definitions orgdef,
    mtl_system_items_b_kfv kfv,
    mtl_item_catalog_groups_b mic,
    pa_ego_lifecycles_v lc,
    pa_ego_phases_v lp
  WHERE msiv.inventory_item_id   = kfv.inventory_item_id
  AND msiv.item_catalog_group_id = mic.item_catalog_group_id
  AND msiv.lifecycle_id          = lc.proj_element_id
  AND Msiv.Current_Phase_Id      = Lp.Proj_Element_Id
  AND msiv.organization_id       = kfv.organization_id
  AND msiv.organization_id       = orgdef.organization_id
  AND MSIV.ORGANIZATION_ID       = 82
  AND rownum                     <20
  );
INSERT INTO xx_test1c VALUES
  (xxml
  ) ;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
  dbms_output.put_line(sqlerrm);
END;
Re: Creating boundaries in between xml elements [message #632297 is a reply to message #632296] Wed, 28 January 2015 13:25 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Try with "to_clob(proddata)".

Re: Creating boundaries in between xml elements [message #632299 is a reply to message #632297] Wed, 28 January 2015 13:30 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

same error using "to_clob(proddata)"
anonymous block completed
ORA-19011: Character string buffer too small

Is there a way I can replace to_clob with .getClobVal() in the above query you gave me Michel?
Re: Creating boundaries in between xml elements [message #632300 is a reply to message #632299] Wed, 28 January 2015 13:36 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Yes, try it.

Re: Creating boundaries in between xml elements [message #632301 is a reply to message #632300] Wed, 28 January 2015 14:38 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Using .getClobVal(), but I am facing below error . I am trying to use .getClobVal() in several other places, but still the same error .

ORA-06550: line 18, column 99:
PL/SQL: ORA-22806: not an object or REF

set serveroutput on;
/
declare
xxml clob;
begin
--set sqlblanklines on
with
  lines as (
  
        select '
        
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#ID@xx.com
    Content-Length: #LG
  
    <?xml version="1.0" encoding="UTF-8"?>
    ' lines
       from dual
     )
   select listagg((replace(replace(lines, '#ID', empno), '#LG', length(empdata))||empdata).getClobVal())
             within group (order by empno) res into xxml 
   from lines,
         (select empno, xmlelement("employee",xmlconcat(xmlelement("empno",empno), xmlelement("ename",ename))) empdata
          from scott.emp
          where rownum < 10);
          
insert into xx_test1c values(xxml) ;
commit;
  exception
  when others then dbms_output.put_line(sqlerrm);
  end;
/

Error report -
ORA-06550: line 18, column 92:
PL/SQL: ORA-22806: not an object or REF
ORA-06550: line 5, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
Re: Creating boundaries in between xml elements [message #632302 is a reply to message #632301] Wed, 28 January 2015 14:45 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Use getClobVal on xmlelement and let the to_clob on REPLACE.

Re: Creating boundaries in between xml elements [message #632303 is a reply to message #632302] Wed, 28 January 2015 14:58 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Hi Michel,

It works fine with scott.emp data using getClobVal on xmlelement and let the to_clob on REPLACE..
But when I keep getClobVal on xmlelement in actual Product data query, I get the following errror..

anonymous block completed
ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 5168, maximum: 4000)

anonymous block completed
ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 986295, maximum: 4000)


Re: Creating boundaries in between xml elements [message #632304 is a reply to message #632303] Wed, 28 January 2015 15:07 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

If you have not TO_CLOB on REPLACE it is a CHAR and so the result of concatenation is a CHAR which is limited to 4000.
Both operands must be a CLOB to have to CLOB as result and so can exceed 4000 bytes.

Re: Creating boundaries in between xml elements [message #632305 is a reply to message #632304] Wed, 28 January 2015 15:10 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Also do NOT use PL/SQL.
Just
INSERT INTO xx_test1c (<the query>);


Re: Creating boundaries in between xml elements [message #632307 is a reply to message #632305] Wed, 28 January 2015 15:25 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Reason I am using (Insert into Table) is to view the clob data.
Actually I want to send this clob data (in clob variable) directly to other system using UTL_HTTP.
In my end code I will not save this file in any table.
Re: Creating boundaries in between xml elements [message #632310 is a reply to message #632307] Wed, 28 January 2015 16:20 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Though I am using two clob values concatenated into a clob variable, system is treating it as a char(4000) limit.
I guess clob stores up-till 4gb of data.

My simplified code is..
SET serveroutput ON;
/
DECLARE
  xxml CLOB;
BEGIN
  --set sqlblanklines on
WITH lines AS
  (SELECT '            

--yytet00pubSubBoundary00tetyy    
Content-ID: xx.#ID@xx.com    
Content-Length: #LG      

<?xml version="1.0" encoding="UTF-8"?>    
' lines
  FROM dual
  )
SELECT listagg(to_clob(REPLACE(REPLACE(lines, '#ID', segment1), '#LG', LENGTH(proddata)))
  ||proddata) within GROUP (
ORDER BY segment1) res
INTO xxml
FROM lines,
  (SELECT segment1,
    xmlelement("products",xmlconcat(xmlelement("itemnumber",segment1), xmlelement("itemtype",item_type))).getClobVal() proddata
  FROM mtl_system_items_b
  WHERE rownum < 1000
  );
INSERT INTO xx_test1c VALUES
  (xxml
  ) ;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
  dbms_output.put_line(sqlerrm);
END;


And error after running this script is..
anonymous block completed
ORA-01489: result of string concatenation is too long
Re: Creating boundaries in between xml elements [message #632317 is a reply to message #632310] Wed, 28 January 2015 21:02 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Can someone please tell me, which part of the above script does the database consider as a string?
Re: Creating boundaries in between xml elements [message #632318 is a reply to message #632317] Wed, 28 January 2015 21:49 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
When all else fails, Read The Fine Manual
http://docs.oracle.com/database/121/SQLRF/functions100.htm#SQLRF30030

"The return data type is RAW if the measure column is RAW; otherwise the return value is VARCHAR2."
Re: Creating boundaries in between xml elements [message #632324 is a reply to message #632317] Thu, 29 January 2015 00:45 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

You can use T. Kyte's STRAGG function instead.

Re: Creating boundaries in between xml elements [message #632365 is a reply to message #632324] Thu, 29 January 2015 08:14 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Or just use recursive sub-query factoring:

with e as (
            select  empno,
                    xmlelement(
                               "employee",xmlconcat(
                                                    xmlelement("empno",empno),
                                                    xmlelement("ename",ename)
                                                   )
                              ).getclobval() empdata,
                    row_number() over(order by empno) rn,
                    count(*) over() cnt
              from  emp
           ),
     r(
       res,
       rn,
       cnt
      ) as (
             select  '
        
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#' || empno || '@xx.com
    Content-Length: ' || length(empdata) || '
  
    <?xml version="1.0" encoding="UTF-8"?>' || empdata res,
                     rn,
                     cnt
               from  e
               where rn = 1
            union all
             select  r.res || '
        
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#' || empno || '@xx.com
    Content-Length: ' || length(empdata) || '
  
    <?xml version="1.0" encoding="UTF-8"?>' || e.empdata res,
                     e.rn rn,
                     r.cnt cnr
               from  r,
                     e
               where e.rn = r.rn + 1
           )
select  res
  from  r
  where rn = cnt
/

RES
---------------------------------------------------------------------------------------------------------


    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7369@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7369</empno><ename>SMITH</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7499@xx.com
    Content-Length: 60

RES
---------------------------------------------------------------------------------------------------------

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7499</empno><ename>ALLEN</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7521@xx.com
    Content-Length: 59

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7521</empno><ename>WARD</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7566@xx.com

RES
---------------------------------------------------------------------------------------------------------
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7566</empno><ename>JONES</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7654@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7654</empno><ename>MARTIN</ename></employee>

    --yytet00pubSubBoundary00tetyy

RES
---------------------------------------------------------------------------------------------------------
    Content-ID: xx.#7698@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7698</empno><ename>BLAKE</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7782@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7782</empno><ename>CLARK</ename></employee>


RES
---------------------------------------------------------------------------------------------------------
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7788@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7788</empno><ename>SCOTT</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7839@xx.com
    Content-Length: 59

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7839</empno><ename>KING</ename></employee>

RES
---------------------------------------------------------------------------------------------------------

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7844@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7844</empno><ename>TURNER</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7876@xx.com
    Content-Length: 60


RES
---------------------------------------------------------------------------------------------------------
    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7876</empno><ename>ADAMS</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7900@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7900</empno><ename>JAMES</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7902@xx.com
    Content-Length: 59

RES
---------------------------------------------------------------------------------------------------------

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7902</empno><ename>FORD</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7934@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7934</empno><ename>MILLER</ename></employee>


SQL> 


SY.
Re: Creating boundaries in between xml elements [message #632367 is a reply to message #632365] Thu, 29 January 2015 08:42 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Hey SY, Great Solution!!
But I am looking for single query which will insert the whole data in clob variable, So that I can avoid cursors for better performance as I am dealing with atleast 100 to 400mb of xmldata.
Re: Creating boundaries in between xml elements [message #632370 is a reply to message #632367] Thu, 29 January 2015 08:48 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Thanks Michel. I will try to use STRAGG instead of LISTAGG. Hope it will go through Smile
Re: Creating boundaries in between xml elements [message #632371 is a reply to message #632370] Thu, 29 January 2015 08:58 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
Which is better?
a) working and "slow"
b) "fast" and throwing errors
Re: Creating boundaries in between xml elements [message #632375 is a reply to message #632371] Thu, 29 January 2015 09:28 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Hi BlackSwan,

I understand what you are saying.
But we already have a working and "slow" solution running in our production instance. I am looking for enhancing the existing solution with better performance.
Currently we are only able to send 2000 products every hour by using cursors. I want to increase this rate.

Just wanted to see if this works, I can able to send 1000 products in less than a minute.
I have XML ready, but these boundaries with content id and length are killing me Sad. Thats why I am asking for help.

Thanks,
Manu
Re: Creating boundaries in between xml elements [message #632376 is a reply to message #632375] Thu, 29 January 2015 09:40 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
XML is the antithesis of FAST.
You would be hard pressed to get more verbose than XML.
To me this is like tying your right wrist to your left ankle & asking how to run a fast Marathon.
XML was NEVER intended to be fast; just "flexible".

http://www.orafaq.com/forum/t/194115/
Re: Creating boundaries in between xml elements [message #632379 is a reply to message #632376] Thu, 29 January 2015 10:04 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Solution which Michel Cadot gave me, is like 1 inch close to Good and Fast Trifecta. The only issue I am facing is 'ORA-01489: result of string concatenation is too long'. If this is resolved, then its my dream come true(based on Trifecta middle dot).
SET serveroutput ON;
/
DECLARE
  xxml CLOB;
BEGIN
  --set sqlblanklines on
WITH lines AS
  (SELECT '            

--yytet00pubSubBoundary00tetyy    
Content-ID: xx.#ID@xx.com    
Content-Length: #LG      

<?xml version="1.0" encoding="UTF-8"?>    
' lines
  FROM dual
  )
SELECT listagg(to_clob(REPLACE(REPLACE(lines, '#ID', segment1), '#LG', LENGTH(proddata)))
  ||proddata) within GROUP (
ORDER BY segment1) res
INTO xxml
FROM lines,
  (SELECT segment1,
    xmlelement("products",xmlconcat(xmlelement("itemnumber",segment1), xmlelement("itemtype",item_type))).getClobVal() proddata
  FROM mtl_system_items_b
  WHERE rownum < 1000
  );
INSERT INTO xx_test1c VALUES
  (xxml
  ) ;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
  dbms_output.put_line(sqlerrm);
END;


And error after running this script is..

anonymous block completed
ORA-01489: result of string concatenation is too long
Re: Creating boundaries in between xml elements [message #632380 is a reply to message #632379] Thu, 29 January 2015 10:12 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

The solution is there:

Michel Cadot wrote on Thu, 29 January 2015 07:45

You can use T. Kyte's STRAGG function instead.


Use the one for CLOB.


Re: Creating boundaries in between xml elements [message #632381 is a reply to message #632367] Thu, 29 January 2015 10:36 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
wantmannu wrote on Thu, 29 January 2015 09:42
But I am looking for single query


??? This is a single query returning a single row, so you can scrap that PL/SQL and issue:

INSERT INTO xx_test1c
with e as (
            select  empno,
                    xmlelement(
                               "employee",xmlconcat(
                                                    xmlelement("empno",empno),
                                                    xmlelement("ename",ename)
                                                   )
                              ).getclobval() empdata,
                    row_number() over(order by empno) rn,
                    count(*) over() cnt
              from  emp
           ),
     r(
       res,
       rn,
       cnt
      ) as (
             select  '
        
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#' || empno || '@xx.com
    Content-Length: ' || length(empdata) || '
  
    <?xml version="1.0" encoding="UTF-8"?>' || empdata res,
                     rn,
                     cnt
               from  e
               where rn = 1
            union all
             select  r.res || '
        
    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#' || empno || '@xx.com
    Content-Length: ' || length(empdata) || '
  
    <?xml version="1.0" encoding="UTF-8"?>' || e.empdata res,
                     e.rn rn,
                     r.cnt cnr
               from  r,
                     e
               where e.rn = r.rn + 1
           )
select  res
  from  r
  where rn = cnt
/


For example:

SQL> create table xx_test1c(res clob)
  2  /

Table created.

SQL> INSERT INTO xx_test1c
  2  with e as (
  3              select  empno,
  4                      xmlelement(
  5                                 "employee",xmlconcat(
  6                                                      xmlelement("empno",empno),
  7                                                      xmlelement("ename",ename)
  8                                                     )
  9                                ).getclobval() empdata,
 10                      row_number() over(order by empno) rn,
 11                      count(*) over() cnt
 12                from  emp
 13             ),
 14       r(
 15         res,
 16         rn,
 17         cnt
 18        ) as (
 19               select  '
 20          
 21      --yytet00pubSubBoundary00tetyy
 22      Content-ID: xx.#' || empno || '@xx.com
 23      Content-Length: ' || length(empdata) || '
 24    
 25      <?xml version="1.0" encoding="UTF-8"?>' || empdata res,
 26                       rn,
 27                       cnt
 28                 from  e
 29                 where rn = 1
 30              union all
 31               select  r.res || '
 32          
 33      --yytet00pubSubBoundary00tetyy
 34      Content-ID: xx.#' || empno || '@xx.com
 35      Content-Length: ' || length(empdata) || '
 36    
 37      <?xml version="1.0" encoding="UTF-8"?>' || e.empdata res,
 38                       e.rn rn,
 39                       r.cnt cnr
 40                 from  r,
 41                       e
 42                 where e.rn = r.rn + 1
 43             )
 44  select  res
 45    from  r
 46    where rn = cnt
 47  /

1 row created.

SQL> set pagesize 50000
SQL> set long 50000
SQL> select  count(*)
  2    from  xx_test1c
  3  /

  COUNT(*)
----------
         1

SQL> select  *
  2    from  xx_test1c
  3  /

RES
-------------------------------------------------------------------------------------------------------------


    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7369@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7369</empno><ename>SMITH</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7499@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7499</empno><ename>ALLEN</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7521@xx.com
    Content-Length: 59

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7521</empno><ename>WARD</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7566@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7566</empno><ename>JONES</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7654@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7654</empno><ename>MARTIN</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7698@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7698</empno><ename>BLAKE</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7782@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7782</empno><ename>CLARK</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7788@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7788</empno><ename>SCOTT</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7839@xx.com
    Content-Length: 59

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7839</empno><ename>KING</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7844@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7844</empno><ename>TURNER</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7876@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7876</empno><ename>ADAMS</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7900@xx.com
    Content-Length: 60

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7900</empno><ename>JAMES</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7902@xx.com
    Content-Length: 59

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7902</empno><ename>FORD</ename></employee>

    --yytet00pubSubBoundary00tetyy
    Content-ID: xx.#7934@xx.com
    Content-Length: 61

    <?xml version="1.0" encoding="UTF-8"?><employee><empno>7934</empno><ename>MILLER</ename></employee>


SQL> 


SY.

[Updated on: Thu, 29 January 2015 10:37]

Report message to a moderator

Re: Creating boundaries in between xml elements [message #632383 is a reply to message #632381] Thu, 29 January 2015 10:47 Go to previous messageGo to next message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

Hi SY, are you using same db version which I am using. Reason I am asking is I am getting error while running your query.


SQL Error: ORA-00600: internal error code, arguments: [qctfrc : bfc], [4000], [0], [1], [873], [1], [2], [394], [], [], [], []
00600. 00000 -  "internal error code, arguments: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]"
*Cause:    This is the generic internal error number for Oracle program
           exceptions.	This indicates that a process has encountered an
           exceptional condition.
*Action:   Report as a bug - the first argument is the internal error number
Re: Creating boundaries in between xml elements [message #632384 is a reply to message #632383] Thu, 29 January 2015 11:03 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
SQL> select * from v$version
  2  /

BANNER
-----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

SQL> 


SY.
Re: Creating boundaries in between xml elements [message #632396 is a reply to message #632384] Thu, 29 January 2015 15:45 Go to previous messageGo to previous message
wantmannu
Messages: 42
Registered: June 2009
Location: cali
Member

I am still not able to get the solution. I have used STRAGG , XMLAGG, CLOBAGG and it is throwing with various errors Sad. Please help!!
And the solution SY gave , it throws out error for more than 4000 characters too.
Previous Topic: ORA-01460: unimplemented or unreasonable conversion requested
Next Topic: REGULAR_EXPRESSION query
Goto Forum:
  


Current Time: Tue Apr 23 01:50:28 CDT 2024