Вставка и обновление нескольких записей XML в SQL 2008 - решение, но, возможно, не правильное? - PullRequest
1 голос
/ 28 июня 2011

Хорошо, поэтому у меня есть два следующих теста / примера запросов для вставки и обновления данных из XML в таблицу SQL 2008. Довольно простой факт в том, что входящая структура XML будет соответствовать структуре таблицы SQL (ну, конечно, в обновлении есть только необходимые поля - снова только пример).

ВСТАВИТЬ ЗАЯВЛЕНИЕ

declare @passedXML xml
set @passedXML='<root><record><name>Sam</name><age>37</age><comments /></record><record><name>Dan</name><age>32</age><comments /></record></root>'

insert into test (name, age, comments)
select  x.record.query('name').value('.', 'varchar(255)'),
        x.record.query('age').value('.', 'int'),
        x.record.query('comments').value('.','varchar(255)')
from @passedXML.nodes('root/record') as x(record)

Так что никаких проблем, две XML-записи вставляются по мере необходимости. Теперь перейдем к выражению UPDATE:

ОБНОВЛЕНИЕ ОБНОВЛЕНИЯ

declare @passedXML xml
set @passedXML='<root><record><id>3</id><comments>This is a new comment</comments></record><record><id>2</id><comments>Michael Michael</comments></record></root>'
update test
set comments = (select  x.record.query('comments').value('.','varchar(255)')
    from @passedXML.nodes('root/record') as x(record)
    where id = x.record.query('id').value('.','bigint'))

Хорошо, значит, обновление работает - для двух «записей» XML поле комментариев обновляется на основе переданного

МОЙ ВОПРОС ЕСТЬ

Конечно, учитывая приведенный выше пример UPDATE, предложение where взято из XML, а не из таблицы TEST. Поэтому, когда выполняется UPDATE, запрос говорит 100 (если, скажем, это количество записей в таблице TEST) записей обновлено .. конечно, только две (в этом случае) записи были обновлены, но SQL должен был пройти через всю таблицу ?? Я полагаю, есть ли способ каким-то образом иметь предложение where из XML, присоединенного к базовой таблице TEST, если это имеет смысл? то есть ограничить ТЕСТ только обновленными элементами?

1 Ответ

2 голосов
/ 28 июня 2011

Позвольте мне немного изменить ваш запрос на обновление:

  declare @passedXML xml
set @passedXML='<root><record><name>Sam</name><age>37</age><comments /></record><record><name>Dan</name><age>32</age><comments /></record></root>'

DECLARe @test TABLE (id bigint IDENTITY(1,1),name nvarchar(100), age int, comments varchar(255))
insert into @test (name, age, comments)
select  x.record.query('name').value('.', 'varchar(255)'),
        x.record.query('age').value('.', 'int'),
        x.record.query('comments').value('.','varchar(255)')
from @passedXML.nodes('root/record') as x(record)


set @passedXML='<root><record><id>99999</id><comments>This is a new comment</comments></record><record><id>2</id><comments>Michael Michael</comments></record></root>'
; with CTE as( 
SELECT  x.record.query('comments').value('.','varchar(255)') comment,
        x.record.query('id').value('.','int') id
    from @passedXML.nodes('root/record') as x(record))
update @test
set comments = cte.comment
FROM @test T
JOIN CTE oN cte.id=t.id

Результат обновления: (1 row(s) affected)

Сервер SQL достаточно умен, чтобы не обновлять каждую строку.Если вы посмотрите на план выполнения, вы увидите, что в хеш-совпадении есть только одно действительное количество строк, а не две:

enter image description here

@@ RoWCOUNT покажет вам тоже 1, и оновсе в порядке.

В вашем примере вы обновляете каждую строку (если в XML такого идентификатора нет, в комментариях должен быть вставлен NULL)

...