2016-06-27 6 views
0

MS SQL Server 2012データベースに、ノードをテーブルに抽出するためのクエリを作成するために必要なXML列があります。 XML構造の要点は次のとおりです。SQL Server 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> 

各連絡先ノードから名前、電話番号、メールアドレスを取得するクエリを作成しようとしています。 XPath /root/*Contact/は残念なことに法的ではありません。私はUNIONの列を結合する束を組み合わせたクエリを書くことができることを知っていますが、おそらく私が現在認識していない簡単な方法があるように感じます。

名前、電話番号、&各* Contactノードから電子メールを取得するために使用できるワイルドカードまたは何らかのORメカニズムを使用する方法はありますか?

注:は、連絡先ではない次の内部ノードとして名前を持つノードがあり、電話番号&電子メールは両方ともオプションフィールドですから使用できません。

答えて

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  | 
+------------------+------+-------+-------+ 
+0

感謝を!これは私が探していたものです。私は、単一の静的なドキュメントではなく、XML列に格納されているすべてのドキュメントにこれを全面的に適用する必要があります。 – JNYRanger