Question

I have the following sql stored procedure to bulk insert and parse an xml file and insert its data into several tables in a database.

The sql below works, however its inserting duplicate records into the #questions table and the #cards table.

Any help on this would be much appreciated. Thanks in advance.

Here is the XML file:

<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User>
    <UserInfo>
        <Id>0001</Id>
        <FirstName>John</FirstName>
        <LastName>Doe</LastName>
        <Email>Doejk@net.com</Email>
    </UserInfo>
    <Questions>
        <Question> 
            <Id>1</Id>
            <AnswerId>1</AnswerId>
        </Question>
        <Question> 
            <Id>2</Id>
            <AnswerId>3</AnswerId>
        </Question>
    </Questions>
    <Cards>
        <Card> 
            <Id>1234</Id>
            <Type>Digital</Type>
            <Status>Active</Status>
        </Card>
        <Card> 
            <Id>1334</Id>
            <Type>Physical</Type>
            <Status>Not Active</Status>
        </Card>
    </Cards>
</User>

<User>
    <UserInfo>
        <Id>0002</Id>
        <FirstName>Mary</FirstName>
        <LastName>Doe</LastName>
        <Email>Doem@net.com</Email>
    </UserInfo>
    <Questions>
        <Question> 
            <Id>3</Id>
            <AnswerId>6</AnswerId>
        </Question>
        <Question> 
            <Id>4</Id>
            <AnswerId>7</AnswerId>
        </Question>
    </Questions>
    <Cards>
        <Card> 
            <Id>3333</Id>
            <Type>Digital</Type>
            <Status>Active</Status>
        </Card>
        <Card> 
            <Id>4444</Id>
            <Type>Physical</Type>
            <Status>Active</Status>
        </Card>
    </Cards>
</User>
</Users>

Here is SQL code

/*************************************************************************
 -- CREATE TEMP TABLES --
**************************************************************************/
CREATE TABLE #XMLDATA
(RecordId int IDENTITY(1,1) NOT NULL,
XmlData xml NOT NULL)

CREATE TABLE #USERS
         (UserID                int         null,
          firstname         varchar(50)         null,
          lastname          varchar(50)         null,
          email         varchar(50)         null)



CREATE TABLE #CARDS
    (CardId         int             null,
     userid         int             null,
             card_type      varchar(50)         null,
             card_status        varchar(50)         null)


CREATE TABLE #QUESTIONS
     (UserID        int             null,
              Question_ID       int             null,
      Answer_ID     int             null)



/*************************************************************************
 -- LOAD THE WHOLE XML AS SINGLE BLOB --
**************************************************************************/
INSERT INTO #XMLDATA(XmlData)
SELECT * 
FROM OPENROWSET(
BULK 'c:\users.xml', SINGLE_BLOB) 


/*************************************************************************
 -- INSERT USERS --
**************************************************************************/
INSERT INTO #USERS
    (userid, firstname, lastname, email)

SELECT  href.value('(Id/text())[1]', 'integer'), 
    href.value('(FirstName/text())[1]', 'varchar(50)'), 
    href.value('(LastName/text())[1]', 'varchar(50)'), 
    href.value('(Email/text())[1]', 'varchar(30)'),

FROM    #XMLDATA CROSS APPLY 
XmlData.nodes('Users') AS userinfo(href)


/*************************************************************************
 -- INSERT QUESTIONS INFORMATION  --
**************************************************************************/

INSERT INTO #QUESTIONS
    (UserId, Question_ID, Answer_ID)

SELECT sref.value('(Id/text())[1]', 'integer'),
       qref.value('(Id/text())[1]', 'integer'),
       qref.value('(AnswerId/text())[1]', 'integer')

FROM   #XMLDATA CROSS APPLY 
       XmlData.nodes('Users/Questions/Question') AS Ques(qref) CROSS APPLY
       XmlData.nodes('Users') AS userinf(sref)




/*************************************************************************
 -- INSERT CARD INFORMATION  --
**************************************************************************/

INSERT INTO #CARDS
(userid, card_id, card_type,card_status)

SELECT sref.value('(Id/text())[1]', 'integer'),
cref.value('(Id/text())[1]', 'integer'),  
   cref.value('(Type/text())[1]', 'varchar(50)'),
   cref.value('(Status/text())[1]', 'varchar(50)')

FROM   #XMLDATA CROSS APPLY 
   XmlData.nodes('/Users/Cards/Card') AS cardlist(cref) CROSS APPLY
   XmlData.nodes('/Users') AS userinf(sref)
Was it helpful?

Solution

I'm not sure what your CROSS JOIN is about.

Here is some shredding.

Tip: Comment out the INSERT portion and just do the SELECT portion until you get those tweaked correctly.

DECLARE @data XML;

SET @data = 

N'

<Users>
<User>
    <UserInfo>
        <Id>0001</Id>
        <FirstName>John</FirstName>
        <LastName>Doe</LastName>
        <Email>Doejk@net.com</Email>
    </UserInfo>
    <Questions>
        <Question> 
            <Id>1</Id>
            <AnswerId>1</AnswerId>
        </Question>
        <Question> 
            <Id>2</Id>
            <AnswerId>3</AnswerId>
        </Question>
    </Questions>
    <Cards>
        <Card> 
            <Id>1234</Id>
            <Type>Digital</Type>
            <Status>Active</Status>
        </Card>
        <Card> 
            <Id>1334</Id>
            <Type>Physical</Type>
            <Status>Not Active</Status>
        </Card>
    </Cards>
</User>

<User>
    <UserInfo>
        <Id>0002</Id>
        <FirstName>Mary</FirstName>
        <LastName>Doe</LastName>
        <Email>Doem@net.com</Email>
    </UserInfo>
    <Questions>
        <Question> 
            <Id>3</Id>
            <AnswerId>6</AnswerId>
        </Question>
        <Question> 
            <Id>4</Id>
            <AnswerId>7</AnswerId>
        </Question>
    </Questions>
    <Cards>
        <Card> 
            <Id>3333</Id>
            <Type>Digital</Type>
            <Status>Active</Status>
        </Card>
        <Card> 
            <Id>4444</Id>
            <Type>Physical</Type>
            <Status>Active</Status>
        </Card>
    </Cards>
</User>
</Users>';


SELECT T.myEntity.value('(Id)[1]', 'VARCHAR(20)')
    ,    T.myEntity.value('(FirstName)[1]', 'VARCHAR(20)') 
    ,    T.myEntity.value('(LastName)[1]', 'VARCHAR(20)') 
    ,    T.myEntity.value('(Email)[1]', 'VARCHAR(20)') 
FROM @data.nodes('Users/User/UserInfo') AS T(myEntity);


SELECT 
  T.myEntity.value('(../../UserInfo/Id)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Id)[1]', 'INT')
,    T.myEntity.value('(AnswerId)[1]', 'INT') 
FROM @data.nodes('Users/User/Questions/Question') AS T(myEntity);



SELECT 
  T.myEntity.value('(../../UserInfo/Id)[1]', 'VARCHAR(20)')
, T.myEntity.value('(Id)[1]', 'INT')
    ,    T.myEntity.value('(Type)[1]', 'VARCHAR(20)') 
    ,    T.myEntity.value('(Status)[1]', 'VARCHAR(20)') 
FROM @data.nodes('Users/User/Cards/Card') AS T(myEntity);

OTHER TIPS

CREATE TABLE #XMLDATA
(RecordId int IDENTITY(1,1) NOT NULL,
XmlData xml NOT NULL)

CREATE TABLE #USERS
         (UserID                int         null,
          firstname         varchar(50)         null,
          lastname          varchar(50)         null,
          email         varchar(50)         null)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top