我在SQL Server 2008中有这个XML:
DECLARE @xml xml = '<Root>
<Contacts>
<Contact name="John Doe" type="REG" other="value" />
<Contact name="Jane Doe" type="REG" other="value" />
<Contact name="Jennifer Doe" type="REG" other="value" />
<Contact name="Jane Doe" type="REG" other="value" />
</Contacts>
</Root>'
我想将类型的值更改为其他内容。我可以硬编码我想改变哪一个没问题。
SET @xml.modify('replace value of (/Root/Contacts/Contact)[1]/@type with "NEW"')
SELECT @xml
无论我在括号中放置什么价值,这都是“做对了”。 IOW,上面更改了第一个,将其更改为[3]更改第三个,等等。
我想改变所有这些,无论有多少或几乎没有。所以,我需要得到计数,然后使用变量迭代它们。获得计数很容易,但我无法使变量起作用。
IOW,这个用上面的[1]替换变量的XML不起作用。
DECLARE @i int = 1
SET @xml.modify('replace value of (/Root/Contacts/Contact)[sql:variable("@i")]/@type with "NEW"')
SELECT @xml
它给了我这个错误,它告诉我我做错了什么,但是我不能理解错误来找出我做错了什么
:Msg 2337,Level 16,State 1,Line 14
XQuery [modify()]:'replace'的目标必须至多是一个节点,找到'attribute(type,xdt:untypedAtomic)*'
当我即将点击“发布”时,我发现引用了一些内容,表示你必须使用position()才能在节点索引上使用变量,但示例是查询,而不是修改。这也行不通。
DECLARE @i int = 1
SET @xml.modify('replace value of (/Root/Contacts/Contact)[position()=sql:variable("@i")]/@type with "NEW"')
SELECT @xml
我毫不怀疑这很容易,但我在这里和其他地方搜索了如何使用sql:variable
,几乎所有我发现的例子都将它用作替换中的值,不是索引(也没有“可能已经有你的答案的问题”帮助了。)我还在各个地方尝试了额外的括号等等,而且还没有能够达到神奇的组合。
使用@i?
使上述SET工作失败了答案 0 :(得分:4)
您自己的代码只能使用一个[1]
。函数.modify()
无法解释[sql:variable(...)]
...这可能是任何过滤器,即使是具有多个结果的过滤器......所以只需将其更改为:
DECLARE @xml xml = '<Root>
<Contacts>
<Contact name="John Doe" type="REG" other="value" />
<Contact name="Jane Doe" type="REG" other="value" />
<Contact name="Jennifer Doe" type="REG" other="value" />
<Contact name="Jane Doe" type="REG" other="value" />
</Contacts>
</Root>';
DECLARE @i int = 1
SET @xml.modify('replace value of (/Root/Contacts/Contact)[sql:variable("@i")][1]/@type with "NEW"')
SELECT @xml
但我会走另一条道路......您可能会将整个视图作为派生表阅读,并像这样重建XML:
SELECT
(
SELECT c.value('@name','nvarchar(max)') AS [@name]
--,c.value('@type','nvarchar(max)') AS [@type]
,'NEW' AS [@type]
,c.value('@other','nvarchar(max)') AS [@other]
FROM @xml.nodes('/Root/Contacts/Contact') AS A(c)
FOR XML PATH('Contact'),ROOT('Contact'),TYPE
)
FOR XML PATH('Root')
另一种方法是FLWOR:
SELECT @xml.query('
for $r in /Root/Contacts
return <Root><Contacts>
{
for $c in /Root/Contacts/Contact
return <Contact name="{$c/@name}" type="NEW" other="{$c/@other}"/>
}
</Contacts></Root>
')