我在Orders表中有一个名为OrderXML的xml列...
表格中有一个像这样的XML XPath ...

/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail


那里的InternalOrderDetails包含许多这样的InternalOrderDetail节点...

<InternalOrderDetails>
  <InternalOrderDetail>
    <Item_Number>FBL11REFBK</Item_Number>
    <CountOfNumber>10</CountOfNumber>
    <PriceLevel>FREE</PriceLevel>
  </InternalOrderDetail>
  <InternalOrderDetail>
    <Item_Number>FCL13COTRGUID</Item_Number>
    <CountOfNumber>2</CountOfNumber>
    <PriceLevel>NONFREE</PriceLevel>
  </InternalOrderDetail>
</InternalOrderDetails>


我的最终目标是在节点的Item_Number包含COTRGUID(例如'%COTRGUID')并且PriceLevel = NONFREE的情况下修改OrderXML列中的XML。如果满足该条件,我想将PriceLevel列更改为FREE。

创建xpath表达式以查找正确的节点(使用OrderXML.value或OrderXML.exist函数)以及使用OrderXML.modify函数更新XML时,都遇到了麻烦。

我为where子句尝试了以下内容:

WHERE OrderXML.value('(/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/Item_Number/node())[1]','nvarchar(64)') like '%13COTRGUID'


那确实有效,但是在我看来,我还需要在同一个where子句中包含第二个条件(PriceLevel = NONFREE),但我不知道该怎么做。也许我可以为这样的第二个条件输入AND…

AND OrderXML.value('(/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/PriceLevel/node())[1]','nvarchar(64)') = 'NONFREE'


但由于它是XML查询,因此恐怕它最终会像OR一样运行。

一旦正确获得WHERE子句,我将使用SET这样更新列:

UPDATE Orders SET orderXml.modify('replace value of (/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/PriceLevel[1]/text())[1] with "NONFREE"')


但是,我在一些测试数据上运行了该语句,并且没有更新任何XML列(即使它说zz行有效)。

我在这里待了几个小时都没有结果。感谢帮助。谢谢。

最佳答案

如果在Orders表的每一行中您的条件不止一个节点,则可以使用以下方法:

update orders set
    data.modify('
        replace value of
        (
            /Order/InternalInformation/InternalOrderBreakout/
            InternalOrderHeader/InternalOrderDetails/
            InternalOrderDetail[
                Item_Number[contains(., "COTRGUID")] and
                PriceLevel="NONFREE"
            ]/PriceLevel/text()
        )[1]
        with "FREE"
    ');




如果一行中可以有多个节点,那么有几种可能的解决方案,可惜的是,每个解决方案都不是很优雅。


您可以重建表中的所有xml-sql fiddle demo
或者您可以在循环中进行更新-sql fiddle demo

10-04 12:05
查看更多