简体   繁体   中英

Inserting into relational table data from XML field

I have an XML structure that looks like the following:

SET @TheXML = 
<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>

Basically I have a written a query with extracts each of the children of Mailman and Letter and inserts the values into relational tables, which looks like the following:

INSERT INTO dbo.[Mailman]
SELECT  
    NULLIF(t.value('Name[1]','varchar(100)'),'') as Name,
    NULLIF(t.value('Age[1]','varchar(10)'),'') as Age
FROM @TheXML.nodes('MailingCompany/Mailman') as MailmanTemp(t)

SET @MailPersonFK = SCOPE_IDENTITY();


INSERT INTO dbo.[Letter]
SELECT 
    NULLIF(t.value('DestinationAddress[1]','varchar(100)'),'') as DestinationAddress,
    NULLIF(t.value('DestinationCountry[1]','varchar(100)'),'') as DestinationCountry,
    NULLIF(t.value('OriginCountry[1]','varchar(100)'),'') as OriginCountry,
    NULLIF(t.value('OriginAddress[1]','varchar(100)'),'') as OriginAddress
    @MailPersonFK AS MailmanID
FROM @TheXML.nodes('MailingCompany/Mailman/Letter') as LetterTemp(t)

My issue is that I only want to insert into the Mailman table when node 'Name' is populated with data. Same thing for inserting into Letter with node 'DestinationAddress'.

It's may also be useful noting that the parent node is not always going to be MailingCompany, and a Mailman can have many Letters.

Thanks all!

I believe that altering the XPaths in your nodes() method to the following will meet your requirements:

/*/Mailman[Name[text()!=""]]

Here, we get Mailman elements as long as they are children of any top-level element, and only if they contain text data (also, implicitly, they must exist).

/*/Mailman/Letter[DestinationAddress[text()!=""]]

This one gets letters that are children of any top-level node, it will get multiple Letter elements if there are any. And applys the same test for text content.

Tested successfully on the XML you provided:

  • <Name>Jamie</Name> - returned Name and Age
  • <Name></Name> - nothing returned
  • No <Name> element - nothing returned.

And similar tests for destination address.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM