Importar archivos de un archivo de texto o excel a una tabla con SSIS

Lo ideal es usar el Wizard de importación de archivos de: Project > SSIS Import and Export Wizard, seleccionar el origen el archivo de texto o excel y en el destino seleccionar la base de datos correspondiente y la tabla, como se puede ver en este tutorial.
Hasta ahí todo muy lindo. Es lo que intenté hacer y no pude. Que se supone que es el camino ideal.
En el dtsx que me tocó modificar en aquel sprint, encontré algo raro: importaba el excel a txt, el txt lo importaba a una tabla “previa” que se borraba cada vez que se ejecutaba el dtsx y desde esa tabla previa con un Stored Procedure, se insertaba en la tabla “definitiva”, en la tabla de destino.
Lo mismo pasaba con los txt: lo importaba a la tabla “previa” y de ahí lo insertaba en la tabla de destino con un SP.
Intenté insertarlo directamente desde el excel a la tabla, porque era lo más razonable, pero me daba error en un campo NOT NULL, que en el excel estaba en NULL. Intenté usar un Data Transformation para convertir el NULL en “”, osea, en vacío, porque en SQL Server se diferencia el vacío: “”, de NULL:
Select vacío y NULL en SQL Server


Pero me seguía dando el error de que intentaba insertar un NULL en donde no se podía insertar un NULL.
Así que decidí tomar la triste decisión de usar la misma técnica que el colega que creó el ispac.

Acá están todos los detalles sobre cómo se resuelve el problema con esta técnica.
Supongamos que el archivo de entrada es un .txt con este contenido:

NOMBRE|APELLIDO|TELEFONO
Juan Jose|Lopez|011-1234-5678
María|Martinez|011-1111-5678
Laura|De la Vega|011-2222-2222

y necesitamos insertarlo en esta tabla:

Iniciamos el Wizard tal como nos dice en el tutorial al que hice referencia:

Seleccionamos el archivo:

Vamos a “Columns”:

Vemos que nos auto-detectó que las columnas están separadas por un pipe. Pero nosotros queremos que nos inserte toda la fila “cruda” en la tabla previa. Así que le cambiamos el caracter de separación de columnas por otro, así:

Elegimos el server y la base de datos:

Luego creamos la tabla “previa”:

CREATE TABLE [dbo].[testing_empleados_previa](
[data] varchar NOT NULL
)

El objeto que es el tipo de conexión a la base de datos, puede cambiarse por cualquier otro, en mi proyecto usamos siempre “ADO .NET”, que no sé cuál de todos de la lista es, así que en el wizard elijo el que viene por defecto y después lo cambio por otro objeto de destino y le pongo el “ADO .NET” y listo.
En “Destination” ponemos la tabla previa:

Ya nos está importando en la tabla previa:

Ahora tenemos que crear una función que nos genere un campo separado por cada registro insertado. Le agregamos la cantidad de campos que queramos. En el proyecto en el que estoy trabajando tenemos 56 campos jajaja, pero acá pongo 3 para no hacerlo tan largo:

GO
/ Object: UserDefinedFunction [dbo].[fnSplitStringText] Script Date: 9/8/2020 12:07:19 /
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnSplitStringText]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(
id int,
CAMPO1 varchar(max),
CAMPO2 varchar(max),
CAMPO3 varchar(max)
)

BEGIN
DECLARE @SQLString NVARCHAR(MAX)
DECLARE @start INT, @end INT
declare @cont int=1
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)

WHILE @start < LEN(@string) + 1 BEGIN
IF @end = 0
SET @end = LEN(@string) + 1

if (@cont =1)
BEGIN
    INSERT INTO @output (id, CAMPO1) 
    values(1, SUBSTRING(@string, @start, @end - @start))
END

if (@cont =2)
BEGIN
    UPDATE a 
    SET a.CAMPO2=''+ SUBSTRING(@string, @start, @end - @start)+''
    FROM @output  a
    WHERE Id=1
END

if (@cont =3)
BEGIN
    UPDATE a 
    SET a.CAMPO3=''+ SUBSTRING(@string, @start, @end - @start) +''
    FROM @output  a
    WHERE Id=1
END
SET @start = @end + 1 
SET @end = CHARINDEX(@delimiter, @string, @start)
SET @cont =@cont + 1

END
RETURN

END

Ahora solo falta hacer un select de esa tabla separando los campos con la función recién creada:

Y finalmente hacemos el insert con ese select:

Leave a Reply

Your email address will not be published. Required fields are marked *