Как насчет двухэтапного подхода? Сначала загрузите данные в промежуточную таблицу как «большие строки», затем используйте второй запрос, чтобы разбить необработанные строки на соответствующие поля и обработать «отсутствующие столбцы f5 и / или f4» соответственно?
будет выглядеть (более или менее) так: (не проверено!)
CREATE TABLE [dbo].[deviceDataBulk_staging](
[rowid] int IDENTITY(1 , 1) PRIMARY KEY,
[raw] [varchar](34) NOT NULL)
GO
BULK INSERT [deviceDataBulk_staging]
FROM '<your file>'
-- not sure if you really need a format-file here,
-- simply make sure to pass the correct line-separator if it is 'exotic'.
GO
INSERT [deviceDataBulk] (f1, f2, f3, f4, f5)
SELECT f1 = SubString([raw], 1 , 9),
f1 = SubString([raw], 10 , 5),
f1 = SubString([raw], 15 , 7),
f1 = (CASE WHEN Length([raw] < 22 THEN NULL ELSE SubString([raw], 22 , 7) END),
f1 = (CASE WHEN Length([raw] < 29 THEN NULL ELSE SubString([raw], 29 , 6) END)
FROM [deviceDataBulk_staging]
ORDER BY [rowid]
В этом случае промежуточный файл будет выглядеть так:
[rowid] предназначен для того, чтобы сохранить порядок, идентичный порядку, изначально указанному в файле, он может вам и не понадобиться, но ИМХО издержки минимальны, и MSSQL в любом случае не слишком заинтересован в таблицах HEAP, поэтому его наличие " Хорошая вещь [Тм] "