1

これが挑戦です。以下のコードは、xml 変数からいくつかの行を削除する実際の方法を示しています。その意図は、oldValue 属性と newValue 属性が同じである primaryKey 属性が 1 に設定されていない行を削除することです。(つまり、両方とも null にすることも、両方を同じ値にすることもできます) 以下のコードは、これが起こっていることを示しています。ただし、以下のコードではカーソルを使用しています。単一の @xml.modify を使用して、または少なくともカーソルを使用することなく削除を実行できたとしても、私は驚かないでしょう。

declare @xml xml ='<changes schemaName="Security" tableName="AccessProfiles">
  <column name="AccessProfileId" primaryKey="1" oldValue="114" newValue="114" />
  <column name="AccessProfileName" oldValue="test" newValue="Testing" />
  <column name="DeleteMeSame" oldValue="testValue" newValue="testValue" />
  <column name="DeleteMeNull" />
  <column name="KeepMePrimaryNull" primaryKey="1" />
  <column name="KeepMePrimarySame" primaryKey="1" oldValue="sameValue" newValue="sameValue"/>
</changes>';

declare @columnName sysname;

declare deleteNodesCursor cursor fast_forward for
    with shreddedXml as (
        select
            N.value( '@name' , 'sysname' ) as name,
            N.value( '@primaryKey' , 'bit' ) as primaryKey,
            N.value( '@oldValue' , 'varchar(max)' ) as oldValue,
            N.value( '@newValue' , 'varchar(max)' ) as newValue
        from @xml.nodes('/changes/column') as T(N)
    )
    select
        Name
    from shreddedXml
    where primaryKey is null
    and (oldValue = newValue
    or  (oldValue is null and newValue is null))

open deleteNodesCursor

while (1=1)
begin
    fetch next from deleteNodesCursor into @columnName
    if @@fetch_status != 0
        break;

    set @xml.modify( 'delete /changes[1]/column[@name= sql:variable("@columnName")]' )
end;

close deleteNodesCursor;
deallocate deleteNodesCursor;

select @xml

要約すると、問題は、これを効率的に達成するにはどうすればよいかということです。

4

1 に答える 1

1

「意図は、oldValue 属性と newValue 属性が同じである 1 に設定された primaryKey 属性を持たない行を削除することです。(つまり、両方が null になるか、両方が同じ値を持つ可能性があります)」

これは、次のように単一の式に変換できます@xml.modify(SQL Server 2008R2 でテストおよび動作しました)。

set @xml.modify('delete /changes/column[not(@primaryKey=1) and not(@oldValue!=@newValue)]')
于 2016-04-07T00:46:06.293 に答える