После многих исследований кажется очевидным, что невозможно сохранить порядок строк с помощью команды «Массовая вставка», написанной Microsoft. Вы должны либо сами добавить столбец идентификатора непосредственно в файл импорта, либо использовать оболочку или другой внешний скрипт, либо без этого. Похоже, что это была бы необходимая (и простая) функция для Microsoft, но после более чем десятилетия ничего от них не произойдет.
Тем не менее, мне нужно было сохранить фактический порядок записей в файле импорта после импорта, поскольку записи с более высокими значениями будут заменять записи с более низкими значениями, если заданный столбец будет иметь такое же значение.
Так что я пошел другим путем. Мои ограничения были:
- Я вообще не мог изменить исходный файл. (и создать плохой прецедент!)
- Я не мог использовать внешний скрипт. Слишком сложно. Это должно было быть простое решение на основе T-Sql, без выполнения CMD. Для этого нужно было выполнить одну процедуру, чтобы ее можно было автоматизировать.
Мне понравилась логика использования Powershell для создания упорядоченных операторов вставки для каждой строки с последующим запуском в Sql. По сути, это ставило в очередь каждую запись для отдельной вставки, а не для БОЛЬШОЙ вставки. Да, это будет работать, но это также будет очень медленно. У меня часто есть файлы с 500K + строк в них. Мне нужно что-то БЫСТРОЕ.
Итак, я столкнулся с XML. Массовая загрузка файла напрямую в одну переменную XML. Это сохранит порядок записей при добавлении каждой в XML. Затем проанализируйте переменную XML и вставьте результаты в таблицу, одновременно добавив столбец идентификаторов.
Существует предположение, что файл импорта является стандартным текстовым файлом, где каждая запись заканчивается строкой (Char (13) + Char (10))
Мой подход состоит из 2 шагов:
Выполните инструкцию IMPORT SQL (используя OPENROWSET), инкапсулируя каждую запись с тегами XML. Захват результатов в переменную XML.
Разобрать переменную по тегам XML в таблицу, добавив столбец [ID] с приращением.
---------------------------------
Declare @X xml;
---------------------------------
SELECT @X=Cast('<X>'+Replace([BulkColumn],Char(13)+Char(10),'</X><X>')+'</X>' as XML)
FROM OPENROWSET (BULK N'\\FileServer\ImportFolder\ImportFile_20170120.csv',SINGLE_CLOB) T
---------------------------------
SELECT [Record].[X].query('.').value('.','varchar(max)') [Record]
,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) [ID]
--Into #TEMP
FROM @X.nodes('X') [Record](X);
---------------------------------
Теги XML заменяют каждый перевод строки.
Если файл заканчивается переводом строки, это приведет к добавлению пустой строки в конце. Просто удалите последнюю строку.
Я записал это в свою процедуру, используя динамический sql, чтобы я мог передать FileName и установить идентификатор, начинающийся с 1 или 0 (в случае, если есть строка заголовка).
Мне удалось запустить это для файла с 300K-записями примерно за 5 секунд.