2016-10-06 2 views
2

Сегодня у меня есть новая ситуация, в которой из клиента спрашивает следующее:SSIS 2012 - Загрузка XML-файлы из папки в таблицу SQL Server COLUMN, используя Execute SQL Task и цикл просмотра контейнера

У нас есть файлы XML в папка. Нам нужно загрузить эти файлы в столбец таблицы SQL Server (который имеет тип данных XML); мы НЕ загружаем выходы XML в различные таблицы SQL Server, вместо этого мы загружаем сам XML-файл в столбец с типом данных XML в базе данных SQL Server.

Это должно быть сделано только в SSIS, согласно требованиям клиента. Таким образом, я использую Execute SQL Task таким образом. (Помимо XML-файла, нам нужны ImportDate,и т. Д.)

Тип подключения - OLE DB; SQL Statement I have выглядит следующим образом:

INSERT INTO dbo.tablename (IncomingXMLfile, ImportDate) 
-- I am using just 2 columns as an example for this table-- 
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE() 
FROM OPENROWSET(BULK 'C:\Mic\...........\API_Schemas\ABC.xml', SINGLE_BLOB) AS x; 

Это прекрасно работает, когда я жестко задаю только один файл. Теперь, в папке C:\Mic\...\API_Schemas, есть много файлов XML, мне нужно загрузить каждый из них, и кроме этого получить их ImportDate (GETDATE()) и имя самого файла (я не упомянул этот столбец для теперь в заявлении INSERT). Я должен использовать контейнер ForEachLoop и помещать задачу Execute SQL в этот контейнер.

Следовательно, есть 2 аспекта этой проблемы:

  1. Параметрирование имя файла внутри Execute SQL Task.

  2. Использование контейнера ForEachLoop (и размещение этой задачи выполнения SQL внутри) для запуска каждого XML-файла в папке.

Я использую пользовательскую переменную с именем Filename (строка тип данных), который имеет значение ABC.xml (первый файл в серии файлов XML в папке); Я параметризовать выше запрос TSQL такого способа (см ниже):

INSERT INTO dbo.tablename (IncomingXMLfile, ImportDate) 
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE() 
FROM OPENROWSET(BULK 'C:\Mic\...........\API_Schemas\?', SINGLE_BLOB) AS x; 

я отображающий этот параметр (?) переменное Имя файла пользователя в этом Execute SQL Task (ParameterMapping вкладки). Запрос корректно анализируется в задаче SQL Execute! Однако, когда я выполняю этот SQL Task, я получаю эту ошибку:

"Parameter name is unrecognized.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.

Эта ситуация довольно отличается, когда я загрузить данные из файлов XML (с помощью редактора исходного кода XML, с режимом доступа данных (XML-данных с переменной) и т. д.) в таблицы SQL Server. В нашем случае мы загружаем сам файл XML в таблицу SQL Server COLUMN с типом данных XML и получаем информацию о различных файлах XML, загруженных из папки. В результате я не уверен, как использовать переменную для запуска этого пакета.

  • Может ли кто-нибудь в первую очередь помочь мне в правильном параметризации имени файла?

  • И как настроить Контейнер ForEachLoop для чтения каждого файла из папки?

Я смущен тем, как использовать пользовательские переменные в этом сценарии.

+0

Самый прямой способ заключается в использовании динамического SQL в цикле в то время. Получите список файлов из папки в таблицу temp, возьмите сначала, сгенерируйте запрос, запустите его на второй ... или даже сгенерируйте один большой оператор и запустите его сразу. – gofr1

+0

Можете ли вы привести мне пример использования динамического SQL в таком сценарии? Я использовал Dynamic SQL в разных обстоятельствах, но не в таком случае. – user3812887

+0

Я добавляю решение с динамическим SQL как ответ. – gofr1

ответ

0

Сначала я создать таблицу для хранения XML:

CREATE TABLE XMLstore (
    IncomingXMLfile xml, 
    ImportDate datetime 
) 

Создание 2 файлов для целей тестирования ABC.xml и DEF.xml и поместить в них некоторое содержание XML:

<some> 
    <row id="1"> 
     <stuff>1</stuff> 
    </row> 
</some> 

Затем запустить этот скрипт:

DECLARE @command varchar(1000), 
     @dir varchar(max) = 'D:\API_Schemas\', 
     @n int = 0, 
     @i int = 1, 
     @sql nvarchar(max) 

DECLARE @files TABLE (
    id INT IDENTITY(1,1), 
    files varchar(1000) 
) 

SET @command = 'dir "'+ @dir +'" /B' 

INSERT INTO @files (files) 
EXEC xp_cmdshell @command 

SELECT @n = COUNT(*) 
FROM @files 
WHERE files like '%.xml%' 

WHILE @n >= @i 
BEGIN 

    SELECT @sql = N' 
    INSERT INTO XMLstore (IncomingXMLfile, ImportDate) 
    SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE() 
    FROM OPENROWSET(BULK '''[email protected]+files+''', SINGLE_BLOB) AS x;' 
    FROM @files 
    WHERE id = @i 

    EXEC sp_executesql @sql 

    SET @i = @i + 1 
END 

После этого я выбираю из таблицы XMLstore:

SELECT * 
FROM XMLstore 

И получить выход:

IncomingXMLfile         ImportDate 
<some><row id="1"><stuff>1</stuff></row></some> 2016-10-06 10:17:41.453 
<some><row id="2"><stuff>2</stuff></row></some> 2016-10-06 10:17:41.457 

Описание:

Файлы хранятся здесь D:\API_Schemas\. Я использую xp_cmdshell для запуска команды dir "D:\API_Schemas\" /B, чтобы получить все файлы из этого каталога.

/B используется для включения

Uses bare format (no heading information or summary)

таким образом мы получаем только имена файлов. И положите их в таблицу @files.

Эта таблица получила столбец идентификации, который добавляет id, начиная с 1 в каждую строку (файл). Таким образом, мы можем повторять цикл while, используя простой счетчик (@i).

В цикле while мы создаем динамический SQL-запрос и запускаем его.

Примечание:

Вместо xp_cmdshell вы можете использовать xp_dirtree (это недокументированная и не поддерживается), как:

DECLARE @dir varchar(100) = 'D:\API_Schemas\' 

DECLARE @files TABLE (
    id INT IDENTITY(1,1), 
    files varchar(1000), 
    depth int, 
    [file] int 
) 

INSERT INTO @files 
EXEC xp_dirtree @dir, 1, 1 
Смежные вопросы