Массовая вставка SQL с параметром FIRSTROW пропускает следующую строку - PullRequest
8 голосов
/ 23 июня 2009

Я не могу понять, как это происходит.

Вот пример файла, который я пытаюсь массово вставить в SQL Server 2005:

***A NICE HEADER HERE***
0000001234|SSNV|00013893-03JUN09
0000005678|ABCD|00013893-03JUN09
0000009112|0000|00013893-03JUN09
0000009112|0000|00013893-03JUN09

Вот мой массовый оператор вставки:

BULK INSERT sometable
FROM 'E:\filefromabove.txt
WITH
(
FIRSTROW = 2,
FIELDTERMINATOR= '|',
ROWTERMINATOR = '\n'
)

Но по какой-то причине единственный выход, который я могу получить:

0000005678|ABCD|00013893-03JUN09
0000009112|0000|00013893-03JUN09
0000009112|0000|00013893-03JUN09

Первая запись всегда пропускается, если только я полностью не удаляю заголовок и не использую параметр FIRSTROW. Как это возможно?

Заранее спасибо!

Ответы [ 5 ]

14 голосов
/ 23 июня 2009

Я не думаю, что вы можете пропустить строки в другом формате с помощью BULK INSERT / BCP.

Когда я запускаю это:

TRUNCATE TABLE so1029384

BULK INSERT so1029384
FROM 'C:\Data\test\so1029384.txt'
WITH
(
--FIRSTROW = 2,
FIELDTERMINATOR= '|',
ROWTERMINATOR = '\n'
)

SELECT * FROM so1029384

Я получаю:

col1                                               col2                                               col3
-------------------------------------------------- -------------------------------------------------- --------------------------------------------------
***A NICE HEADER HERE***
0000001234               SSNV                                               00013893-03JUN09
0000005678                                         ABCD                                               00013893-03JUN09
0000009112                                         0000                                               00013893-03JUN09
0000009112                                         0000                                               00013893-03JUN09

Похоже, для этого требуется '|' даже в данных заголовка, потому что он читает до этого в первом столбце - глотая новую строку в первом столбце. Очевидно, что если вы включите параметр терминатора поля, он ожидает, что каждая строка ДОЛЖНА иметь его.

Вы можете удалить строку с шагом предварительной обработки. Другая возможность - выбрать только полные строки, а затем обработать их (исключая заголовок). Или используйте инструмент, который может справиться с этим, например, SSIS.

8 голосов
/ 23 июня 2009

Может быть, проверить, что заголовок имеет тот же конец строки, что и фактические строки данных (как указано в ROWTERMINATOR)?

Обновление: с MSDN :

Атрибут FIRSTROW не предназначен пропустить заголовки столбцов. Пропуская заголовки не поддерживаются BULK Вставить заявление. При пропуске строк, выглядит SQL Server Database Engine только на полевых терминаторах, и не проверяет данные в поля пропущенных строк.

6 голосов
/ 08 августа 2013

Мне было проще всего прочитать всю строку в один столбец, а затем проанализировать данные с помощью XML.

IF (OBJECT_ID('tempdb..#data') IS NOT NULL) DROP TABLE #data
CREATE TABLE #data (data VARCHAR(MAX))

BULK INSERT #data FROM 'E:\filefromabove.txt' WITH (FIRSTROW = 2, ROWTERMINATOR = '\n')

IF (OBJECT_ID('tempdb..#dataXml') IS NOT NULL) DROP TABLE #dataXml
CREATE TABLE #dataXml (ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, data XML)

INSERT #dataXml (data)
SELECT CAST('<r><d>' + REPLACE(data, '|', '</d><d>') + '</d></r>' AS XML)
FROM #data

SELECT  d.data.value('(/r//d)[1]', 'varchar(max)') AS col1,
        d.data.value('(/r//d)[2]', 'varchar(max)') AS col2,
        d.data.value('(/r//d)[3]', 'varchar(max)') AS col3
FROM #dataXml d
0 голосов
/ 25 января 2019

Вы можете использовать приведенный ниже фрагмент

BULK INSERT TextData
FROM 'E:\filefromabove.txt'
WITH
(
FIRSTROW = 2,
FIELDTERMINATOR = '|',  --CSV field delimiter
ROWTERMINATOR = '\n',   --Use to shift the control to next row
ERRORFILE = 'E:\ErrorRows.csv',
TABLOCK
)
0 голосов
/ 06 февраля 2014

Учитывая, как искаженные данные могут выглядеть после импорта BCP в SQL Server из источников данных, отличных от SQL, я бы предложил сначала выполнить весь импорт BCP в некоторые рабочие таблицы.

Например

усеченная таблица Address_Import_tbl

BULK INSERT dbo.Address_Import_tbl FROM 'E: \ external \ SomeDataSource \ Address.csv' С ( FIELDTERMINATOR = '|', ROWTERMINATOR = '\ n', MAXERRORS = 10 )

Убедитесь, что все столбцы в Address_Import_tbl являются nvarchar (), чтобы сделать его как можно более независимым и избежать ошибок преобразования типов.

Затем примените все необходимые исправления к Address_Import_tbl. Как удаление ненужного заголовка.

Затем выполните запрос INSERT SELECT, чтобы скопировать его из Address_Import_tbl в Address_tbl вместе с любыми необходимыми преобразованиями типов данных. Например, для приведения импортированных дат в SQL DATETIME.

...