У меня есть XML
столбец, который содержит данные с похожей структурой:
<Root>
<Elements>
<Element Code="1" Value="aaa"></Element>
<Element Code="2" Value="bbb"></Element>
<Element Code="3" Value="ccc"></Element>
</Elements>
</Root>
Как я могу изменить данные, используя SQL Server, чтобы изменить каждый Value
атрибут в элемент?
<Root>
<Elements>
<Element Code="1">
<Value>aaa</Value>
</Element>
<Element Code="2">
<Value>bbb</Value>
</Element>
<Element Code="3">
<Value>ccc</Value>
</Element>
</Elements>
</Root>
Обновить:
Мой XML выглядит примерно так:
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
<Element Code="4" Value="" ExtraData="extra" />
<Element Code="5" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>
Я хотел бы только переместить Value
атрибут и сохранить все остальные атрибуты и элементы.
sql-server
xml
xquery
Wojteq
источник
источник
<Value>
элементов для каждого<Element>
. Если нет, то перемещение атрибута в элемент просто создает более раздутый и, возможно, менее эффективный XML.<Value>
элемента или вместо него.Ответы:
Вы можете уничтожить XML и перестроить его снова, используя XQuery.
Результат:
Если
Elements
это не первый элементRoot
запроса, его необходимо изменить, чтобы добавить все элементы доElements
первого и все элементы послеElements
после.источник
Вы также можете использовать методы типа данных XML (например, изменить ) и некоторые XQuery для изменения XML, например
Этот метод не подходит для масштабирования больших кусков XML, но может подойти вам лучше, чем полная замена XML.
Вы также можете легко адаптировать этот метод, если ваш XML хранится в таблице. Опять же по опыту я бы не советовал запускать одно обновление для таблицы с миллионами строк. Если у вас большая таблица, попробуйте навести на нее курсор или иным образом пакетировать обновления. Вот техника:
источник
ОБНОВИТЬ:
Я обновил код, а также входной и выходной XML в приведенном ниже примере запроса, чтобы отразить последнее требование, изложенное в комментарии к прекрасному ответу @ Mikael , а именно:
В то время как одно выражение может правильно соответствовать этому новому варианту, похоже, не существует способа пропустить пустой
<Value/>
элемент за один проход, так как условная логика не допускается в строке замены. Итак, я адаптировал это, чтобы он состоял из двух частей: один проход для получения непустых@Value
атрибутов и один проход для получения пустых@Value
атрибутов. Не было необходимости обрабатывать<Element>
s, пропускающие@Value
атрибут, так как желание в<Value>
любом случае не иметь элемента.Одним из вариантов является обработка XML как обычной строки и преобразование его на основе шаблона. Это легко сделать с помощью регулярных выражений (в частности, функции «Заменить»), которые можно сделать доступными через код SQLCLR.
В приведенном ниже примере используется скалярный UDF RegEx_Replace из библиотеки SQL # (автором которого я являюсь, но эта функция RegEx доступна в бесплатной версии вместе со многими другими):
Эти
PRINT
заявления находятся там только , чтобы сделать для облегчения сравнения бок о бок на вкладке «Сообщения». В результате получается (я немного изменил исходный XML, чтобы было очень ясно, что были затронуты только нужные части и больше ничего):Если вы хотите обновить поле в таблице, вы можете изменить приведенное ниже:
источник
Вероятно, есть лучшие способы сделать это вне SQL Server. Тем не менее, вот один из способов сделать это.
Xml CTE преобразует вашу переменную xml в таблицу.
Основной выбор затем преобразует CTE обратно в XML.
Это также можно сделать с помощью
For XML Explicit
.источник