在XML列中查询一对多关系

时间:2020-07-29 23:16:16

标签: tsql sql-server-2012 cross-apply

我在表中有一个XML列。

表的外观包含两列:

  • ID
  • 部门XML

DepartmentXML通常如下所示:

<Root>
    <Department>
        <dID>100</dID>
        <DName>Engineering</DName>
    </Department>
    <Employee>
        <EmployeeID>999</EmployeeID>
        <EName>AAA BBB</EName>
    </Employee>
    <Employee>
        <EmployeeID>888</EmployeeID>
        <EName>XXX YYY</EName>
    </Employee>
</Root>

如何查询该XML,以得到这样的结果?

   +------------------------------------------+
   |dID|DepartmentName|EmployeeID|EmployeeName|
   +------------------------------------------+
   |100|Engineering   |999       |AAA BBB     |
   |100|Engineering   |888       |XXX YYY     |
   +------------------------------------------+

我知道可能必须使用CROSS APPLY,但是这种特殊情况的语法对我来说很难理解。

谢谢。

1 个答案:

答案 0 :(得分:1)

尝试这样:

首先创建一个模型表来模拟您的问题:

DECLARE @tbl TABLE(ID INT IDENTITY, DepartmentXml XML);
INSERT INTO @tbl VALUES
(N'<Root>
    <Department>
        <dID>100</dID>
        <DName>Engineering</DName>
    </Department>
    <Employee>
        <EmployeeID>999</EmployeeID>
        <EName>AAA BBB</EName>
    </Employee>
    <Employee>
        <EmployeeID>888</EmployeeID>
        <EName>XXX YYY</EName>
    </Employee>
</Root>');

-查询

SELECT t.ID
      ,t.DepartmentXml.value('(/Root/Department/dID/text())[1]','int') AS DepartmentId
      ,t.DepartmentXml.value('(/Root/Department/DName/text())[1]','nvarchar(max)') AS DepartmentName
      ,A.e.value('(EmployeeID/text())[1]','int') AS EmployeeId
      ,A.e.value('(EName/text())[1]','nvarchar(max)') AS EmployeeName
FROM @tbl t
OUTER APPLY t.DepartmentXml.nodes('/Root/Employee') A(e);

简而言之:

  • 我们可以直接选择行的ID
  • 我们可以直接从XML(非重复)中读取部门的信息
  • 我们可以将APPLY.nodes()一起使用来重复节点。
  • 我们可以对A.e使用相对的XPath来获取员工的数据