Discrepancia de tipo T-SQL BULK INSERT

Oct 15 2020

Estoy tratando de hacer un INSERTAR A GRANEL simple desde un archivo CSV grande a una tabla. La tabla y el archivo tienen columnas coincidentes. Este es mi codigo:

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

Como puede ver, lo he intentado con terminadores de fila \ny 0x0a(y muchos más)

Sigo recibiendo un error de falta de coincidencia de tipos:

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)".

La columna createdAtes de tipo datetime:

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

Estos son los valores de la createdAtcolumna tomados de las tres primeras filas:

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

También probé con un formato de número diferente como se sugiere. También intenté cambiar el tipo de columna a DATETIME2(n):

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

No tengo idea de qué más revisar.

Apreciaría cualquier ayuda.

¡Gracias!

Respuestas

2 marc_s Oct 15 2020 at 16:47

Hay muchos formatos de cadenas literales para convertir a fechas y horas compatibles con SQL Server; consulte los Libros en pantalla de MSDN sobre CAST y CONVERT . La mayoría de esos formatos dependen de la configuración que tenga; por lo tanto, estas configuraciones pueden funcionar algunas veces, y otras no. Y el DATETIMEtipo de datos en particular es notoriamente exigente sobre qué formatos de cadenas literales funcionan, y cuáles otros (la mayoría) no ... ¡ DATETIME2(n)es mucho más indulgente y menos exigente de manejar!

La forma de resolver esto es utilizar el formato de fecha ISO-8601 (ligeramente adaptado) que es compatible con SQL Server; este formato siempre funciona , independientemente de la configuración de idioma y formato de fecha de SQL Server.

El formato ISO-8601 es compatible con SQL Server y viene en dos versiones:

  • YYYYMMDDsolo por fechas (sin porción de tiempo); nota aquí: ¡ sin guiones! , eso es muy importante! NOYYYY-MM-DD es independiente de la configuración de formato de fecha en su servidor SQL y NO funcionará en todas las situaciones.

o:

  • YYYY-MM-DDTHH:MM:SSpara fechas y horas: tenga en cuenta aquí: este formato tiene guiones (pero se pueden omitir) y un Tdelimitador fijo entre la parte de fecha y hora de su DATETIME.

Esto es válido para SQL Server 2000 y versiones posteriores.

Si usa SQL Server 2008 o más reciente y el DATEtipo de datos (¡solo DATE, no DATETIME !), Entonces de hecho también puede usar el YYYY-MM-DDformato y eso también funcionará con cualquier configuración en su SQL Server.

No me pregunte por qué todo este tema es tan complicado y algo confuso, así es como es. Pero con el YYYYMMDDformato, debería estar bien para cualquier versión de SQL Server y para cualquier idioma y configuración de formato de fecha en su SQL Server.

La recomendación para SQL Server 2008 y versiones posteriores es usarlo DATEsi solo necesita la parte de la fecha y DATETIME2(n)cuando necesita tanto la fecha como la hora. Debería intentar comenzar a eliminar gradualmente el DATETIMEtipo de datos si es posible

En su caso, probaría una de dos cosas:

  • si puede, use en DATETIME2(n)lugar de DATETIMEcomo tipo de datos de su columna, eso por sí solo podría resolver todos sus problemas

  • si no puede usar DATETIME2(n), intente usar en 2020-08-22T13:51:57lugar de 2020-08-22 13:51:57especificar su fecha y hora en el archivo de importación CSV.