我在MS SQL Server 2012数据库中有一个XML列,我需要创建一个查询,将节点提取到表中。以下是XML结构的要点:
<root>
<ProjectInfo>
<PrimaryContact>
<Name>
<Phone>
<Email>
</PrimaryContact>
<SecondaryContact>
<Name>
<Phone>
<Email>
</SecondaryContact>
<TechnicalContact>
<Name>
<Phone>
<Email>
</TechnicalContact>
<BillingContact>
<Name>
<Phone>
<Email>
</BillingContact>
<OtherStuff>
</root>
我正在尝试编写一个查询,从每个Contact节点获取Name,Phone和Email。遗憾的是,XPath /root/*Contact/
不合法。我知道我可以编写一个结合了大量UNION
s的查询来合并列,但我觉得可能有一种我目前不知道的更简单的方法。
有没有办法使用通配符或某种OR-ing机制,可用于检索名称,电话和&amp;来自每个* Contact节点的电子邮件?
注意:我无法使用/root/*/Name
,因为还有其他节点将Name作为下一个内部节点,而不是联系人,而Phone&amp;电子邮件都是可选字段。
答案 0 :(得分:1)
您可以查看此工作示例:
DECLARE @xml XML=
'<root>
<ProjectInfo>
<Name value="this not"/>
</ProjectInfo>
<PrimaryContact>
<Name value="x"/>
<Phone value="y"/>
<Email value="z"/>
</PrimaryContact>
<SecondaryContact>
<Name value="a"/>
<Phone value="b"/>
<Email value="c"/>
</SecondaryContact>
<TechnicalContact>
<Name value="e"/>
<Phone value="f"/>
<Email value="g"/>
</TechnicalContact>
<BillingContact>
<Name value="m"/>
<Phone value="n"/>
<Email value="o"/>
</BillingContact>
<OtherStuff>
<Name value="don''t include"/>
</OtherStuff>
</root>';
SELECT Level1.value('local-name(.)','nvarchar(max)') AS Level1_Name
,Level2.value('local-name(.)','nvarchar(max)') AS Level2_Name
,Level2.value('@value','nvarchar(max)') AS Level2_Value
FROM @xml.nodes('/root/*[fn:contains(local-name(),"Contact")]') A(Level1)
CROSS APPLY Level1.nodes('*') AS B(Level2);
结果
+------------------+-------+---+
| PrimaryContact | Name | x |
+------------------+-------+---+
| PrimaryContact | Phone | y |
+------------------+-------+---+
| PrimaryContact | Email | z |
+------------------+-------+---+
| SecondaryContact | Name | a |
+------------------+-------+---+
| SecondaryContact | Phone | b |
+------------------+-------+---+
| SecondaryContact | Email | c |
+------------------+-------+---+
| TechnicalContact | Name | e |
+------------------+-------+---+
| TechnicalContact | Phone | f |
+------------------+-------+---+
| TechnicalContact | Email | g |
+------------------+-------+---+
| BillingContact | Name | m |
+------------------+-------+---+
| BillingContact | Phone | n |
+------------------+-------+---+
| BillingContact | Email | o |
+------------------+-------+---+
只需删除[fn:contains(local-name(),"Contact")]
,您就会看到ProjectInfo
和OtherStuff
的名称 - 值。
如果您需要并排使用列,则可以使用PIVOT
SELECT p.*
FROM
(
SELECT Level1.value('local-name(.)','nvarchar(max)') AS Level1_Name
,Level2.value('local-name(.)','nvarchar(max)') AS Level2_Name
,Level2.value('@value','nvarchar(max)') AS Level2_Value
FROM @xml.nodes('/root/*[fn:contains(local-name(),"Contact")]') A(Level1)
CROSS APPLY Level1.nodes('*') AS B(Level2)
) AS tbl
PIVOT
(
MIN(Level2_Value) FOR Level2_Name IN(Name,Phone,Email)
) AS p;
结果:
+------------------+------+-------+-------+
| Level1_Name | Name | Phone | Email |
+------------------+------+-------+-------+
| BillingContact | m | n | o |
+------------------+------+-------+-------+
| PrimaryContact | x | y | z |
+------------------+------+-------+-------+
| SecondaryContact | a | b | c |
+------------------+------+-------+-------+
| TechnicalContact | e | f | g |
+------------------+------+-------+-------+