locked
Carga de TXT con BCP

    Question

  • Hola amigos... tengo un problema al querer cargar un archivo TXT a una tabla en SQL 2008 mediante un BCP, este archivo viene delimitado por punto y coma (;), el problema surge en los campos numéricos ya que algunos vienen con decimales y el separador de decimal es una coma (,) si este indicador de decimal fuera punto (.) la carga resultaría sin problemas. Quisiera saber si hay alguna manera de indicarle al BCP que el separador de decimales es coma en lugar de punto para envitar que se caiga el proceso, ya sea en el archivo de formato o en la línea de comando misma. ¿alguien sabe como solucionar esto?. Muchas gracias
    Monday, April 19, 2010 4:56 PM

Answers

  • Existe otra opción, que es la usar OPENROWSET. Con los datos de ejemplo, habría que crear un archivo de formato que podría ser el siguiente:

    9.0
    2
    1       SQLCHAR       0       8       ";"      1     Col1         ""
    2       SQLCHAR       0       5       "\r\n"      2     Col2         ""

    Una vez creado el archivo de formato, podríamos acceder a esos datos (devolviendo ya los separadores decimales correctos para SQL Server) con la instrucción siguiente:

    SELECT CONVERT(DECIMAL(10,4),REPLACE(Col1, ',', '.')), CONVERT(DECIMAL(10,4),REPLACE(Col2, ',', '.')) FROM OPENROWSET( BULK '<tu archivo de datos>', FORMATFILE='<tu archivo de formato>') as a

    Luego sólo tendrías que añadir el INSERT para almacenar los datos en la tabla correcta.

    Tuesday, April 20, 2010 11:00 AM
  • Hola.

    Con el permiso de Carlos, la opción que te propone no usa el comando BCP, sería una sentencia sql (para lanzarla desde el Management Studio, por ejemplo). Y la sintaxis es la que ya te ha puesto:

    insert TABLACORRECTA
    SELECT CONVERT(DECIMAL(10,4),REPLACE(Col1, ',', '.')), CONVERT(DECIMAL(10,4),REPLACE(Col2, ',', '.')) 
    FROM OPENROWSET( BULK '<tu archivo de datos>', FORMATFILE='<tu archivo de formato>') as a

    Si no lo logras, nos dices.

     


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, April 20, 2010 7:50 PM
    Moderator

All replies

  • Si los campos están delimitados por ';' y así se le indica al BCP, los '.' y las ',' no deberían darle problemas. Cuál es el mensaje de error que usted recibe cuando dice que se "cae el proceso" ?
    Gustavo Larriera Sosa, Microsoft MVP | ascii164.blogspot.com | /*Este mensaje se proporciona tal como es, sin garantías de ninguna clase.*/
    Monday, April 19, 2010 5:37 PM
    Moderator
  • Es que se cae porque dice que hay Caracteres Inválidos... y si yo cambio esas comas por puntos en los decimales...

    carga sin ningún problema... pero obviamente no se puede estar cambiando a cada rato esos caracteres, la idea es que tome el archivo tal cual como se genera, ya que son varios millones de registros.

    Monday, April 19, 2010 5:54 PM
  • Puede usted pegar acá el texto exacto del mensaje de error?
    Gustavo Larriera Sosa, Microsoft MVP | ascii164.blogspot.com | /*Este mensaje se proporciona tal como es, sin garantías de ninguna clase.*/
    Monday, April 19, 2010 6:12 PM
    Moderator
  • aqui está el mensaje... la lina de arriba es el error, lo de abajo es lo que se intenta insertar... si yo cambio las comas por punto, pasa sin problemas... 

    gracias por tu tiempo

     

    #@ Row 4, Column 3: Invalid character value for cast specification @#
     HIP  100000007   000000001,990265 00,00 0000000000000,00 

    Monday, April 19, 2010 6:26 PM
  • Una forma posible de hacerlo:

    1. Reciba los datos en una tabla intermedia donde los números son de tipo string. De esta forma, los números que traen coma separadora de decimales son aceptados sin errores.
    2. Luego reemplace en la tabla intermedia las comas por puntos.
    3. Finalmente inserte en la tabla definitiva los datos reemplazados.

    El siguiente script es un ejemplo de lo anterior, donde el archivo de datos NUMEROS.TXt es asi:

    123,4567; 1,23
    234,5678; 2,34
    345,6789; 3,45
    456,7890; 4,56
    

    El script de carga entonces es así:

    -- Tabla intermedia que recibirá los numeros en formato de texto
    CREATE TABLE NumerosTxt (
      numero1 CHAR(10),
      numero2 CHAR(10) 
      )
    GO
    
    -- Tabla definitiva con los numeros
    CREATE TABLE Numeros (
      numero1 DECIMAL(10,4),
      numero2 DECIMAL(10,4) 
      )
    GO
    
    -- Cargar el archivo de numeros en la tabla intermedia  
    BULK INSERT NumerosTxt 
      FROM 'x:\numeros.txt' 
      WITH (FIELDTERMINATOR = ';' );
    GO
    
    -- Popular la tabla definitiva con los numeros
    INSERT INTO Numeros
      SELECT	CONVERT(DECIMAL(10,4),REPLACE(Numero1, ',', '.')), 
    			CONVERT(DECIMAL(10,4),REPLACE(Numero2, ',', '.'))
    			FROM NumerosTxt
    			
    
    Espero que le sirva de inspiración.
    Gustavo Larriera Sosa, Microsoft MVP | ascii164.blogspot.com | /*Este mensaje se proporciona tal como es, sin garantías de ninguna clase.*/
    Monday, April 19, 2010 7:57 PM
    Moderator
  • Si estimado, seria lo mas logico, el problema es que precisamente la tabla que intento llenar es la que se designó como temporal, y dentro de esa bd no se puede crear tablas nuevas, hay que trabajar con el modelo asignado...

    muchas gracias de todas formas...

    Tuesday, April 20, 2010 12:07 AM
  • Existe otra opción, que es la usar OPENROWSET. Con los datos de ejemplo, habría que crear un archivo de formato que podría ser el siguiente:

    9.0
    2
    1       SQLCHAR       0       8       ";"      1     Col1         ""
    2       SQLCHAR       0       5       "\r\n"      2     Col2         ""

    Una vez creado el archivo de formato, podríamos acceder a esos datos (devolviendo ya los separadores decimales correctos para SQL Server) con la instrucción siguiente:

    SELECT CONVERT(DECIMAL(10,4),REPLACE(Col1, ',', '.')), CONVERT(DECIMAL(10,4),REPLACE(Col2, ',', '.')) FROM OPENROWSET( BULK '<tu archivo de datos>', FORMATFILE='<tu archivo de formato>') as a

    Luego sólo tendrías que añadir el INSERT para almacenar los datos en la tabla correcta.

    Tuesday, April 20, 2010 11:00 AM
  • Comprendo tu... pero dime... ¿en donde deberia poner el Select y el Insert, en el archivo de formatos, en la linea de comando del BCP, como sería?
    Tuesday, April 20, 2010 4:11 PM
  • Hola.

    Con el permiso de Carlos, la opción que te propone no usa el comando BCP, sería una sentencia sql (para lanzarla desde el Management Studio, por ejemplo). Y la sintaxis es la que ya te ha puesto:

    insert TABLACORRECTA
    SELECT CONVERT(DECIMAL(10,4),REPLACE(Col1, ',', '.')), CONVERT(DECIMAL(10,4),REPLACE(Col2, ',', '.')) 
    FROM OPENROWSET( BULK '<tu archivo de datos>', FORMATFILE='<tu archivo de formato>') as a

    Si no lo logras, nos dices.

     


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, April 20, 2010 7:50 PM
    Moderator
  • comprendo Alberto muchas gracias, pero la carga debe ser por BCP... es norma del Banco aquí...
    Wednesday, April 21, 2010 2:02 PM
  • Hombre, entiendo que algún cambio te permitirán en el banco, ya que supongo que son los máximos interesados en que esto funcione: si te obligan a usar bcp, tienes que usar la tabla que te han dado y el archivo de origen lleva ese separador decimal, entonces no existe solución posible, al menos desde SQL.

    Como no te crees tu propio programita que cambie la "," por el "." como separador decimal en ese archivo de origen no vas a poder solucionarlo.

    Wednesday, April 21, 2010 2:20 PM