Shweetha
Shweetha

Reputation: 1

Parsing Dynamic XML to SQL Server tables with Parent and child relation

I have a XML in Source Table. I need to parse this XML to 3 different tables which has Parent Child relationship. I can do this in C# but currently for this i need to implement it at SQL server side. The sample xml looks like:

<ROWSET>
  <ROW>
     <HEADER_ID>5001507</HEADER_ID>
     <ORDER_NUMBER>42678548</ORDER_NUMBER>
     <CUST_PO_NUMBER>LSWQWE1</CUST_PO_NUMBER>
     <CUSTOMER_NUMBER>38087</CUSTOMER_NUMBER>
     <CUSTOMER_NAME>UNIVERSE SELLER</CUSTOMER_NAME>
     <LINE>
       <LINE_ROW>
         <HEADER_ID>5001507</HEADER_ID>
         <LINE_ID>12532839</LINE_ID>
         <LINE_NUMBER>1</LINE_NUMBER>        
         <ITEM_NUMBER>STAGEPAS 600I-CA</ITEM_NUMBER>
         <ORDER_QUANTITY>5</ORDER_QUANTITY>        
       </LINE_ROW>      
       <LINE_ROW>
         <HEADER_ID>5001507</HEADER_ID>
         <LINE_ID>12532901</LINE_ID>
         <LINE_NUMBER>3</LINE_NUMBER>        
         <ITEM_NUMBER>CD-C600 RK</ITEM_NUMBER>
         <ORDER_QUANTITY>6</ORDER_QUANTITY>
       </LINE_ROW>
       <LINE_ROW>
         <HEADER_ID>5001507</HEADER_ID>
         <LINE_ID>12532902</LINE_ID>
         <LINE_NUMBER>4</LINE_NUMBER>
         <ITEM_NUMBER>CD-S300 RK</ITEM_NUMBER>
         <ORDER_QUANTITY>8</ORDER_QUANTITY>
      </LINE_ROW>      
    </LINE>
    <PRCADJ>
      <PRCADJ_ROW>
        <PRICE_ADJUSTMENT_ID>43095064</PRICE_ADJUSTMENT_ID>
        <HEADER_ID>5001507</HEADER_ID>
        <LINE_ID>12532839</LINE_ID>        
        <ADJUSTED_AMOUNT>-126</ADJUSTED_AMOUNT>
      </PRCADJ_ROW>
      <PRCADJ_ROW>
        <PRICE_ADJUSTMENT_ID>43095068</PRICE_ADJUSTMENT_ID>
        <HEADER_ID>5001507</HEADER_ID>
        <LINE_ID>12532840</LINE_ID>
        <ADJUSTED_AMOUNT>-96.6</ADJUSTED_AMOUNT>
      </PRCADJ_ROW>          
    </PRCADJ>
 </ROW>
</ROWSET>

The issue is the Parent can have multiple child and each child can multiple sub child. How can i write query to transfer this into Sql Server 2005

Upvotes: 0

Views: 1480

Answers (2)

radar
radar

Reputation: 13425

you can do some thing like this. using cross apply you will get node elements and then extract the value using value clause. you need to specify the column type i.e int or varchar etc.

The result can then be inserted using insert into select query.

insert into Table1 values ( header_id, order_number, cust_po_number)
select R.value('(HEADER_ID)[1]', 'int') As header_id,
       R.value('(ORDER_NUMBER)[1]', 'int') as order_number,
       R.value('(CUST_PO_NUMBER)[1]', 'varchar(256)') as cust_po_number
from table 
cross apply XMLdata.nodes('/ROWSET/ROW') AS P(R)

insert into Table2 values ( header_id, line_id, line_number)
select R.value('(HEADER_ID)[1]', 'int') As header_id,
       R.value('(LINE_ID)[1]', 'int') as line_id,
       R.value('(LINE_NUMBER)[1]', 'int') as line_number
from table 
cross apply XMLdata.nodes('/ROWSET/ROW/LINE/LINE_ROW') AS P(R)

Upvotes: 1

marc_s
marc_s

Reputation: 755391

You need to use three CROSS APPLY operators to break up the "list of XML elements" into separate pseudo tables of XML rows, so you can access their properties - something like this:

SELECT
    HeaderID = XCRow.value('(HEADER_ID)[1]', 'int'),
    OrderNumber = XCRow.value('(ORDER_NUMBER)[1]', 'int'),
    LineHeaderID = XCLine.value('(HEADER_ID)[1]', 'int'),
    LineID = XCLine.value('(LINE_ID)[1]', 'int'),
    LineNumber = XCLine.value('(LINE_NUMBER)[1]', 'int'),
    PriceAdjustmentID = XCPrc.value('(PRICE_ADJUSTMENT_ID)[1]', 'int'),
    AdjustedAmount = XCPrc.value('(ADJUSTED_AMOUNT)[1]', 'decimal(20,4)')
FROM 
    dbo.YourTableNameHere
CROSS APPLY
    Data.nodes('/ROWSET/ROW') AS XTRow(XCRow)
CROSS APPLY
    XCRow.nodes('LINE/LINE_ROW') AS XTLine(XCLine)
CROSS APPLY
    XCRow.nodes('PRCADJ/PRCADJ_ROW') AS XTPrc(XCPrc)

With this, the first CROSS APPLY will handle all the elements that are found directly under <ROWSET> / <ROW> (the header information), the second one will enumerate all instances of <LINE> / <LINE_ROW> below that header element, and the third CROSS APPLY handles the <PRCADJ> / <PRCADJ_ROW> elements, also below the header.

You might need to tweak the outputs a bit - and I only picked two or three of the possible values - extend and adapt to your own needs! But this should show you the basic mechanism - the .nodes() method returns a "pseudo table" of XML fragments, one for each match of the XPath expression you define.

Upvotes: 1

Related Questions