使用SQL Server将XML文件分解为单独的行

时间:2012-01-10 02:49:29

标签: sql-server xml sql-server-2008 xpath xquery

这就是我正在做的事情。我正在将XML文件插入XML列,以及其他列(如日期戳等)以进行日志记录(这些与此请求无关)

该文件看起来像这样:

<topLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
<topLevelItem>

我的目标是能够查询XML字段,并在其自己的行中以XML格式获取每个<secondLevelItem>的结果集。如下:

第1行:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

第2行:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

第3行:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

这必须使用Microsoft SQL Server并且不使用CLI来完成。我需要能够声明我想要分解哪个XML节点,因为有些文件具有我不需要的其他XML元素。类似于WHERE node = secondLevelItem

3 个答案:

答案 0 :(得分:2)

使用SQL Server 2005及更高版本,SQL Server中提供了出色的XQuery支持。

此处的方法是使用.nodes().query()方法:

SELECT 
    Col.query('.')
FROM 
dbo.YourTable
CROSS APPLY
    YourXmlColumn.nodes('/topLevelItem/secondLevelItem') AS Tbl(Col)
WHERE
    (some condition)

.nodes()函数创建一个“临时,内联”伪表Tbl,其中包含一列Col,其中包含XML列中每个节点的一个XML条目,该条目与给定的XPath相匹配(在这种情况下:<secondLevelItem>内的每个<topLevelItem>都会匹配。

由于您需要每个XML元素的整个XML,只需使用.query('.')返回完整的XML元素。

答案 1 :(得分:1)

使用nodes()粉碎XML并使用local-name()sql:variable()查找所需的节点,使用query()检索XML。

declare @NodeName varchar(100) = 'secondLevelItem'

select T.N.query('.')
from YourTable
  cross apply XMLCol.nodes('//*[local-name()=sql:variable("@NodeName")]') as T(N)

答案 2 :(得分:1)

如果您只是将原始XML提供给存储过程而不是从表中提取,则可以执行以下操作。

DECLARE @XML xml
SET @XML = '<topLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>One</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>One One</secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>Two</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>Two Two</secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>Three</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>Three Three</secondLevelItemAnotherDetail>
  </secondLevelItem>
</topLevelItem>'


SELECT 
    Tbl.Col.query('.')
FROM 
    @XML.nodes('/topLevelItem/secondLevelItem') AS Tbl(Col)