Эффективно удалять узлы из xml
Вот вызов. Приведенный ниже код демонстрирует рабочий метод удаления некоторых строк из переменной xml. Намерение состоит в том, чтобы удалить строки, у которых атрибут primaryKey не установлен в 1, где атрибуты oldValue и newValue совпадают. (я имею в виду одно и то же, оба могут иметь значение null или оба имеют одинаковое значение) Код ниже демонстрирует это. Тем не менее, код ниже использует курсор. Меня не удивит, если удастся выполнить удаление, используя один @ml.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 ответ
"Намерение состоит в том, чтобы удалить строки, у которых атрибут primaryKey не установлен в 1, где атрибуты oldValue и newValue одинаковы. (Я имею в виду, что оба могут иметь значение null или оба имеют одинаковое значение)"
Это может быть переведено в единый @xml.modify
выражение следующим образом (протестировано и работало в SQL Server 2008R2):
set @xml.modify('delete /changes/column[not(@primaryKey=1) and not(@oldValue!=@newValue)]')