从两级XML列表中提取值到SQL列

3

我有一个SQL Server 2008数据库,从中提取了多个来自不同表的值,将其放入单个表中。其中包括从XML中提取的一些数据,最近这些数据被存储在单个级别上,例如:

<XMLData>
  <Item>
    <Name>Name1</Name>
    <Value>Value1</Value>
  </Item>
  <Item>
    <Name>Name2</Name>
    <Value>Value2</Value>
  </Item>
  <Item>
    <Name>Name3</Name>
    <Value>Value3</Value>
  </Item>
  <Item>
    <Name>Name4</Name>
    <Value>Value4</Value>
  </Item>
</XMLData>

我会使用以下方法提取所需信息:
SELECT
   Name = IXML.value('(./Name)[1]', 'varchar(20)'),
   Value = IXML.value('(./Value)[1]', 'varchar(20)')
INTO dbo.newTable
FROM dbo.oldTable
CROSS APPLY oldTable.InfoXML.nodes('/XMLData/item') Book(IXML)

这将返回:

Name    Value
--------------
Name1   Value1
Name2   Value2
Name3   Value3
Name4   Value4

然而,现在XML列表已经改变,并在另一个列表内生成,如下所示:
<XMLData>
<LongDirectory>
  <Category>
    <Item>
      <CategoryName>Cat1</CategoryName>
      <SubCategory>
        <Item>
          <Name>Name1</Name>
          <Value>Value1</Value>
        </Item>
        <Item>
          <Name>Name2</Name>
          <Value>Value2</Value>
        </Item>
        <Item>
          <Name>Name3</Name>
          <Value>Value3</Value>
        </Item>
      </SubCategory>
    </Item>
    <Item>
      <CategoryName>Cat2</CategoryName>
      <SubCategory>
        <Item>
          <Name>Name4</Name>
          <Value>Value4</Value>
        </Item>
        <Item>
          <Name>Name5</Name>
          <Value>Value5</Value>
        </Item>
      </SubCategory>
    </Item>
    <Item>
      <CategoryName>Cat3</CategoryName>
      <SubCategory>
        <Item>
          <Name>Name6</Name>
          <Value>Value6</Value>
        </Item>
        <Item>
          <Name>Name7</Name>
          <Value>Value7</Value>
        </Item>
      </SubCategory>
    </Item>
  </Category>
</LongDirectory>
</XMLData>

我需要生成的信息看起来像这样:

Name    Value    Category
-------------------------
Name1   Value1   Cat1
Name2   Value2   Cat1
Name3   Value3   Cat1
Name4   Value4   Cat2
Name5   Value5   Cat2
Name6   Value6   Cat3
Name7   Value7   Cat3

我该如何修改查询以适应结构变化?非常感谢您的帮助。

1个回答

0

您可以使用嵌套的nodes()方法来完成:

select
    I.C.value('(Name)[1]', 'varchar(20)') as Name,
    I.C.value('(Value)[1]', 'varchar(20)') as Value,
    C.C.value('(CatName)[1]', 'varchar(20)') as Category
-- into dbo.newTable
from dbo.oldTable as T
    cross apply T.InfoXML.nodes('XMLData/Category') as C(C)
    cross apply C.C.nodes('Item') as I(C)

或者使用parent轴 (..):

select
    I.C.value('(Name)[1]', 'varchar(20)') as Name,
    I.C.value('(Value)[1]', 'varchar(20)') as Value,
    I.C.value('(../CatName)[1]', 'varchar(20)') as Category
-- into dbo.newTable
from dbo.oldTable as T
    cross apply T.InfoXML.nodes('XMLData/Category/Item') as I(C)

SQL Fiddle 示例


更新

select
    I.C.value('(Name)[1]', 'varchar(20)') as Name,
    I.C.value('(Value)[1]', 'varchar(20)') as Value,
    C.C.value('(CategoryName)[1]', 'varchar(20)') as Category
from dbo.oldTable as T
    outer apply T.InfoXML.nodes('XMLData/LongDirectory/Category/Item') as C(C)
    outer apply C.C.nodes('SubCategory/Item') as I(C)

sql fiddle example


我使用了你发布的第一种方法,它成功生成了所有值,但是似乎每个类别值都会重复每个条目(至少根据我的测试数据,我认为它与类别值的数量有关)。因此,当从一个包含3个类别的XML页面中提取时,所有行都会出现三次。我记得以前遇到过这个问题,但是想不起来我的解决方案是什么。有什么想法吗? - Justin RLA
你能否添加一个XML示例,以便你可以看到这样的重复吗? - Roman Pekar
我已经更新了原始问题中的XML,使其与实际情况相符。 - Justin RLA
那么我该如何确定我正在从哪个表(标记为dbo.oldTable)提取xml?新表从多个表中提取各种信息(包括我正在获取xml的表中的其他列)。 - Justin RLA
找到了重复的问题。有人在我不知情的情况下修改了我提取的另一个表格(与这些值无关),这导致生成了重复项,影响了我的整个表格,所以这与此问题无关。@Roman 感谢您的帮助! - Justin RLA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接