通过传递SQL变量来更新xml数据节点

时间:2019-03-25 11:57:40

标签: sql-server xml nodes

我有以下XML,我需要根据参数更新指定的XML:

<DOPremium>
    <BasePremium>337500</BasePremium>
    <TotalPremium>337500</TotalPremium>
    <NettPremium>337500</NettPremium>
    <GrossPremium>337500</GrossPremium>
    <OptionId>0</OptionId>
</DOPremium>
<DOPremium>
     <BasePremium>337500</BasePremium>
     <TotalPremium>337500</TotalPremium>
     <NettPremium>337500</NettPremium>
     <GrossPremium>337500</GrossPremium>
     <OptionId>1</OptionId>
</DOPremium>
<DOPremium>
     <BasePremium>337500</BasePremium>
     <TotalPremium>337500</TotalPremium>
     <NettPremium>337500</NettPremium>
     <GrossPremium>337500</GrossPremium>
     <OptionId>2</OptionId>
</DOPremium>

我正在尝试根据DOPremium对象的选择来更新相应的节点,但是我无法做到这一点。有人可以验证我错了吗?

SET @NewXmlValue = N' <BasePremium>[sql:variable("@R15_premium")]</BasePremium>'
SET @DataXml.modify('delete /*/Premiums/DOPremium/BasePremium[sql:variable("@OptionID")]')          
SET @DataXml.modify('insert sql:variable("@NewXmlValue") into (/*/Premiums/DOPremium[sql:variable("@OptionID")])[1]')           

-- Add TotalPremium
SET @NewXmlValue = N' <TotalPremium>[sql:variable("@R15_premium")]</TotalPremium>'
SET @DataXml.modify('delete /*/Premiums/DOPremium/TotalPremium[sql:variable("@OptionID")]')         
SET @DataXml.modify('insert sql:variable("@NewXmlValue") into (/*/Premiums/DOPremium[sql:variable("@OptionID")])[1]')

1 个答案:

答案 0 :(得分:0)

好的,首先,这是行不通的:

SET @NewXmlValue = N'<BasePremium>[sql:variable("@R15_premium")]</BasePremium>'

sql:variable()仅在XQuery操作中解释为函数。这不是XQuery操作,因此只会在文本上插入sql:variable(...)。如果您想要一个带有变量文本值的实际XML节点,则必须多一些回旋处:

SET @NewXmlValue = '';
SET @NewXmlValue = (SELECT @NewXmlValue.query('<BasePremium>{sql:variable("@R15_premium")}</BasePremium>'));

可以在docs中找到此方法(及其他方法)。 (当然,在这种非常简单的情况下,在T-SQL中连接字符串也是可行的,但是总的来说,这不是一个好主意,因为它不需要在必要时转义XML。)

选择所需的DOPremium节点的语法也需要工作-/BasePremium[sql:variable("@OptionID")]是合法的,但是它表示“ BasePremium节点,其顺序从1开始依次编号为{{ 1}}”。如果@OptionID应该与@OptionID中的内容匹配,那不是写它的方法。

如果您要编写“将具有等于OptionID的{​​{1}}文本的BasePremium的节点的OptionID值的内容更改为值@OptionID”,这就是下面的方法您可以这样做(嗯,这样做的一种方法):

@R15_premium

SET @DataXml.modify(' replace value of ( /* /Premiums /DOPremium[child::OptionId/.=sql:variable("@OptionID")] /BasePremium /text() )[1] with sql:variable("@R15_premium")') 类似。当然,您也可以替换整个节点,但这似乎不必要。