Вставьте данные XML в таблицы SQL - PullRequest
1 голос
/ 16 ноября 2009

У меня есть 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. Моя таблица имеет следующую схему:

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 / themes / topic / департамент / questionHead / question') вкладка AS (столбец)

и теперь я могу получить доступ к вопросу, но не могу ничего найти рядом с ответом. У кого-нибудь есть идеи?

Ответы [ 2 ]

4 голосов
/ 16 ноября 2009

Поместите синглтон в каждое значение xml.value:

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

Несмотря на объявление схемы XML, SQL никак не может угадать, что разделы / разделы являются одноэлементными, поэтому вы должны явно принудительно задать их с помощью (...)[1].

Обновление

Если ваш XML имеет несколько элементов для родительского элемента , ваш запрос неверен. Вам нужно переместить topic в nodes:

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

Таким образом, вы проецируете строку для каждой темы во всех узлах тем. Ваш исходный запрос может выбрать только одну отдельную тему из каждого родителя тем.

1 голос
/ 16 ноября 2009

Попробуйте использовать [1] внутри xpath вашего .value() Например:

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

вместо

tab.col.value('./topic/@name', 'varchar(100)')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...