Импорт XML в SQL-сервер кошмар - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь импортировать в SQL-сервер загрузку данных из XML-файлов, и у меня возникают проблемы с добавлением соответствующих ключей (хранящихся в узле «keys»), чтобы связать XML-данные вместе в SQL-сервере.

Пожалуйста, рассмотрите фрагмент XML ниже.

<person>
    <keys>
        <key>xx8546</key>
        <key>yy369</key>
    </keys>

    <sex>f</sex>

   <names>
      <name>
         <prename>Sarah</prename>
         <surname>Connor</surname>
      </name>

      <name>
         <prename>Sarah</prename>
         <surname>Williams</surname>
      </name>
  </names>

  <mmx>
      <spouse-name>
          <prename>John</prename>
          <surname>Wyatt</surname>
      </spouse-name>
      <year-of-marriage>1985</year-of-marriage>
  </mmx>

  <pbx>
     <spouse-name>
        <prename>John</prename>
        <surname>Williams</surname>
     </spouse-name>

     <child-name>
        <prename>Sarah</prename>
        <surname>Bean</surname>
     </child-name>

     <year-of-baptism>2007</year-of-baptism>
 </pbx>
</person>  

Мне нужно добавить соответствующий ключ к каждому из узлов.

Вот часть моего tsql:

DECLARE @x xml;
DECLARE @hdoc int;

SELECT @x = P
FROM OPENROWSET (BULK 'C:\person.xml', SINGLE_BLOB) AS Person(P)

EXEC sp_xml_preparedocument @hdoc OUTPUT, @x

--Person
SELECT * --into tbl_Person
FROM OPENXML (@hdoc, '/persons/person/names/name', 2)
WITH (
[key]  nvarchar(100)  '../../keys/key', 
prename varchar(100),
surname varchar(100),
sex varchar(50) '../../sex'
)

Приведенный выше код только вставляетпервое ключевое значение в обоих результатах, например <key xx8546 </key>.Пожалуйста, вы можете помочь мне разобраться в этом, это действительно расстраивает.

Большое спасибо,

BN.

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

FROM OPENXML с соответствующими СП для подготовки и удаления документа устарели и больше не должны использоваться. Вместо этого используйте соответствующие методы, которые предоставляет тип данных XML .

Порядок элементов является неотъемлемой частью документа XML. Это не лучший дизайн, но можно связать информацию через их относительное положение . Очевидно, у вас возникнут проблемы, если здесь чего-то не хватает.

Я не понял, как <sex> связан и что ваши <mmx> и <pbx> здесь делают, но вы можете идти по этой дороге:

DECLARE  @xml XML=
N'<person>
    <keys>
        <key>xx8546</key>
        <key>yy369</key>
    </keys>
    <sex>f</sex>
    <names>
      <name>
         <prename>Sarah</prename>
         <surname>Connor</surname>
      </name>
      <name>
         <prename>Sarah</prename>
         <surname>Williams</surname>
      </name>
    </names>
  </person>';

Запрос начинается с внутри строки . Количество ключей возвращается как производная таблица. В этом случае Tally вернет set из 1 и 2.

Теперь вы можете использовать этот рабочий номер, чтобы получить коррелированные данные из вашего XML:

WITH Tally(Nr) AS (SELECT TOP (@xml.value(N'count(/person/keys/key)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values) 
SELECT Nr
      ,@xml.value(N'(/person/keys/key[sql:column("Nr")]/text())[1]','nvarchar(max)') AS PersonKey
      ,@xml.value(N'(/person/names/name[sql:column("Nr")]/prename/text())[1]','nvarchar(max)') AS PersonPrename
      ,@xml.value(N'(/person/names/name[sql:column("Nr")]/surname/text())[1]','nvarchar(max)') AS PersonSurname

       -- this will return the <sex> for both (as there is just one...)
      ,@xml.value(N'(/person/sex/text())[1]',N'nvarchar(max)') AS sex
FROM Tally;

Результат

Nr  PersonKey   PersonPrename   PersonSurname   sex
1   xx8546      Sarah           Connor          f 
2   yy369       Sarah           Williams        f
0 голосов
/ 10 мая 2018

Я думаю, вы не можете импортировать все данные одновременно, поскольку <keys> явно не связаны с другими данными.

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

Вот базовый пример этого подхода:

create table tb_keys (id int identity(1,1), keycode nvarchar(50))
create table tb_names (id int identity(1,1), prename nvarchar(500), surname nvarchar(500))

declare @x xml;

select @x = p from openrowset (bulk 'c:\person.xml', single_blob) as person(p)

insert into tb_keys
select p.value('.', 'nvarchar(50)') as [key] from @x.nodes('/person/keys/key') AS T(p)

insert into tb_names
select 
    x.rec.query('./prename').value('.', 'nvarchar(500)') as 'prename',
    x.rec.query('./surname').value('.', 'nvarchar(500)') as 'surname'
from @x.nodes('/person//names/name') as x(rec)

select k.keycode, n.prename, n.surname 
from tb_keys k inner join tb_names n on k.id = n.id

Выход:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...