#sql #xml #tsql #xpath #dml
Вопрос:
У меня есть таблица бд под названием XmlDocument с полем XML, которая используется для хранения xml. И это пример сохраненного xml:
<ol type="decimal" id="id-a4bb3b6d-9908-4972-8b02-72e286795b7a">
<item id="id-92332716-4561-4874-d353-39fdf993fa89">
<para id="id-a3fae837-59d8-4702-b689-f869137a92a7">Item1</para>
</item>
<item id="id-d8031e83-5b68-47cb-f535-41bee9682f4a">
<para id="id-8746fe56-3160-4543-bf28-5f1e1de83ec0">Item2</para>
</item>
</ol>
Моя цель-написать сценарий tsql, который добавит атрибут revNumber ко всем узлам документа, у которого этого атрибута нет. Вот как это должно выглядеть:
<ol revNumber="1.1" type="decimal" id="id-a4bb3b6d-9908-4972-8b02-72e286795b7a">
<item revNumber="1.2" id="id-92332716-4561-4874-d353-39fdf993fa89">
<para revNumber="1.3" id="id-a3fae837-59d8-4702-b689-f869137a92a7">Item1</para>
</item>
<item revNumber="1.0" id="id-d8031e83-5b68-47cb-f535-41bee9682f4a">
<para revNumber="1.2" id="id-8746fe56-3160-4543-bf28-5f1e1de83ec0">Item2</para>
</item>
</ol>
Если у узла уже есть этот атрибут, мы должны пропустить его. Мы можем использовать что-то подобное, но это работает только для одного узла:
SET @requestXML.modify(
'insert
(
attribute revNumber {sql:variable("@revNum") }
)
into (/ol)[1]')
Но структура документа может быть другой. Каков наилучший способ сделать это?
Комментарии:
1. Вы не можете легко сделать это в SQL Server, потому
.modify
что одновременно работает только на одном узле. Лучше просто извлечь его в клиентское приложение и обработать там. Или, возможно, функция SQLCLR.
Ответ №1:
Наконец я нашел решение:
declare @xml XML = '
<root>
<text>test</text>
<text>test</text>
<text>test</text>
<text>test</text>
</root>
'
while @xml.exist('//*[not(@TEST)]') = 1
begin
set @xml.modify('
insert attribute TEST {"value"}
into (//*[not(@TEST)])[1]
')
end
select @xml
Комментарии:
1. Хороший ответ, 1 с моей стороны!