2015-04-23 2 views
3
Declare @MainXml XML = 
'<?xml version="1.0" encoding="utf-8"?> 
<result> 
<cash number="10"> 
<account amt="11.00" status="Closed"/> 
<account amt="12.00" status="Closed"/>      
</cash>   
<cash number="20"> 
<account amt="21.00" status="Closed"/> 
<account amt="22.00" status="Closed"/>      
</cash>   
</result>' 

Читаю данные, используя следующий запросЧтение XML повторяющиеся теги в SQL сервере

Declare @Innerxml xml; 
SELECT @Innerxml = T.c.query('<result>{/result/cash}</result>') 
FROM @MainXml.nodes('result') T(c) 

SELECT 
Result.Claim.value('(./@number)[1]','varchar(max)') as C1, 
Result.Claim.value('(./@amt)[1]','varchar(max)') as C2, 
Result.Claim.value('(./@status)[1]','varchar(max)') as C3 
From @Innerxml.nodes('/result/cash/account') Result(Claim) 

Я хочу читать XML и хранить в БД, как показано ниже.

C1 C2  C3 
---------------- 
10 11.00 Closed 
10 12.00 Closed 
20 21.00 Closed 
20 22.00 Closed 

но мой запрос возвращает NULL только в C1 колонке Пожалуйста, помогите мне здесь. Заранее спасибо

ответ

2

Вы не должны использовать родительские оси в запросах XML в SQL Server. Созданный план запроса будет O (n). Для каждого узла в XML проверяется все узлы в XML.

Сначала наклеить на result/cash, а затем наклейку на account в кресте.

select C.X.value('@number', 'varchar(max)') as C1, 
     A.X.value('@amt', 'varchar(max)') as C2, 
     A.X.value('@status', 'varchar(max)') as C3 
from @MainXml.nodes('result/cash') as C(X) 
    cross apply C.X.nodes('account') as A(X) 

Я не вижу смысла создавать вторую переменную XML. Используйте @MainXML напрямую.

+0

Хотя это звучит логично, я не уверен, что это всегда так. Я считаю, что я видел запросы с '..', иногда выполняемыми лучше, чем те, у которых несколько применений, например, но у меня нет точного примера на данный момент. Тем не менее, было бы интересно проверить его –

+0

Также я не согласен с тем, что план будет «O (n^2)», он должен быть линейным, потому что каждый узел имеет только один родительский –

+0

@ RomanPekar посмотреть на http: // stackoverflow.com/questions/24196516/cross-apply-xml-query-performs-exponential-worse-as-xml-document-grows –

2

@number является атрибутом <cash>, но ваш контекстный узел - <account>. Вам нужно подойти к дереву XML на один уровень, чтобы перейти к узлу <cash> перед доступом к атрибуту. Вы можете сделать .., чтобы добраться до родительского текущего узла в XPath:

SELECT 
Result.Claim.value('(../@number)[1]','varchar(max)') as C1, 
Result.Claim.value('(./@amt)[1]','varchar(max)') as C2, 
Result.Claim.value('(./@status)[1]','varchar(max)') as C3 
From @Innerxml.nodes('/result/cash/account') Result(Claim) 
+0

Большое вам спасибо .. Вы сделали свой день .. – user1893874

Смежные вопросы