Home > Software design >  SQL: Update xml column in a table recursively
SQL: Update xml column in a table recursively

Time:10-27

I have a table in sql server 2012

With the following column definition

   CREATE TABLE [dbo].[tblStepList](
    [ToDoId] [int] IDENTITY(1,1) NOT NULL,
    [Data] [xml] NOT NULL
}

And the data column is xml with

<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>'

I want to update each row of the table with my new xml to look with new node named TextReadingId after TextReading name

I want to insert a new node named TextReadingId I want my TextReadingId values to be running numbers as follows

 <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>1</TextReadingId> 
          </Step>
        </Steplist>';

This is what I tried but it is not working as expected

DECLARE @i int;

SELECT

@i = s.data.value('count(/Steplist/Step)', 'nvarchar(max)')

FROM tblStepList   s

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

print @i
End

CodePudding user response:

Please try the following solution.

It is using XQuery and its FLWOR expression.

SQL

USE tempdb;
GO

DROP TABLE IF EXISTS [dbo].[tblStepList];

CREATE TABLE [dbo].[tblStepList](
    [ToDoId] [int] IDENTITY(1,1) NOT NULL,
    [Data] [xml] NOT NULL
);

INSERT INTO dbo.tblStepList ([Data]) VALUES
(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>');

-- before
SELECT * FROM dbo.tblStepList;

UPDATE dbo.tblStepList
SET [Data]  = [Data].query('<Steplist>
{
    for $x in /Steplist/Step
    let $pos := count(Steplist/*[. << $x])   1
    return <Step>{$x/*,
        if (not($x/TextReadingId)) then <TextReadingId>{$pos}</TextReadingId>
        else ()} 
        </Step>
}
</Steplist>');

-- after
SELECT * FROM dbo.tblStepList;
  • Related