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

烂漫一生 提交于 2020-06-27 05:51:42

问题


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


回答1:


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.




回答2:


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)


来源:https://stackoverflow.com/questions/27136761/parsing-dynamic-xml-to-sql-server-tables-with-parent-and-child-relation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!