【问题标题】:How to using for loop using XQuery to delete xml nodes [duplicate]如何使用 XQuery 使用 for 循环删除 xml 节点 [重复]
【发布时间】:2014-03-07 15:12:42
【问题描述】:

我在 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'),我不想使用 Cursor 或类似的东西,只使用一个脚本来做到这一点,我尽我所能,但我无法得到答案,有人可以帮助我吗?提前谢谢!!!

输出应该是:

    <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>
  <Data>
    <Id>1</Id>
    <Name>Kevin</Name>
    <Des>Des1</Des>
  </Data>
</Root>

我怎样才能做到这一点?有什么帮助吗?我是 SQL 到 XML 的新手,请帮助我!!!

【问题讨论】:

  • 这个重复链接只是删除表中的特定记录,我想删除一个XML参数中的记录,这个不一样...
  • 完全没有区别。您只需要指向您的参数/变量而不是表格列,方法是相同的。
  • @JNK 建议的问题是关于使用另一个 XML 从 XML 中删除项目,这 与您的问题不同,但 one of the answers 确实包含对您有用的信息,提供在多种条件下删除多个节点的各种方法。您只需将列引用替换为变量的引用。
  • 我只是使用下面的脚本在数据库中执行,

标签: sql sql-server xml xquery


【解决方案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

【讨论】:

    【解决方案2】:

    您可以分解根节点@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>
    

    SQL Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 2010-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多