sql-servert-sqlxpathxqueryxml-dml

How to update the existing node value of XML by multiplying it with n times in SQL Server


Here is the XML I have in my Table Field

<CtcConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Ctc>3</Ctc>
    <SalaryComponent>
        <SalaryComponentConfiguration>
            <Name>Basic</Name>
            <DisplayOrder>0</DisplayOrder>
            <Value>5634655</Value>
        </SalaryComponentConfiguration>
        <SalaryComponentConfiguration>
            <Name>HR</Name>
            <DisplayOrder>0</DisplayOrder>
            <Value>1234</Value>
        </SalaryComponentConfiguration>
        <SalaryComponentConfiguration>
            <Name>medical</Name>
            <DisplayOrder>0</DisplayOrder>
            <Value>0</Value>
        </SalaryComponentConfiguration>
    </SalaryComponent>
</CtcConfiguration>

I want the update the existing node(DisplayOrder) value by multiplying it with n times.

This is what I get so far to update a node value:

    DECLARE @NodeName VARCHAR(100)=N'Basic';
    DECLARE @NewValue INT=3;
    UPDATE payroll.pays 
    SET CtcConfiguration.modify(
          N'replace value of (/CtcConfiguration
                              /SalaryComponent
                              /SalaryComponentConfiguration[(Name/text())[1]=sql:variable("@NodeName")]
                              /Value/text())[1] 
            with sql:variable("@NewValue")');

Solution

  • I want to offer you two approaches:

    Use these variables to pick the right node and to define the multiplier

    DECLARE @AttributeName VARCHAR(100)=N'medical';
    DECLARE @Multiply INT=2;
    
    UPDATE YourTable
    SET YourXML.modify(N'replace value of (/CtcConfiguration
                                           /SalaryComponent
                                           /SalaryComponentConfiguration[(Name/text())[1]=sql:variable("@AttributeName")]
                                           /DisplayOrder/text())[1] 
                         with xs:int((/CtcConfiguration
                                     /SalaryComponent
                                     /SalaryComponentConfiguration[(Name/text())[1]=sql:variable("@AttributeName")]
                                     /DisplayOrder/text())[1]) * sql:variable("@Multiply")');
    

    --Alternatively you can use an updateable CTE:
    --In this case you use sql:column() instead of sql:variable()

    SET @AttributeName=N'Basic';
    
    WITH cte AS
    (
        SELECT *
               --you can place any multiplier here
              ,10 * YourXML.value(N'(/CtcConfiguration
                                     /SalaryComponent
                                     /SalaryComponentConfiguration[(Name/text())[1]=sql:variable("@AttributeName")]
                                     /DisplayOrder/text())[1] ',N'int') AS NewValue
        FROM YourTable
    )
    UPDATE cte
    SET YourXML.modify(N'replace value of (/CtcConfiguration
                                           /SalaryComponent
                                           /SalaryComponentConfiguration[(Name/text())[1]=sql:variable("@AttributeName")]
                                           /DisplayOrder/text())[1] 
                         with sql:column("NewValue")');