TSQL需要根据具有条件

时间:2016-10-24 16:54:34

标签: sql-server xml tsql xpath xquery

我得到了这样的XML:

<root>
     <child1>
             <...../>
             <...../>
             <...../>
             <child2>
                     <child3>Value1</child3>
                     <child3>Value2</child3>
                     <child3>Value3</child3>
             </child2>
     </child1>
</root>

我已经搜索了几天但是找不到我遇到的这个问题的合适答案。

基本上,我想从child1及其所有子节点中删除root节点value(在这种情况下,Value1){{1}但是,可能有多个child3个节点,如果它有我想要的值,我想保留child3(在这种情况下,它可以是child3Value2) ,即使它有一个值(Value3)我试图删除。

目前,这就是我正在使用的。

Value1

我想做的是

set @xml.modify('delete root/child1[child2[child3 = "Value1"]]')

基本上,不要删除包含我想要的子数据的节点,即使它具有我不想要的特定值,然后删除我不想要的每个节点其他情况。

通过查询set @xml.modify('delete root/child1[child2[child3 = "Value1"] AND !(child2[child3 = "Value2"] OR child2[child3 = "Value3"])]') 节点中的ID并进行大量预备工作,还有其他方法可以实现此目的,但我希望尽可能整合代码或者拥有比这更智能的代码。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用XML.modify()方法和contains函数(not(contains..)):

DECLARE @x xml = N'<root>
<child1>
    <child2>
        <child3>Value1</child3>
        <child3>Value2</child3>
        <child3>Value3</child3>
    </child2>
</child1>
<child1>
    <child2>
        <child3>Value1</child3>
        <child3>Value4</child3>
        <child3>Value5</child3>
    </child2>
</child1>
<child1>
    <child2>
        <child3>Value5</child3>
        <child3>Value2</child3>
        <child3>Value6</child3>
    </child2>
</child1>
</root>'


SET @x.modify('delete /root/child1[contains(.,"Value1") and (not(contains(.,"Value2")) or not(contains(.,"Value3")))]')

SELECT @x

输出将是:

<root>
  <child1>
    <child2>
      <child3>Value1</child3>
      <child3>Value2</child3>
      <child3>Value3</child3>
    </child2>
  </child1>
  <child1>
    <child2>
      <child3>Value5</child3>
      <child3>Value2</child3>
      <child3>Value6</child3>
    </child2>
  </child1>
</root>

答案 1 :(得分:0)

我不知道,如果我确实得到了这个,但你可以用FLWOR-query() - 级联来解决这个问题:

DECLARE @xml xml = 
N'<root>
    <child1 id="1" type="Is to be deleted completely">
        <child2>
            <child3>Value1</child3>
        </child2>
        <child2>
            <child3>Value1</child3>
        </child2>
    </child1>

    <child1 id="2" type="Should remain but those with the search value should be deleted">
        <child2>
            <child3>Value1</child3>
            <child3>Other a</child3>
            <child3>Other c</child3>
        </child2>
    </child1>

    <child1 id="3" type="First child2 delete, second just delete the one with delete value, third untouched">
        <child2>
            <child3>Value1</child3>
        </child2>
        <child2>
            <child3>Value1</child3>
            <child3>Other a</child3>
            <child3>Other c</child3>
        </child2>
        <child2>
            <child3>Other a</child3>
            <child3>Other c</child3>
        </child2>
    </child1>

    <child1 id="4" type="Untouched, no search value">
        <child2>
            <child3>Other m</child3>
        </child2>
        <child2>
            <child3>Other n</child3>
        </child2>
    </child1>
</root>';

DECLARE @DeleteValue NVARCHAR(100)='Value1';
  • 第一个FLWOR-query()将重建XML而不带有带有搜索值的节点

  • 第二个FLWOR-query()将删除所有没有内容的child2元素

  • 第三个FLWOR-query()将删除所有没有内容的child1元素

这是查询:

SELECT @xml.query
(
N'
<root>
    {
    for $c1 in /root/child1
    return
        <child1> {$c1/@*}
        {
        for $c2 in $c1/child2
        return
            <child2> {$c2/@*}
            {
            for $c3 in $c2/child3[text()!=sql:variable("@DeleteValue")]
            return $c3 
            }
            </child2>
        }
        </child1>
    }
</root>'
).query 
(
N'
<root>
{
    for $c1 in /root/child1
    return
        <child1> {$c1/@*}
        {
        for $c2 in $c1/child2[string-length(.)!=0]
        return $c2 
        }
        </child1>
}
</root>'
).query
(
N'
<root>
{
    for $c1 in /root/child1[string-length(.)!=0]
    return $c1 
}
</root>'
);

这是结果

<root>
  <child1 id="2" type="Should remain but those with the search value should be deleted">
    <child2>
      <child3>Other a</child3>
      <child3>Other c</child3>
    </child2>
  </child1>
  <child1 id="3" type="First child2 delete, second just delete the one with delete value, third untouched">
    <child2>
      <child3>Other a</child3>
      <child3>Other c</child3>
    </child2>
    <child2>
      <child3>Other a</child3>
      <child3>Other c</child3>
    </child2>
  </child1>
  <child1 id="4" type="Untouched, no search value">
    <child2>
      <child3>Other m</child3>
    </child2>
    <child2>
      <child3>Other n</child3>
    </child2>
  </child1>
</root>