2017-02-07 7 views
0

я иметь следующую структуру XML:Чтение динамических узлов XML в SQL Server

set @MailXML = 
'<MailingCompany> 
    <Mailman> 
     <Name>Jamie</Name> 
      <Age> 24 </Age> 
      <Letter> 
      <DestinationAddress> 440 Mountain View Parade </DestinationAddress> 
      <DestinationCountry> USA </DestinationCountry> 
       <OriginCountry> Australia </OriginCountry> 
      <OriginAddress> 120 St Kilda Road </OriginAddress> 
      </Letter> 
    </Mailman> 
</MailingCompany>' 

My SQL в настоящее время выглядит следующим образом:

-- Mail Insertion 
INSERT INTO mailDB.dbo.Mailman 
    SELECT 
     m.value('Name[1]','varchar(50)') as Name, 
     m.value('Age[1]','varchar(50)') as Age 
    FROM 
     @MailXML.nodes('/MailingCompany/Mailman') as A(m) 

SET @MailPersonFK = SCOPE_IDENTITY(); 

-- Letter Insertion 
INSERT INTO mailDB.dbo.Letter 
    SELECT 
     l.value('DestinationAddress[1]', 'varchar(50)') as DestinationAddress, 
     l.value('DestinationCountry[1]', 'varchar(50)') as DestinationCountry, 
     l.value('OriginCountry[1]', 'varchar(50)') as OriginCountry, 
     l.value('OriginAddress[1]', 'varchar(50)') as OriginAddress 
     @MailPersonFK as MailID 
    FROM 
     @MailXML.nodes('MailingCompany/Mailman/Letter') as B(l) 

Я пытаюсь извлечь Mailman и буквенные данные в их собственные таблицы. Тем не менее, у меня есть работа, но моя проблема в том, что узел MailCompany является динамическим. Иногда это может быть, например, MailVehicle, и мне все еще нужно , чтобы прочитать соответствующие данные узла Mailman и Letter и вставить их в свои соответствующие таблицы.

Так как

FROM @MailXML.nodes('/MailingCompany/Mailman') as A(t) 

и

FROM @MailXML.nodes('MailingCompany/Mailman/Letter') as B(l) 

Будет необходимо изменить, чтобы позволить MailingCompany быть динамичным.

Я попытался извлечь родительский узел и сцепить его в строку поместить в .nodes функционировать как следующее:

set @DynXML = '/' + @parentNodeVar + '/Mailman' 

FROM @MailXML.nodes(@DynXML) as A(t) 

Однако я получаю следующее сообщение об ошибке:

The argument 1 of the XML data type method "nodes" must be a string literal.

Как я могу преодолеть эту динамическую проблему XML?

Большое спасибо заранее

+0

согласно моему пониманию, вы пытаетесь сказать, что Mailman и Letter никогда не меняются, но родительский узел Mailman может быть изменен. поэтому вам трудно получить данные Mailman и Letter .means, которые вы хотите динамически найти в Mailman и Letter узле из xml .Am iI Right? –

ответ

3

Посмотрите на этом уменьшенном Например:

DECLARE @xml1 XML= 
N'<MailingCompany> 
    <Mailman> 
    <Name>Jamie</Name> 
    <Letter> 
     <DestinationAddress> 440 Mountain View Parade </DestinationAddress> 
    </Letter> 
    </Mailman> 
</MailingCompany>'; 

DECLARE @xml2 XML= 
N'<OtherName> 
    <Mailman> 
    <Name>Jodie</Name> 
    <Letter> 
     <DestinationAddress> This is the other address </DestinationAddress> 
    </Letter> 
    </Mailman> 
</OtherName>'; 

SELECT @xml1.value(N'(*/Mailman/Name)[1]','nvarchar(max)') AS Mailman_Name 
     ,@xml1.value(N'(*/Mailman/Letter/DestinationAddress)[1]','nvarchar(max)') AS DestinationAddress 
SELECT @xml2.value(N'(*/Mailman/Name)[1]','nvarchar(max)') AS Mailman_Name 
     ,@xml2.value(N'(*/Mailman/Letter/DestinationAddress)[1]','nvarchar(max)') AS DestinationAddress 

Вы можете заменить имя узла с *.

Другой трюк является глубокий поиск с // (такой же результат, как и раньше):

SELECT @xml1.value(N'(//Name)[1]','nvarchar(max)') AS Mailman_Name 
     ,@xml1.value(N'(//DestinationAddress)[1]','nvarchar(max)') AS DestinationAddress 
SELECT @xml2.value(N'(//Name)[1]','nvarchar(max)') AS Mailman_Name 
     ,@xml2.value(N'(//DestinationAddress)[1]','nvarchar(max)') AS DestinationAddress 

Общее правило: быть как можно более конкретным.

+0

Удивительно, что это именно то, что я хотел. Спасибо @ Шнуго! – Mark

+0

У меня есть одна и та же проблема, но мне нужно также выбрать «OtherName» ... как я могу это сделать? Спасибо @Shnugo – Kunal