【问题标题】:Querying XML that has multiple sub-entities查询具有多个子实体的 XML
【发布时间】:2016-12-02 03:19:42
【问题描述】:

我对如何在 SQL Server 2008+ 中查询 XML 有基本的了解。基本的。但是我很难从这个简单的 XML 中得到我想要的东西,今天下午我已经在 SO 和整个网络上搜索了很长一段时间,但还没有找到神奇的词来寻求帮助。

鉴于此 XML:

declare @xml xml =
'<?xml version="1.0" encoding="utf-8"?>
<Customers>
  <Customer id="12345" name="John Doe" addr1="123 Somewhere Ln" city="Riverside" state="CA">
    <Children>Jane</Children>
    <Children>John Jr.</Children>
    <Children>Susan</Children>
  </Customer>
</Customers>
<Customers>
  <Customer id="97531" name="Ben Franklin" addr1="456 Anywhere Dr" city="Albuquerque" state="NM">
    <Children>Andrew</Children>
    <Children>Adam</Children>
  </Customer>
</Customers>'

我可以运行此查询并获取 ID 和名称:

select cust.col.value('@id[1]','int') as id,
       cust.col.value('@name[1]','varchar(30)') as name
  from @xml.nodes('/Customers/Customer') as cust(col)

id     name
12345  John Doe
97531  Ben Franklin

但是,接下来我想要的是每个孩子的 id 和 name,但我无法弄清楚需要什么才能得到它。 IOW,我想要这个:

id      child
12345   Jane
12345   John Jr.
12345   Susan
97531   Andrew
97531   Adam

请注意,我需要列式数据,而不是 XML。

那么,什么 SELECT 会从那个 xml 中给我这些结果?

谢谢!

【问题讨论】:

    标签: sql xml sql-server-2008 tsql


    【解决方案1】:

    根据您的查询,只需在 Children 元素上添加 CROSS APPLY。现在您可以从CustomerChildren 元素中选择数据:

    select cust.col.value('@id','int') as id,
           child.col.value('.','varchar(30)') as child
    from @xml.nodes('/Customers/Customer') as cust(col)
        cross apply cust.col.nodes('Children') as child(col)
    

    输出:

    id          child
    ----------- ------------------------------
    12345       Jane
    12345       John Jr.
    12345       Susan
    97531       Andrew
    97531       Adam
    

    注意. 用于引用当前元素上下文;而且,在 XML 中,同一个父元素中不能有两个同名的属性,因此不需要@id[1] 中的索引器。

    【讨论】:

    • 完美。在我发布这个之后我做了一些探索之后发现了 CROSS APPLY,但是我尝试了我能想到的一切来获得孩子的名字,但没有成功。我从未见过'。前。我得到了这些东西,但我仍然不了解它。非常感谢!
    • 除了我在这个答案中写的内容之外,. 在这种情况下引用了Children 元素,因为它用于child.col
    • ...别忘了接受这个答案 (read more)。谢谢
    【解决方案2】:

    你可以:

    select cust.col.value('../@id','int') as id,
           cust.col.value('../@name','varchar(30)') as name,
           cust.col.value('.','varchar(30)') as child
      from @xml.nodes('/Customers/Customer/Children') as cust(col)
    

    得到:

    id      name            child
    12345   John Doe        Jane
    12345   John Doe        John Jr.
    12345   John Doe        Susan
    97531   Ben Franklin    Andrew
    97531   Ben Franklin    Adam
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多