2009-01-26 19 views
30

Estoy tratando de insertar un archivo .csv en una base de datos con saltos de línea de Unix. El comando Me postulo es:Inserción masiva, SQL Server 2000, saltos de línea de unix

BULK INSERT table_name 
FROM 'C:\file.csv' 
WITH 
( 
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
) 

Si puedo convertir el archivo en formato Windows funciona la carga, pero no quiero hacer este paso adicional si se puede evitar. ¿Algunas ideas?

Respuesta

92

Me sentí obligado a contribuir ya que tenía el mismo problema, y ​​tengo que leer 2 archivos UNIX de SAP al menos un par de veces al día. Por lo tanto, en lugar de usar unix2dos, necesitaba algo con menos intervención manual y más automático a través de la programación.

Como se mencionó, el Char (10) funciona dentro de la cadena sql. No quería usar una cadena sql, así que usé '' '' + Char (10) + '' '', pero por alguna razón, esto no compiló.

Lo que hizo el trabajo era muy pulido: con (ROWTERMINATOR = '0x0a')

Problema resuelto con Hex!

Espero que esto ayude a alguien.

+0

Gracias @Randy J. Cambió la respuesta aceptada porque esta es una solución mejor. –

+0

Desafortunadamente, esto no funcionó para mi archivo de Unix que finaliza con LF, pero la solución de SQL dinámico funcionó. – samaspin

+0

Esto me salvó el día, ¡zas! – RBarryYoung

1

Una opción sería usar bcp, y configurar un archivo de control con '\n' como el carácter de salto de línea.

Aunque ha indicado que preferiría no hacerlo, otra opción sería usar unix2dos para procesar previamente el archivo en uno con '\r\n' saltos de línea.

Finalmente, puede usar la opción FORMATFILE en BULK INSERT. Esto usará un archivo de control bcp para especificar el formato de importación.

+0

pensé inserción masiva llama el módulo de BCP. ¿Me equivoco? –

+0

Lo hace, de ahí su capacidad de usar archivos bcp para especificar el formato de entrada. – ConcernedOfTunbridgeWells

0

Me parece que hay dos vías generales que se pueden tomar: alguna forma alternativa de leer el CSV en el script SQL o convertir el CSV de antemano con cualquiera de las numerosas maneras en que puede hacerlo (bcp, unix2dos, si es un rey de una sola cosa, probablemente incluso puedas usar tu editor de código para arreglar el archivo por ti).

¡Pero tendrá que dar un paso más!

Si este SQL se inicia desde un programa, es posible que desee convertir las terminaciones de línea en ese programa. En ese caso y usted decide codificar la conversión usted mismo, esto es lo que necesita tener en cuenta: 1. La terminación de línea podría ser \ n 2. o \ r \ n 3. o incluso \ r (Mac!) 4. buena pena, podría ser que algunas líneas tienen \ r \ n y otras \ n, cualquier combinación es posible a menos que controle de dónde vino el CSV

OK, OK. La posibilidad 4 es descabellada. Sucede en el correo electrónico, pero esa es otra historia.

13

Gracias a todos los que han respondido pero he encontrado mi solución preferida.

Cuando le dice a SQL Server ROWTERMINATOR = '\ n' esto lo interpreta como el terminador de fila predeterminado en Windows que en realidad es "\ r \ n" (usando la notación C/C++). Si el terminador de fila realmente es simplemente "\ n", deberá usar el SQL dinámico que se muestra a continuación.

DECLARE @bulk_cmd varchar(1000) 
SET @bulk_cmd = 'BULK INSERT table_name 
FROM ''C:\file.csv'' 
WITH (FIELDTERMINATOR = '','', ROWTERMINATOR = '''+CHAR(10)+''')' 
EXEC (@bulk_cmd) 

¿Por qué no se puede decir BULK INSERT ... (ROWTERMINATOR = CHAR (10)) es más allá de mí. No parece que pueda evaluar expresiones en la sección CON del comando.

Lo que hace arriba es crear una cadena del comando y ejecutar eso. Evitando cuidadosamente la necesidad de crear un archivo adicional o seguir pasos adicionales.

0

Creo que "ROWTERMINATOR = '\ n'" funcionaría. Sugeriría abrir el archivo en una herramienta que muestre "caracteres ocultos" para asegurarse de que la línea se termine como usted piensa. Yo uso Notepad ++ para cosas como esta.

+0

Sí, pensarías que funcionaría. Y también la mayoría de nosotros. Pero no es así '\ n' se reemplaza automáticamente por' \ r \ n', de ahí los requisitos para otras soluciones para obtener un LF por sí mismo. –

0

Se trata de esto. Unix usa LF (ctrl-J), MS-DOS/Windows usa CR/LF (ctrl-M/Ctrl-J).

Cuando usa '\ n' en Unix, se traduce a un caracter LF. En MS-DOS/Windows se traduce a CR/LF. Cuando su importación se ejecuta en el archivo formateado Unix, solo ve una LF.Por lo tanto, a menudo es más fácil ejecutar el archivo a través de unix2dos primero. Pero como dijiste en tu pregunta original, no quieres hacer esto (supongo que hay una buena razón por la que no puedes).

Por qué no puedes hacer:

(ROWTERMINATOR = CHAR(10)) 

Probablemente porque cuando se está analizando el código SQL, no es la sustitución del carbón de leña (10) con el carácter LF (porque ya está encerrado en comillas simples) O tal vez se interpreta como:

(ROWTERMINATOR = 
    ) 

¿Qué sucede cuando se repiten los contenidos de @bulk_cmd?

2

¡Es un poco más complicado que eso! Cuando le dice a SQL Server ROWTERMINATOR = '\ n' esto lo interpreta como el terminador de fila predeterminado en Windows que en realidad es "\ r \ n" (usando la notación C/C++). Si el terminador de fila realmente es "\ n", deberá usar el SQL dinámico que se muestra arriba. ¡Acabo de pasar la mayor parte de una hora averiguando por qué \ n realmente no significa \ n cuando se usa con BULK INSERT!

3

confirmo que la sintaxis

ROWTERMINATOR = '''+CHAR(10)+''' 

obras cuando se utiliza con un comando EXEC.

Si tiene varios caracteres ROWTERMINATOR (por ejemplo, un tubo y un avance de línea Unix), entonces la sintaxis para esto es:

ROWTERMINATOR = '''+CHAR(124)+''+CHAR(10)+''' 
Cuestiones relacionadas