在SQL Server中读取动态XML节点

时间:2017-02-07 03:40:29

标签: sql sql-server xml database dynamic

我有以下XML结构:

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>'

我的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和Letter数据提取到各自的表中。我有这个工作,但我的问题是MailCompany节点是动态的。有时它可能是MailVehicle,例如,我仍然需要 读取相应的MailmanLetter节点数据,并将它们插入各自的表中。

所以两者

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)

但是我收到以下错误:

  

XML数据类型方法“nodes”的参数1必须是字符串文字。

如何克服这种动态XML问题?

非常感谢您提前

1 个答案:

答案 0 :(得分: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

一般规则:尽可能具体。