替换存储在XML数据在存储过程中与ID

问题描述:

值I在形式XML:替换存储在XML数据在存储过程中与ID

<Books> 
    <Book> 
     <Name>Lord of the Rings</Name> 
    </Book> 
    <Book> 
     <Name>Harry Potter</Name> 
    </Book> 
    <Book> 
     <Name>Girl with the Dragon Tattoo</Name> 
    </Book> 
</Books> 

我然后有一个包含两列(Id和名称)的表:

  • 1 :魔戒
  • 2:哈利波特
  • 3:女孩龙纹身

使用TSQL,我要更新XML成为:

<Books> 
    <Book> 
     <Name>1</Name> 
    </Book> 
    <Book> 
     <Name>2</Name> 
    </Book> 
    <Book> 
     <Name>3</Name> 
    </Book> 
</Books> 

如,我需要做一个查找到“查找”表和更新节点的值是ID,而不是名称。

我能想到的唯一方法是创建一个循环并使用XPath提取名称,查询查找表,然后使用'替换值'调用XML上的修改。有没有更好的方法,因为我想我的建议解决方案会很慢?该解决方案需要使用TSQL,并且在调用SP之前不能在业务逻辑中执行。我想有一种方法可以在基于集合的操作中执行此操作,但我正在努力寻找它。

+0

Th e序列是1 2 1,我认为它应该是1 2 3. –

+0

这真的是你的元素名称吗?这些不是有效的XML元素名称,因此您不能使用XML数据类型来修改内容。 –

+0

@MikaelEriksson - 我已经更新了示例,因为我选择了一个很差的示例。没有这些不是节点名称。 – psych

我不认为这是一个很好的解决方案,但确保有答案帮助其他人查看此问题,这是我的解决方案:

DECLARE @BookId NVARCHAR(10) 
DECLARE @BookName NVARCHAR(100) 
DECLARE @Counter INT 
DECLARE @MaxCounter INT 
SET @Counter = 1 

SET @MaxCounter = @BooksXml.value('count(/Books/Book)', 'int') 

WHILE @Counter <= @MaxCounter 
BEGIN 
    SET @BookName = @BooksXml.value('(/Books/Book[sql:variable("@Counter")]/Name/text())[1]', 'nvarchar(100)') 
    SELECT @BookId=CAST(ProductID AS NVARCHAR(10)) FROM Book WHERE Name = @BookName 

    SET @BooksXml.modify('replace value of (/Books/Book[sql:variable("@Counter")]/Name/text())[1] with sql:variable("@BookId")') 

    SET @Counter = @Counter + 1 
END 

我认为你是走向正确的道路。我个人认为这不会很慢。或者你有没有发现?

考虑从MSDN这个例子@http://msdn.microsoft.com/en-us/library/ms190675.aspx

DECLARE @myDoc xml 
SET @myDoc = '<Root> 
<Location LocationID="10" 
      LaborHours=".1" 
      MachineHours=".2" >Manu steps are described here. 
<step>Manufacturing step 1 at this work center</step> 
<step>Manufacturing step 2 at this work center</step> 
</Location> 
</Root>' 
--SELECT @myDoc 

我想在这里这个权利是非常快速的操作:

SET @myDoc.modify(' 
    replace value of (/Root/Location[1]/@LaborHours)[1] 
    with (
     if (count(/Root/Location[1]/step) > 3) then 
     "3.0" 
     else 
      "1.0" 
    ) 
') 
SELECT @myDoc 
+0

感谢您的回答 - 感谢您花时间回复。 我同意你发布的例子应该很快。但是,如果有多个位置节点,您将如何更新所有LaborHours属性?我的建议是有效循环上面的代码,为XML中的每个目标节点调用一次。虽然数据集不是太大,但我认为可能有更快的方法。 +1,因为我认为你的回答对这个问题是有建设性的。 – psych