2012-07-10 141 views
1

我有一个55MB的XML,并且正在尝试使用OPENXML将其切碎,因为它看起来比正常的XML切分更快。 XML的结构是这样的:通过OPENXML解析XML时出错

<DATA_EXPORT> 
<HEADER> 
    <RECDATE> 
     <START>2011-03-16</START> 
     <END>2012-02-10</END> 
    </RECDATE> 
    <SOME_COUNT>10288</SOME_COUNT> 
    <QUESTION_MAP> 
     <QUESTION> 
      <SERVICE>OU</SERVICE> 
      <VARNAME>UNIT</VARNAME> 
      <QUESTION_TEXT></QUESTION_TEXT> 
     </QUESTION> 
       250 more nodes like <QUESTION> 
    </QUESTION_MAP> 
</HEADER> 
<SOMENODES> 
    <SURVEY_ID>448817197</SURVEY_ID> 
    <CLIENT_ID>58</CLIENT_ID> 
    <SERVICE>OU</SERVICE> 
    <RECDATE>2011-03-29</RECDATE> 
    <DISDATE>2010-03-29</DISDATE> 
</SOMENODES> 
    : 
    : 
    1000s of nodes like <SOMENODES> 
</DATA_EXPORT> 

,我使用下面的查询获取数据出来

declare @xmlData varchar(max) = null 
     ,@iDoc int = null 
     ,@xml xml = null 

select @xmlData = cast(@xml as varchar(max)) 

    exec sp_xml_preparedocument @iDoc OUTPUT, @xmlData 

    select * 
      ,getdate() 
    from openxml(@iDoc, '//DATA_EXPORT/SOMEDATA', 2) 
    with (
     surveyId  varchar(50)  'SURVEY_ID[1]', 
     clientId  int   'CLIENT_ID[1]', 
     [service]  varchar(50)  'SERVICE[1]', 
     recieveDate  datetime  'RECDATE [1]', 
     dischargeDate datetime    'DISDATE [1]' 
    ) 
    option (optimize for unknown) 

我已经wrritten这是存储过程和我得到以下错误的节点:

The XML parse error 0xc00ce562 occurred on line number 1, near the XML text "<". 
Msg 6602, Level 16, State 2, Procedure sp_xml_preparedocument, Line 1 
The error description is 'A declaration was not closed.'. 
Msg 8179, Level 16, State 5, Procedure q_ImportSurveyMasterDetails, Line 81 
Could not find prepared statement with handle 0. 
The statement has been terminated. 

任何人都可以帮助我什么是行号错误,如错误所示? 还有没有更好更快的方式来粉碎一个55MB的XML文件?

在此先感谢。

+0

我假设Xml格式良好,您是否可以在VS或SSMS中打开它?如果Xml有声明,请检查它前面是否有空白。您是否尝试过使用'XQuery'语法(主要是'nodes()'和'value()'函数)?另一个选项是Sql Clr存储过程,但涉及更多工作。 – 2012-07-11 00:54:11

+0

我能够在VS中打开它,并检查第1行中是否有任何特殊字符。但是在标签开始之前没有特殊字符。 – Ankur 2012-07-11 17:10:01

+1

对,我想知道为什么你使用'@xmlData VARCHAR(MAX)'作为'sp_xml_preparedocument'的参数,而不是直接使用'@xml XML'。可能是因为编码而导致某些字符在转换过程中遭到破坏? – 2012-07-11 22:29:23

回答

1

问题#1:The XML parse error 0xc00ce562 occurred on line number 1, near the XML text "<"。 通过将@xmlData更改为@xml来修复,即不将其转换为varchar(max),只是将它作为xml传递。感谢@dan radu为您提供的所有帮助。

问题#2:合并语句中的option关键字。它似乎不能在合并中使用,因为合并语句本身就是一个单独的sql语句。它应该在合并语句的末尾使用,例如

merge dbo.table1 as target 
using (
     select 
      n.value('(SURVEY_ID)[1]', 'bigint') as surveyId 
      ,n.value('(CLIENT_ID)[1]', 'int') as clientId 
      ,n.value('(SERVICE)[1]', 'varchar(50)') as [service] 
      ,n.value('(RECDATE)[1]', 'datetime') as recieveDate 
      ,n.value('(DISDATE)[1]', 'datetime') as dischargeDate 
     from @xml.nodes('//DATA_EXPORT/SOMENODES') x(n) 

     ) as source 
on target.surveyId = source.surveyId 
    and target.[service] = source.[service] 
when matched then 
update set 
     target.clientId = source.clientId, 
     target.[service] = source.[service], 
     target.surveyRecieveDate = source.recieveDate, 
     target.dischargeDate = source.dischargeDate 
when not matched then 
insert (surveyId, clientId, [service], surveyRecieveDate, dischargeDate) 
values (surveyId, clientId, [service], recieveDate, dischargeDate) 
option (optimize for unknown); 
+0

很高兴你解决了第一个问题。我已经执行了你的'MERGE'语句,它对我无影响(在'SQL Server 2008 R2'上)。 – 2012-07-12 22:58:38

+0

@danradu:是的,它是合并声明的修正版本。我之前在合并中使用了option关键字,在任何情况下都不应该这样做。 – Ankur 2012-07-17 01:10:03