Incompatibilidade de tipo T-SQL BULK INSERT

Oct 15 2020

Estou tentando fazer um BULK INSERT simples de um grande arquivo CSV para uma tabela. A tabela e o arquivo possuem colunas correspondentes. Este é o meu código:

BULK INSERT myTable
FROM 'G:\Tests\mySource.csv'
WITH (
    FIRSTROW = 2,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n',
    -- ROWTERMINATOR = '0x0a',
    BATCHSIZE = 1000,
    MAXERRORS = 2
)
GO

Como você pode ver, tentei com terminadores de linha \ne 0x0a(e muitos outros)

Continuo recebendo um erro de incompatibilidade de tipo:

Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 18 (createdAt).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 3, column 18 (createdAt).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 4, column 18 (createdAt).
Msg 4865, Level 16, State 1, Line 1
Cannot bulk load because the maximum number of errors (2) was exceeded.
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)".

A coluna createdAté do tipo datetime:

CREATE TABLE [dbo].[myTable]
(
    ...
    [createdAt] [datetime] NULL,
    ...
)

Estes são os valores da createdAtcoluna retirados das três primeiras linhas:

2020-08-22 13:51:57
2020-08-22 14:13:13
2020-08-22 14:16:23

Também tentei com um formato de número diferente, conforme sugerido. Também tentei alterar o tipo de coluna para DATETIME2(n):

2020-08-22T13:51:57
2020-08-22T14:13:13
2020-08-22T14:16:23

Não tenho ideia do que mais revisar.

Eu apreciaria qualquer ajuda.

Obrigado!

Respostas

2 marc_s Oct 15 2020 at 16:47

Existem muitos formatos de literais de string a serem convertidos em datas e horas com suporte do SQL Server - consulte os Manuais Online do MSDN sobre CAST e CONVERT . A maioria desses formatos depende de quais configurações você tem - portanto, essas configurações podem funcionar algumas vezes - e às vezes não. E o DATETIMEtipo de dados em particular é notoriamente exigente sobre quais formatos de literais de string funcionam - e quais outros (a maioria) não ... DATETIME2(n)é muito mais indulgente e menos exigente de lidar!

A maneira de resolver isso é usar o formato de data ISO-8601 (ligeiramente adaptado) que é compatível com o SQL Server - esse formato funciona sempre - independentemente do idioma do SQL Server e das configurações de formato de data.

O formato ISO-8601 é compatível com o SQL Server e vem em dois tipos:

  • YYYYMMDDapenas para datas (sem parte do tempo); nota aqui: sem travessões! , isso é muito importante! NÃOYYYY-MM-DD é independente das configurações de formato de data em seu SQL Server e NÃO funcionará em todas as situações!

ou:

  • YYYY-MM-DDTHH:MM:SSpara datas e horas - observe aqui: este formato tem travessões (mas podem ser omitidos) e um Tdelimitador fixo entre a data e a hora do seu DATETIME.

Isso é válido para SQL Server 2000 e mais recente.

Se você usar o SQL Server 2008 ou mais recente e o DATEtipo de dados (apenas DATE- não DATETIME !), Então você também pode usar o YYYY-MM-DDformato e isso também funcionará com quaisquer configurações em seu SQL Server.

Não me pergunte por que todo esse tópico é tão complicado e um tanto confuso - é assim que as coisas são. Mas com o YYYYMMDDformato, você deve estar bem para qualquer versão do SQL Server e para qualquer configuração de idioma e formato de data em seu SQL Server.

A recomendação para o SQL Server 2008 e mais recente é usar DATEse você precisar apenas da parte da data e DATETIME2(n)quando precisar de data e hora. Você deve tentar começar a eliminar o DATETIMEtipo de dados sempre que possível

No seu caso, eu tentaria uma de duas coisas:

  • se você puder - usar em DATETIME2(n)vez de DATETIMEcomo o tipo de dados da sua coluna - isso por si só pode resolver todos os seus problemas

  • se você não puder usar DATETIME2(n)- tente usar em 2020-08-22T13:51:57vez de 2020-08-22 13:51:57para especificar sua data e hora no arquivo de importação CSV.