Home > Net >  SQL: Use modify function to iterate on xml nodes or How to insert or modify nodes recursively
SQL: Use modify function to iterate on xml nodes or How to insert or modify nodes recursively

Time:10-27

I have an xml as show in the code below

I want to iterate though each node and insert one node after each TextReadingName node

DECLARE @XML XML =
N'<Steplist>
  <Step>
    <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>     
  </Step>
  <Step>
    <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
    <TextReadingName>reading1</TextReadingName>
  </Step>
</Steplist>';



--SELECT x.XmlCol.value('(StepId)[1]', 'nvarchar(max)') as StepId
--FROM   @xml.nodes('/Steplist/Step') x(XmlCol)  

This is how I want my new xml to look

N'<Steplist>
      <Step>
        <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
        <Rank>1</Rank>
        <IsComplete>false</IsComplete>
        <TextReadingName>bug-8588_Updated3</TextReadingName>    
      <TextReadingId>1</TextReadingId>   
      </Step>
      <Step>
        <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
        <Rank>2</Rank>
        <TextReadingName>reading1</TextReadingName>
      <TextReadingId>2</TextReadingId> 
      </Step>
    </Steplist>';

I am able to select nodes as shown below but not able to iterate through each node and modify the data

--SELECT x.XmlCol.value('(StepId)[1]', 'nvarchar(max)') as StepId
--FROM   @xml.nodes('/Steplist/Step') x(XmlCol) 

I am looking same function as above but for inserting nodes

This is how I want my new xml to look with new node named TextReadingId after TextReading name

N'<Steplist>
      <Step>
        <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
        <Rank>1</Rank>
        <IsComplete>false</IsComplete>
        <TextReadingName>bug-8588_Updated3</TextReadingName>    
      <TextReadingId>1</TextReadingId>   
      </Step>
      <Step>
        <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
        <Rank>2</Rank>
        <TextReadingName>reading1</TextReadingName>
      <TextReadingId>2</TextReadingId> 
      </Step>
    </Steplist>';

CodePudding user response:

You can use modify with insert, but the main drawback seems to be that SQL server only allows insert into a single node, I couldn't combine it with a FLOWR expression, so I had to use an SQL WHILE loop to perform various modify calls:

DECLARE @XML XML =
N'<Steplist>
  <Step>
    <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>     
  </Step>
  <Step>
    <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
    <TextReadingName>reading1</TextReadingName>
  </Step>
</Steplist>';

BEGIN

DECLARE @i int;

SELECT @i = @XML.value('count(Steplist/Step)', 'int');

WHILE @i > 0
  BEGIN

    SET @XML.modify('insert <TextReadingId>{sql:variable("@i")}</TextReadingId> as last into (/Steplist/Step[sql:variable("@i")])[1]');

    SET @i = @i - 1;
  END
END
SELECT @XML;
  • Related