Изменить значения XML, определенные при перекрестном применении - PullRequest
2 голосов
/ 22 июля 2011

У меня проблема с данными, некоторые значения хранятся в столбце XML в базе данных. Я воспроизвел проблему в следующем примере:

Сценарий установки:

create table XMLTest
(
    [XML] xml
)

--A row with two duff entries
insert XMLTest values ('
    <root>
        <item>
            <flag>false</flag>
            <frac>0.5</frac>
        </item>
        <item>
            <flag>false</flag>
            <frac>0</frac>
        </item>
        <item>
            <flag>false</flag>
            <frac>0.5</frac>
        </item>     
        <item>
            <flag>true</flag>
            <frac>0.5</frac>
        </item>
    </root>
    ')

В части XML неправильные записи с <flag>false</flag> и <frac>0.5</frac>, так как значение flag должно быть true для ненулевых frac значений.

Следующий SQL-код идентифицирует узлы элементов XML, которые требуют обновления:

select
    i.query('.')
from
    XMLTest
    cross apply xml.nodes('root/item[flag="false" and frac > 0]') x(i)

Я хочу сделать обновление для исправления этих узлов, но я не вижу, как изменить элементы item, обозначенные cross apply. Я видел, что обновление выглядит примерно так:

 update t
    set
        x.i.modify('replace value of (flag/text())[1] with "true"')
    from
        XMLTest t
        cross apply xml.nodes('root/item[flag="false" and frac > 0]') x(i)

Однако это не работает: я получаю сообщение об ошибке «Неверный синтаксис рядом с« изменить »».

Можно ли это сделать с помощью этого метода?

Я знаю, что альтернативой было бы сделать замену строки в столбце xml, но мне не нравится, что это немного неубедительно (и я не уверен, что это не сломало бы мои проблемы с реальными словами )

1 Ответ

4 голосов
/ 22 июля 2011

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

С http://msdn.microsoft.com/en-us/library/ms190675.aspx "Выражение1: Идентифицирует узел, значение которого должно быть обновлено. Он должен идентифицировать только один узел. "

-- While there are rows that needs to be updated
while exists(select *
             from XMLTest
             where [XML].exist('root/item[flag="false" and frac > 0]') = 1)
begin
  -- Update the first occurence in each XML instance 
  update XMLTest set
    [XML].modify('replace value of (root/item[flag="false" and frac > 0]/flag/text())[1] with "true"')
  where xml.exist('root/item[flag="false" and frac > 0]') = 1
end             
...