SQL 服务器 XML 列中的部分通配符搜索
Partial Wildcard Searches in SQL Server XML Columns
我在 MS SQL Server 2012 数据库中有一个 XML 列,我需要为其创建一个查询以将节点提取到 table 中。这是 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>
我正在尝试编写一个查询,从每个联系人节点获取姓名、Phone 和电子邮件。不幸的是,XPath /root/*Contact/
不合法。我知道我可以编写一个组合了一堆 UNION
的查询来合并列,但我觉得可能有一种我目前不知道的更简单的方法。
有没有办法使用通配符或某种 OR-ing 机制来从每个 *Contact 节点检索姓名、Phone 和电子邮件?
注意:我不能使用 /root/*/Name
,因为还有其他节点将 Name 作为下一个不用于联系人的内部节点,并且 Phone 和 Email 都是可选字段。
您可以看看这个工作示例:
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 |
+------------------+------+-------+-------+
我在 MS SQL Server 2012 数据库中有一个 XML 列,我需要为其创建一个查询以将节点提取到 table 中。这是 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>
我正在尝试编写一个查询,从每个联系人节点获取姓名、Phone 和电子邮件。不幸的是,XPath /root/*Contact/
不合法。我知道我可以编写一个组合了一堆 UNION
的查询来合并列,但我觉得可能有一种我目前不知道的更简单的方法。
有没有办法使用通配符或某种 OR-ing 机制来从每个 *Contact 节点检索姓名、Phone 和电子邮件?
注意:我不能使用 /root/*/Name
,因为还有其他节点将 Name 作为下一个不用于联系人的内部节点,并且 Phone 和 Email 都是可选字段。
您可以看看这个工作示例:
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 |
+------------------+------+-------+-------+