Как импортировать из файла XML в мастере импорта и экспорта SQL Server?
У меня есть данные и схема для таблицы в виде одного файла XML. Как импортировать это с помощью мастера импорта и экспорта SQL Server?
Должен ли я использовать "Источник плоских файлов" в качестве источника данных? Или что?
[Для информации, я экспортировал XML из VistaDB, но я еще не дошел до того момента, когда система, создавшая данные, может быть проблемой.]
1 ответ
Насколько я знаю, вы не можете сделать это с помощью мастера импорта экспорта. Предполагая, что вы хотите, чтобы данные были все реляционными, а не XML-типом данных, вам нужно будет создать таблицу и использовать sp_xml_preparedocument и OPENXML.
См. Как использовать OPENXML для загрузки данных XML в существующую таблицу SQL?
Насколько мне известно, в MS SQL Server Management Studio нет инструмента для загрузки XML в таблицу. Существует вариант, который включает комбинацию OPENROWSET и обработки XML, но требует, чтобы файлы находились в файловой системе сервера.
Мне нужно было загрузить в таблицу серию файлов журналов, сгенерированных веб-приложением Java, но у меня не было доступа для их загрузки на сервер, у меня были журналы на моем локальном компьютере. Мне удалось загрузить данные в двухэтапном процессе, который не слишком громоздкий, но определенно слишком медленный для постоянного решения.
Я создал таблицу, состоящую из двух столбцов: автономного первичного ключа и varchar(max). Я использовал данные импорта для загрузки текстовых файлов в таблицу, чтобы каждая строка в файле представляла собой запись в таблице. Первичный ключ случайно представляет номер строки. Так что я мог написать что-то вроде:
select LineNumber, TextLine from [LogFile] order by LineNumber
Затем я подготовил другую таблицу со структурой, которая соответствовала записям в моем XML. Особенность моих XML-файлов заключалась в том, что каждый тег "значение" находился в отдельной текстовой строке, а открывающий и закрывающий теги "записи" - в отдельной строке.
Например:
<log>
<record>
<date>2018-07-27T09:54:20</date>
<millis>1532706860250</millis>
<sequence>13587</sequence>
<logger>registroweb.ServReg</logger>
<level>INFO</level>
<class>somepackage.someclass</class>
<method>methodname</method>
<thread>11153</thread>
<message>some very long text</message>
<param>another long text</param>
</record>
...
</log>
Это означало бы, что я мог бы выбрать все записи, где text_line = '
Итак, с помощью следующего запроса я смог преобразовать плоскую линейную таблицу в правильную таблицу:
insert into LogFileProcessed(
[date],
[millis],
[sequence],
[logger] ,
[level] ,
[class] ,
[method] ,
[thread] ,
[message],
[param]
)
select
--record.TextLine,
convert(datetime, replace(replace(ltrim(dte.TextLine), '<date>', ''), '</date>', ''), 126) [date],
convert(bigint, replace(replace(ltrim(mls.TextLine), '<millis>', ''), '</millis>', '')) [millis],
convert(bigint, replace(replace(ltrim(seq.TextLine), '<sequence>', ''), '</sequence>', '')) [sequence],
replace(replace(ltrim(logr.TextLine), '<logger>', ''), '</logger>', '') [logger],
replace(replace(ltrim(lvl.TextLine), '<level>', ''), '</level>', '') [level],
replace(replace(ltrim(cls.TextLine), '<class>', ''), '</class>', '') [class],
replace(replace(ltrim(mtd.TextLine), '<method>', ''), '</method>', '') [method],
replace(replace(ltrim(trd.TextLine), '<thread>', ''), '</thread>', '') [thread],
replace(replace(ltrim(msg.TextLine), '<message>', ''), '</message>', '') [message],
replace(replace(ltrim(prm.TextLine), '<param>', ''), '</param>', '') [param]
from LogFile record
left join LogFile dte on dte.LineNumber = record.LineNumber+1
left join LogFile mls on mls.LineNumber = record.LineNumber+2
left join LogFile seq on seq.LineNumber = record.LineNumber+3
left join LogFile logr on logr.LineNumber = record.LineNumber+4
left join LogFile lvl on lvl.LineNumber = record.LineNumber+5
left join LogFile cls on cls.LineNumber = record.LineNumber+6
left join LogFile mtd on mtd.LineNumber = record.LineNumber+7
left join LogFile trd on trd.LineNumber = record.LineNumber+8
left join LogFile msg on msg.LineNumber = record.LineNumber+9
left join LogFile prm on prm.LineNumber = record.LineNumber+10 and prm.TextLine <> '</record>' -- param is actually the only tag that is optional and some times is not present in the record.
where record.TextLine = '<record>'
order by 1, 2
Учитывая особые ограничения, которые у меня были в то время, и структуру файлов, это работало достаточно хорошо для одноразовой задачи, позволяя мне выполнять регулярные запросы к данным без необходимости многократно запускать синтаксический анализ или код обработки XML.