我在SQL存储过程中有一个XML参数@Xml,如下所示:
<Root>
<Data>
<Id>1</Id>
<Name>Kevin</Name>
<Des>Des1</Des>
</Data>
<Data>
<Id>2</Id>
<Name>Alex</Name>
<Des>Des2</Des>
</Data>
<Data>
<Id>3</Id>
<Name>Amy</Name>
<Des>Des3</Des>
</Data>
</Root>
现在,我想在这个xml中删除几个节点,过滤器是这样的(Id = 2 AND Name ='Alex')OR(Id = 3 AND Name ='Amy'),我不想使用光标或类似的东西,只需用一个脚本来做,我尽力为此,但我无法得到答案,任何人都可以帮助我?在此先感谢!!!
输出应为:
<Root>
<Data>
<Id>1</Id>
<Name>Kevin</Name>
<Des>Des1</Des>
</Data>
</Root>
PS:过滤器是#table,所以,实际问题是,如何删除包含在#table中的XML中的特定记录?
Id Name
2 Alex
3 Amy
Declare @Xml XML
set @Xml = '<Root>
<Data>
<Id>1</Id>
<Name>Kevin</Name>
<Des>Des1</Des>
</Data>
<Data>
<Id>2</Id>
<Name>Alex</Name>
<Des>Des2</Des>
</Data>
<Data>
<Id>3</Id>
<Name>Amy</Name>
<Des>Des3</Des>
</Data>
</Root>'
create TABLE #tempResult
(
Id Int,
Name Varchar(10)
)
insert into #tempResult
values(2, 'Alex'), (3, 'Amy')
SET @Xml = (
SELECT Node.value('Id[1]','int') AS PId, Node.value('Name[1]','Varchar(10)') AS PName
FROM @Xml.nodes('//Data') AS T(Node)
OUTER APPLY (
SELECT tr.Id, tr.Name
FROM #tempResult tr
WHERE Node.value('Id[1]','int') = tr.Id and Node.value('Name[1]','Varchar(10)') = tr.Name
) a
WHERE a.Id IS NULL
FOR XML PATH(''), TYPE
)
select @Xml
drop table #tempResult
我得到了这样的结果 1 凯文
但我需要整个xml包含Root节点:
<Root>
<Data>
<Id>1</Id>
<Name>Kevin</Name>
<Des>Des1</Des>
</Data>
</Root>
我怎样才能达到这个目标?有帮助吗?我是SQL to XML的新专家,请帮助我!!!
答案 0 :(得分:1)
我得到了答案,谢谢你们所有人
declare @xml xml
set @xml = '<Root><Header>123</Header><Data><Id>1</Id><Name>Kevin</Name><Des>Des1</Des></Data><Data><Id>2</Id><Name>Alex</Name><Des>Des2</Des></Data><Data><Id>3</Id><Name>Amy</Name><Des>Des3</Des></Data><Tail>456</Tail></Root>'
--set @xml.modify('delete /Root/Data[(Id[.=1] and Name[.="Kevin"]) or (Id[.=2] and Name[.="Alex"])]')
select @xml
declare @parameter XML
set @parameter = (SELECT Node.value('(Id)[1]', 'Int') AS Id,
Node.value('(Name)[1]', 'Varchar(10)') AS Name
FROM @xml.nodes('Root/Data') TempXML(Node)
WHERE Node.value('(Id)[1]', 'Int') != 3
for xml path('Root'), TYPE)
--select @parameter
declare @sql nvarchar(max)
set @sql = convert(nvarchar(max),
@parameter.query('for $i in (/Root) return concat("(Id[.=",
string($i/Id[1]),
"] and Name[.=""",
string($i/Name[1]),
"""]) or")')
)
set @sql = '['+substring(@sql,0,len(@sql)-2)+']'
set @sql = 'set @xml.modify(''delete /Root/Data'+@sql+''')'
select @sql
exec sp_executesql @sql, N'@xml xml output', @xml output
select @xml
答案 1 :(得分:1)
您可以在根节点@xml.nodes('/Root/*')
中的节点上粉碎xml,并使用碎片节点R.X.query('.')
中的XML重建它。
在where not exists
子句中,排除临时表中存在的数据节点。
select R.X.query('.')
from @xml.nodes('/Root/*') as R(X)
where not exists (
select *
from #tempResult as T
where T.Id = R.X.value('(Id/text())[1]', 'int') and
T.Name = R.X.value('(Name/text())[1]', 'varchar(100)') and
R.X.value('local-name(.)', 'varchar(100)') = 'Data'
)
for xml path(''), root('Root'), type
结果:
<Root>
<Header>123</Header>
<Data>
<Id>1</Id>
<Name>Kevin</Name>
<Des>Des1</Des>
</Data>
<Tail>456</Tail>
</Root>