批量插入并将复杂的XML文件解析为多个表

时间:2013-05-18 02:35:30

标签: sql sql-server xml xml-parsing bulk-load

我有以下sql存储过程来批量插入和解析xml文件,并将其数据插入到数据库中的多个表中。

下面的sql工作,但它将重复记录插入#questions表和#cards表。

对此的任何帮助将不胜感激。提前谢谢。

这是XML文件:

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

这是SQL代码

/*************************************************************************
 -- 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)

2 个答案:

答案 0 :(得分:0)

我不确定你的CROSS JOIN是什么。

这是一些粉碎。

提示:注释掉INSERT部分,然后执行SELECT部分​​,直到您正确调整这些部分。

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);

答案 1 :(得分:0)

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)