将xml数据插入sql表

时间:2009-11-16 17:43:02

标签: sql xml import

我有一个xml文档,格式如下:

<response username="123" customerName="CustomerName" siteName="SiteName" customerID="123" Period="2009">
  <topics>
    <topic name="MyTopic">
      <department name="MyDepartment" parent="OriginalDepartment">
        <questionHead result="Go" group="Group A" surveyID="1" questionID="2" responseID="3">
          <question>My Question</question>
          <answer>My Ansert</answer>
          <comment>Good Answer</comment>
          <reference>Page 10</reference>
        </questionHead>
        <questionHead result="Go" group="Group A" surveyID="1" questionID="2" responseID="3">
          <question>My Question</question>
          <answer>My Ansert</answer>
          <comment>Good Answer</comment>
          <reference>Page 10</reference>
        </questionHead>

...

有多个主题和部门。我需要将此数据插入到sql server表中。我的表有这个模式:

CREATE TABLE [dbo].[Questions](
    [ImportQuestionID] [int] IDENTITY(1,1) NOT NULL,
    [TopicName] [varchar](100) NULL,
    [DepartmentName] [varchar](100) NULL,
    [ParentDepartmentName] [varchar](100) NULL,
    [QuestionID] [int] NOT NULL,
    [SurveyID] [int] NOT NULL,
    [ResponseID] [int] NOT NULL,
    [PageNumber] [int] NOT NULL,
    [OrderNumber] [int] NOT NULL,
    [Result] [varchar](10) NULL,
    [GroupName] [varchar](100) NULL,
    [QuestionText] [varchar](500) NOT NULL,
    [AnswerText] [varchar](500) NOT NULL,
    [Comment] [varchar](500) NULL,
    [Reference] [varchar](500) NULL)

所以我已经将我的xml文件导入到带有xml列的临时表中,现在我正在尝试解析该文件并将其放入关系表中。

以下是我正在尝试的内容:

INSERT INTO [SRCL_XmlTest].[dbo].[Questions]
           field list...
SELECT tab.col.value('./topic/@name', 'varchar(100)') as TopicName,
        tab.col.value('./topic/department/@name', 'varchar(100)') as DepartmentName,
        tab.col.value('./topic/department/@parent', 'varchar(100)') as ParentDepartmentName,
        tab.col.value('./topic/department/questionH/@questionID', 'int') as QuestionID,
        tab.col.value('./topic/department/questionH/@surveyID', 'int') as SurveyID,
        tab.col.value('./topic/department/questionH/@responseID', 'int') as ResponseID,
        tab.col.value('./topic/department/questionH/@pageNumber', 'int') as PageNumber,
        tab.col.value('./topic/department/questionH/@orderNumber', 'int') as OrderNumber,
        tab.col.value('./topic/department/questionH/@result', 'varchar(10)') as ResultColourCode,
        tab.col.value('./topic/department/questionH/@group', 'varchar(100)') as GroupName,
        tab.col.value('./topic/department/questionH/question', 'varchar(500)') as QuestionText,
        tab.col.value('./topic/department/questionH/answer', 'varchar(500)') as AnswerText,
        tab.col.value('./topic/department/questionH/comment', 'varchar(500)') as Comment,
        tab.col.value('./topic/department/questionH/reference', 'varchar(500)') as Reference
FROM FileImport
CROSS APPLY
XmlData.nodes('//response/topics') AS tab(col)

但是,我一直收到错误:XQuery [FileImport.XmlData.value()]:'value()'需要一个单例(或空序列),找到类型为'xdt:untypedAtomic *'的操作数

这是因为xml中有多个主题节点?我已经尝试将我的选择更改为: XmlData.nodes('// response / topics / topic / department / questionHead / question')AS标签(col)

我现在可以访问这个问题,但无法接近答案。有想法的人吗?

2 个答案:

答案 0 :(得分:4)

在每个xml.value中放置一个单例:

tab.col.value('(./topic)[1]/@name', 'varchar(100)')
tab.col.value('(./topic/department)[1]/@name', 'varchar(100)')
...

Whitouth是一个XML模式声明,SQL无法猜测主题/主题是单例,因此您必须使用(...)[1]明确强制它。

<强>更新

如果您的XML有多个&lt; topic&gt; &lt; topics&gt;的元素父您的查询不正确。您需要将topic移至nodes

SELECT
tab.col.value('@name',...)
tab.col.value('(./department)[1]',...)
...
FROM ...
CROSS APPLY ... nodes('//response/topics/topic') as tab(col);

这样,您可以为所有主题节点中的每个主题投影一行。您的原始查询只能从每个主题父项中选择一个主题。

答案 1 :(得分:1)

尝试在[1]的xpath中使用.value()例如:

tab.col.value('./topic[1]/@name', 'varchar(100)')

而不仅仅是

tab.col.value('./topic/@name', 'varchar(100)')