2008-09-03 21 views
14

Si funciono con la siguiente consulta en SQL Server 2000 Analizador de consultas:¿Es SQL Server Bulk Insert Transactional?

BULK INSERT OurTable 
FROM 'c:\OurTable.txt' 
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t', ROWS_PER_BATCH = 10000, TABLOCK) 

En un archivo de texto que se ajusta al esquema de OurTable por 40 líneas, pero luego cambia de formato para las últimas 20 líneas (digamos el último 20 las líneas tienen menos campos), recibo un error. Sin embargo, las primeras 40 líneas están comprometidas con la mesa. ¿Hay algo en la forma en que llamo Bulk Insert que no sea transaccional, o tengo que hacer algo explícito para forzar su reversión en caso de falla?

Respuesta

18

BULK INSERT actúa como una serie de declaraciones individuales de INSERT y, por lo tanto, si la tarea falla, no revierte todas las inserciones comprometidas.

Puede, sin embargo, ser colocado dentro de una transacción por lo que podría hacer algo como esto:

BEGIN TRANSACTION 
BEGIN TRY 
BULK INSERT OurTable 
FROM 'c:\OurTable.txt' 
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t', 
    ROWS_PER_BATCH = 10000, TABLOCK) 
COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
ROLLBACK TRANSACTION 
END CATCH 
+2

tenga cuidado con el registro de transacciones llenando etc. si está insertando MUCHAS filas. –

0

Intenta ponerlo dentro de la transacción definida por el usuario y ver qué pasa. En realidad, debería retroceder como lo describiste.

2

Como se indica en la definición BATCHSIZE para BULK INSERT en MSDN Library (http://msdn.microsoft.com/en-us/library/ms188365(v=sql.105).aspx):

" Si esto falla, SQL Server confirma o retrotrae la transacción para cada lote ... "

En conclusión, no es necesario agregar transaccionalidad a la inserción masiva.

+0

[Microsoft documentation suckzz !!] (http://technet.microsoft.com/es-es/library/ms188365.aspx) Dos días de prueba y, finalmente, noté que BULK INSERT no admite la reversión en un error de transacción de nivel de compilación. Me refiero a que necesita crear un procedimiento almacenado para la consulta de inserción masiva, luego rodee a exec su_procedimiento con "try/catch". También es muy importante definir MAXERRORS = 0 para detectar el primer error de inmediato. –

2

Puede deshacer las inserciones. Para hacer eso tenemos que entender dos cosas primero

BatchSize

: Número de filas que se inserta por transacción. El valor predeterminado es todo Archivo de datos. Entonces un archivo de datos está en la transacción

Digamos que tiene un archivo de texto que tiene 10 filas y la fila 8 y la Fila 7 tiene algunos detalles no válidos. Cuando realiza un Bulk Inserta el archivo sin especificar o especificando el tamaño del lote, 8 de cada 10 se insertan en la tabla. La fila inválida, es decir, 8vo y 7mo, falla y no se inserta.

Esto sucede porque el recuento predeterminado de MAXERRORS es 10 por transacción.

Como Per MSDN:

MAXERRORS:

especifica el número máximo de errores de sintaxis permitidos en los datos antes de la operación de importación masiva se cancela. Cada fila que no puede ser importada por la operación de importación masiva se ignora y se cuenta como un error . Si no se especifica max_errors, el valor predeterminado es 10.

Así finde fallan todas las 10 filas incluso si uno es inválida tenemos que establecer MAXERRORS=1 y BatchSize=1 Aquí el número de BatchSize también es importante.

Si especifica BatchSize y la fila no válida está dentro del lote en particular, solo retrotraerá el lote en particular, no todo el conjunto de datos. Tenga cuidado al elegir esta opción

Espero que esto resuelva el problema.

+0

¿Cuál es el punto de BatchSize = 1 en lugar de tener instrucciones INSERT individuales? – proteus

+0

Creo que con el tamaño de lote = 1 se compromete la transacción, que es igual que las instrucciones de inserción individuales, pero las últimas necesitan algunos números de bucle y fila para insertar sin duplicación. De acuerdo con su declaración, pero se puede hacer con la ayuda de los atributos BULK INSERT –