1

I have been working a while with SQL Server and queries but this is my first time needing to update a column of type XML.

What i am trying to do (and it is working in the code example below) is find where the 'Name' equals a specific string and then update its related 'Value' to a new value.

In the example below I find the Parameter that contains "UnitPrice" in the xml file by using a loop to find the index. Then I use the index to update the Parameter's value.

Main question: Is there a more efficient way where I do not need to use a while loop but can use some type of where statement?

DECLARE @OUTPUTXML AS XML;
SET @OUTPUTXML = '
<OutputParameters>
  <CommitParameters>
    <Parameter>
      <Name>Item</Name>
      <Value >Baseball Bat</Value>
    </Parameter>
    <Parameter>
      <Name>Quantity</Name>
      <Value >35</Value>
    </Parameter>
    <Parameter>
      <Name>UnitPrice</Name>
      <Value >53.99</Value>
    </Parameter>
    <Parameter>
      <Name>Color</Name>
      <Value >Tan</Value>
    </Parameter>
    <Parameter>
      <Name>Style</Name>
      <Value >Wood</Value>
    </Parameter>
    <Parameter>
      <Name>Size</Name>
      <Value >34</Value>
    </Parameter>
    <Parameter>
      <Name>SKU</Name>
      <Value >123456</Value>
    </Parameter>
  </CommitParameters>
</OutputParameters>';

DECLARE @i AS INT;
DECLARE @iOfName AS INT;
DECLARE @nameCheck AS VARCHAR(200);
DECLARE @ParmName AS VARCHAR(200);
DECLARE @maxNames AS INT;
DECLARE @newValue AS VARCHAR(200);

SET @ParmName = 'UnitPrice';
SET @newValue = '62.99';
SET @i = 1;
SET @maxNames = ( SELECT    MAX(@OUTPUTXML.value('count(/OutputParameters/CommitParameters/Parameter)', 'int')) );

WHILE @i <= @maxNames 
    BEGIN

        SET @nameCheck = (SELECT  @OUTPUTXML.value('(/OutputParameters/CommitParameters/Parameter[sql:variable("@i")]/Name/text())[1]',
                        'varchar(200)'));

        IF (RTRIM(@nameCheck) = @ParmName)
        BEGIN
            SET @iOfName = @i;
            BREAK;
        END;      

        SET @i = @i + 1;
    END;

SET 
   @OUTPUTXML.modify('
    replace value of (/OutputParameters/CommitParameters/Parameter[sql:variable("@iOfName")]/Value/text())[1] 
    with sql:variable("@newValue")
    '); 

Thank you for your help/input.

4

1 回答 1

1

In this case there is no need in walking through elements manually. You can use XPath capabilities and identify necessary Parameter element as:

/OutputParameters/CommitParameters/Parameter[Name[.="UnitPrice"]]

i.e., you can do what you are trying to do with just following:

DECLARE @ParmName AS VARCHAR(200);
DECLARE @newValue AS VARCHAR(200);

SET @ParmName = 'UnitPrice';
SET @newValue = '62.99';

set @OUTPUTXML.modify('
    replace value of (/OutputParameters/CommitParameters/Parameter[Name[text()[1]=sql:variable("@ParmName")]]/Value/text())[1] 
    with sql:variable("@newValue")
    '); 
于 2013-08-17T22:16:17.583 回答