1

さて、次の 2 つのテスト/サンプル クエリを使用して、XML から SQL 2008 テーブルにデータを INSERT および UPDATE します。着信 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)

したがって、問題はありません。必要に応じて 2 つの 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'))

よし、更新がうまくいった - 2 つの XML「レコード」のコメント フィールドが、渡された値に基づいて更新された。

私の質問は

もちろん、上記のサンプルの UPDATE では、WHERE 句は TEST テーブルではなく XML からのものです。したがって、UPDATE が実行されると、クエリは 100 を示します (たとえば、テーブル TEST にあるレコードの数) レコードが更新されました..もちろん、更新されたのは 2 つのレコード (この場合) だけですが、SQL はテーブル全体を実行する必要がありましたか?? それが理にかなっている場合、基になる TEST テーブルに添付された XML の where 句をどうにかして持つ方法があると思いますか? つまり、更新された項目のみに TEST を制限しますか?

4

1 に答える 1

2

更新クエリを少し変更させてください。

  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 サーバーは、すべての行を更新しないほどスマートです。実行計画を見ると、ハッシュ一致の実際の行数は 2 つではなく、1 つだけであることがわかります。

ここに画像の説明を入力

@@RoWCOUNT も 1 と表示されますが、問題ありません。

あなたの例では、すでにすべての行を更新しています(XMLにそのようなIDがない場合、コメントにNULLを挿入する必要があります)

于 2011-06-28T07:57:23.880 に答える