SQL Server ed ALM su database


Il blog di Alessandro Alpi
Archivio Posts
Anno 2018

Anno 2017

Anno 2016

Anno 2015

Anno 2014

Anno 2013

Anno 2012

Anno 2011

Anno 2010

Anno 2009

Anno 2008

Anno 2007

Anno 2006

Split File Flat personalizzato

Quando abbiamo la necessità di leggere da un file csv, oppure delimitato da tabulazioni, utilizzare il flat file connection manager risulta utilissimo.

Con esso infatti è possibile leggere il file sorgente convertendo ogni colonna in un vero e proprio campo (fortemente tipizzato) da poter utilizzare poi nelle nostre trasformazioni successive. Come già indicato in questo post, il flat file connection manager ci consente di selezionare il carattere di separazione di ogni colonna, sia dalla lista già fornita, sia indicando il carattere che più ci aggrada.. Può capitare però di incappare in particolari casi, in cui il carattere di separazione è, per scelta di chi ci fornisce i dati, non "indicabile" nella lista del controllo SSIS.. E' raro trovare questi separatori (ad esempio sugli NG di microsoft, alcuni hanno chiesto come poter splittare un file separato da un codice ASCII 1 e la cui riga termina con ASCII 2) però è possibile..

Vi è da considerare l'ipotesi di utilizzo della bcp utility che consente di specificare, tramite le opzioni -t e -r rispettivamente il delimitatore di colonna e quello di riga, però proveremo a vedere com'è possibile personalizzare la suddivisione del flat file anche tramite SSIS.

Partiamo dal seguente scenario: supponiamo di ricevere un file da una piattaforma diversa da quella che stiamo utilizzando, formattato in questo modo:

A1-separatore-B1-separatore-C1-fineriga-

A2-separatore-B2-separatore-C2-fine_riga-

A3-separatore-B3-separatore-C3-fine_riga-

A4-separatore-B4-separatore-C4-fine_riga-

A5-separatore-B5-separatore-C5-fine_riga-

 

Assumiamo che separatore sia un ASCII 1 e fine_riga sia un ASCII 2 e supponiamo di voler ottenere una tabella a tre campi che possa contenere il file correttamente suddiviso. Un flat file connection manager non è sufficiente ai nostri scopi, perciò dobbiamo per forza di cose ricorrere all'utilizzo di script.

Infatti, una delle possibili soluzioni, è proprio quella di utilizzare Script Component in Data Flow in modalità Sorgente Dati. Ecco come procedere:

1) Control Flow - Creazione delle variabili ROW_DELIMITER e COLUMN_DELIMITER, intere, che conterranno il codice ASCII personalizzato (nell'esempio 2 e 1) e della variabile FileName, che contiene il nome del file da creare per la simulazione.

2) Control Flow - Aggiungere uno Script Task per la creazione del file di testo "simulato", corredato di questo semplice script:

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.IO

Public Class ScriptMain

   Public Sub Main()

      If File.Exists("C:\flat.ale") Then File.Delete("C:\flat.ale")

      Dim sw As New StreamWriter("C:\flat.ale")
      sw.Write("A1" & Chr(1) & "B1" & Chr(1) & "C1" & Chr(2))
      sw.Write("A2" & Chr(1) & "B2" & Chr(1) & "C2" & Chr(2))
      sw.Write("A3" & Chr(1) & "B3" & Chr(1) & "C3" & Chr(2))
      sw.Write("A4" & Chr(1) & "B4" & Chr(1) & "C4" & Chr(2))
      sw.Write("A5" & Chr(1) & "B5" & Chr(1) & "C5" & Chr(2))
      sw.Close()

      Dts.TaskResult = Dts.Results.Success

   End Sub

End Class

 

3) Control Flow - Aggiunta di un DataFlow Task

4) Spostarsi sul Data Flow - Aggiunta di uno Script Transformation Task, configurato (quando richiesto) come sorgente dati.

5) Data Flow - Configurazione Script Source:

Creo tre colonne nel buffer di output del file (chiamato SourceOutput), tipizzandole come stringhe lunghe due caratteri.

 

Passo le variabili utili alla gestione dinamica dei delimiter.

 

Progetto lo script per la gestione dello split custom:

 

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.IO

Public Class ScriptMain
  Inherits UserComponent

  Public Overrides Sub CreateNewOutputRows()

     Dim sr As New StreamReader(Variables.FileName)
     Dim curstring As String
     Dim strs As New System.Collections.Hashtable
     Dim i As Int32 = 1
     Dim charRead As Int32

     Do While Not sr.EndOfStream

        'leggo il carattere
        charRead = sr.Read()

        If charRead <> Variables.ROWDELIMITER And charRead <> Variables.COLDELIMITER Then
            curstring &= Convert.ToChar(charRead)
        Else
            ' aggiungo la stringa nella hashtable
            strs.Add(i, curstring)
            curstring = ""
            i += 1
            ' controllo il fine riga

            If charRead = Variables.ROWDELIMITER Then
               SourceOutputBuffer.AddRow()
               SourceOutputBuffer.A = strs(1).ToString
               SourceOutputBuffer.B = strs(2).ToString
               SourceOutputBuffer.C = strs(3).ToString
               strs.Clear()
               i = 1
            End If
       End If

    Loop

  End Sub

End Class

 

6) Data Flow - Imposto la destinazione in base alle mie esigenze, ad esempio un OLEDB Destination.

 la scelta sulla destinazione la lascio a voi

 

Il gioco è fatto.

In questo modo, abbiamo la possibilità di splittare il file come meglio crediamo. Il metodo, pur essendo customizzabile, ci lega comunque alla definizione delle colonne nel buffer di output dello script source, quindi ad ogni alterazione della struttura del flat file siamo costretti a ridefinire sia il buffer sia lo script. Del resto, il Flat File Connection Manager non ci consente di gestire i flussi in questo modo. Inoltre, il file sorgente, nella maggior parte dei casi, può cambiare all'inizio, ma poi la struttura rimane la medesima. Inoltre dobbiamo anche valutare i vantaggi che possiamo trarre da una soluzione di questo tipo. Una volta caricato il file, possiamo utilizzare tutti gli strumenti SSIS per gestire le trasformazioni anche più complesse. E' un modo per sostituire le sorgenti predefinite di SSIS.

 

Stay Tuned!

Categoria: SSIS 2005 tips
giovedì, 25 gen 2007 Ore. 09.22
Statistiche
  • Views Home Page: 601.390
  • Views Posts: 1.068.558
  • Views Gallerie: 641.208
  • n° Posts: 484
  • n° Commenti: 273



















Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003