2016-06-27 4 views
0

У меня есть столбец XML в базе данных MS SQL Server 2012, который мне нужен для создания запроса для этого, который извлекает узлы в таблицу. Вот суть структуры XML:Частичные подстановочные знаки в столбцах XML SQL Server

<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 s, чтобы объединить столбцы, но я чувствую, что есть, вероятно, более простой способ, которого я в настоящее время не знаю.

Есть ли способ использовать подстановочные знаки или какой-либо механизм OR-ing, который может быть использован для извлечения имени, телефона, & Отправляется от каждого из * контактных узлов?

Примечание: Я не могу использовать /root/*/Name, потому что есть другие узлы, которые имеют имя как следующий внутренний узел, который не для контактов, а Телефон & Электронная почта являются необязательными.

ответ

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