从xml中有效删除节点

时间:2016-04-06 22:51:04

标签: xml tsql xpath xml.modify

这是一个挑战。 下面的代码显示了从xml变量中删除某些行的工作方法。 目的是删除没有将primaryKey属性设置为1的行,其中oldValue和newValue属性相同。 (我的意思是,两者都可以为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

总之,问题是,我如何才能有效地实现这一目标?

1 个答案:

答案 0 :(得分:1)

  

&#34;目的是删除没有将primaryKey属性设置为1的行,其中oldValue和newValue属性相同。 (我的意思是,两者都可以为空或两者都具有相同的值)&#34;

可以将其转换为单个@xml.modify表达式,如下所示(在SQL Server 2008R2中测试并使用):

set @xml.modify('delete /changes/column[not(@primaryKey=1) and not(@oldValue!=@newValue)]')