#sql-server #xml #nodes
#sql-сервер #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:
Хорошо, во-первых, это не может работать:
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>'));
Этот подход (и другие) можно найти в документах. (В этом очень простом случае объединение строк в T-SQL, конечно, также работает, но в целом это не очень хорошая идея, потому что она не заботится об экранировании XML при необходимости.)
Синтаксис для выбора нужного DOPremium
узла также нуждается в доработке — /BasePremium[sql:variable("@OptionID")]
является законным, но это означает « BasePremium
узел, который последовательно нумеруется от 1, имеет номер @OptionID
«. Если @OptionID
предполагается, что она соответствует тому, что находится в OptionID
, это не тот способ ее написания.
Если вы намеревались написать «измените содержимое 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")')
И что-то подобное для TotalPremium
. Вы можете, конечно, также заменить целые узлы, но здесь это кажется ненужным.