SQL Server XML - изменить несколько элементов - PullRequest
0 голосов
/ 22 апреля 2019

У меня есть столбец SQL Server XML с такими данными:

<History>
   <Entry>
      .....
   </Entry>
   <Entry>
      .....
   </Entry>
</History>

Мне нужно добавить уникальный идентификатор для каждого элемента Entry, чтобы получить такой результат:

<History>
  <Entry entryID="AAA">
      .....
   </Entry>
   <Entry entryID="BBB">
      .....
   </Entry>
</History>

У меня он работает для первого вхождения элемента Entry, но я не знаю, как применить его ко всем вхождениям. Кроме того, этот entryID является GUID, и я не знаю, как создать новый для каждой строки.

Вот как я обновляю первый элемент.

declare @eventId varchar(64)
set @eventId =  CONVERT(varchar(64),NEWID())
update Histories
       set XmlHistory.modify('
              insert attribute EntryID {sql:variable("@eventId")}
                     into (History/Entry)[1]
       ')
where HistoryID=285162

У меня также есть запрос, который выбирает элементы, которые нуждаются в этом атрибуте, и еще не имеют его. Это дает первичный ключ и элемент, который мне нужно обновить. Я не могу получить уникальный идентификатор элемента для использования в индексе массива элементов.

select h.id rowPK, m.c.query('.') theElement
from TheTable h
    cross apply h.XMLColumn.nodes('History/Entry[not(@EntryID)]') m(c)
where XMLColumn.exist('(History/Entry)')= 1

1 Ответ

0 голосов
/ 22 апреля 2019

Управление XML в SQL Server может быть очень сложным, если у вас есть опция, любая другая опция!Вы должны применить уникальные идентификаторы перед загрузкой в ​​виде XML на Sql Server.Лучшее, что я мог сделать, - это измельчить XML в табличную переменную, добавить ключи и затем извлечь их в виде потока XML.Я надеюсь, что это поможет ...

Обратите внимание, что при этом проверяются дубликаты ключей, поэтому вам нужно будет обработать это, и вам нужно будет включить любые дополнительные узлы или элементы, на которые вы не ссылались в вопросе.

declare @Histories table
(
    HistoryID int,
    XmlHistory xml
)

insert into @Histories values (285162, '
<History> 
  <Entry> 
    Entry 1
  </Entry> 
  <Entry> 
    Entry 2
  </Entry> 
  <Entry> 
    Entry 3
  </Entry> 
  <Entry> 
    Entry 4
  </Entry> 
</History>');

declare @tmp table 
(
  EntryVal varchar(max),
  EntryGuid varchar(64)
)

insert into @tmp(EntryVal, EntryGuid)
SELECT p1.value(N'.[1]','nvarchar(max)') AS EntryValue, CONVERT(varchar(64),NEWID())
from   @Histories H1
outer apply H1.XmlHistory.nodes(N'/History/Entry') AS A(p1)

select EntryGuid as '@ID', EntryVal as "data()"
from   @tmp
for    XML PATH ('ENTRY'), root ('HISTORY');  

Вывод должен выглядеть следующим образом

<HISTORY>
  <ENTRY ID="1C5C9492-36C8-4E4E-9AE3-DF7E2F1C1948"> 
    Entry 1
  </ENTRY>
  <ENTRY ID="9AC4BB5D-C471-4C89-947B-8C17D2BD446C"> 
    Entry 2
  </ENTRY>
  <ENTRY ID="10A81C91-A58B-4846-A857-A14BFB7F9CB7"> 
    Entry 3
  </ENTRY>
  <ENTRY ID="0E65D134-37A2-489C-8C72-5BE52D08D7B1"> 
    Entry 4
  </ENTRY>
</HISTORY>
...