Erro 4866 com Bulk Insert
Ao me deparar com a situação de realizar uma importação de dados para o SQL Server a partir de arquivos CSV, percebi q seria uma boa oportunidade de usar o BULK INSERT.
Meu CSV é separado por vírgulas e foi escrito em unix. Isso vai nos levar ao velho problema da representação de fim de linha que é diferente entre windows e *unix.
Quando um arquivo plain-text *unix for usado com o código abaixo, o SQL Server vai enviar sempre ao invés de \n, o conjunto \r\n.
BULK INSERT [Data2010-2]
FROM 'C:\dataWithoutHeads.csv'
WITH
(
KEEPNULLS,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)
Esta inconsistência, vai gerar 3 erros quando for executado:
Msg 4866, Level 16, State 1, Line 1
The bulk load failed. The column is too long in the data file for row 1, column 30. Verify that the field terminator and row terminator are specified correctly.
Msg 7399, Level 16, State 1, Line 1
The OLE DB provider "BULK" for linked server "(null)" reported an error. The provider did not give any information about the error.
Msg 7330, Level 16, State 2, Line 1
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)".
O grande erro a ser corrigido aqui é o 4866, que representa um erro no BULK INSERT. Os outros são consequência deste erro.
Para resolver isso de uma forma simples, no unix mesmo, antes de executar o bulk insert, use o aplicativo unix2dos. Ele existe em qualquer distribuição linux e irá “converter” as quebras de linha formato unix para o formato Windows (caso você precise fazer o caminho inverso, existe o aplicativo dos2unix) e sua sintaxe é bem simples. Em qualquer linux shell, digite:
$ unix2dos dataWithoutHeads.csv
A depender do tamanho do arquivo demorará bastante. Para se ter uma referência, na minha máquina (quad core 2.33GHz, 2gb de RAM) levou aproximadamente 10 min para converter 261MB de texto.
Agora, a execução do bulk insert será sem erros.