Niet-standaardtekstbestandsindelingen parseren met het scriptonderdeel

Van toepassing op:SQL Server SSIS Integration Runtime in Azure Data Factory

Wanneer je brondata in een niet-standaard formaat is gerangschikt, kan het handiger zijn om al je parsinglogica in één script te consolideren dan om meerdere Integration Services-transformaties aan elkaar te koppelen om hetzelfde resultaat te bereiken.

Voorbeeld 1: Parsen Row-Delimited records

Voorbeeld 2: Ouder- en kindrecords splitsen

Note

Als je een component wilt maken die je gemakkelijker kunt hergebruiken over meerdere Gegevensstroom-taken en pakketten, overweeg dan de code in dit voorbeeld van een scriptcomponent als uitgangspunt voor een aangepaste data flow-component. Zie Een aangepast gegevensstroomonderdeel ontwikkelen voor meer informatie.

Voorbeeld 1: Parsen Row-Delimited records

Dit voorbeeld laat zien hoe je een tekstbestand waarin elke kolom data op een aparte regel verschijnt kunt nemen en dit kunt parsen tot een bestemmingstabel met behulp van de Script-component.

Voor meer informatie over hoe de Scriptcomponent wordt geconfigureerd voor gebruik als transformatie in de dataflow, zie Creating a Synchronous Transformation with the Script Component en Creating an Asynchronous Transformation with the Script Component.

Om dit voorbeeld van Script Component te configureren

  1. Maak een tekstbestand aan met de naam rowdelimiteddata.txt dat de volgende brongegevens bevat en opslaan:

    FirstName: Nancy  
    LastName: Davolio  
    Title: Sales Representative  
    City: Seattle  
    StateProvince: WA  
    
    FirstName: Andrew  
    LastName: Fuller  
    Title: Vice President, Sales  
    City: Tacoma  
    StateProvince: WA  
    
    FirstName: Steven  
    LastName: Buchanan  
    Title: Sales Manager  
    City: London  
    StateProvince:  
    
    
  2. Open Management Studio en maak verbinding met een instantie van SQL Server.

  3. Selecteer een bestemmingsdatabase en open een nieuw queryvenster. Voer in het queryvenster het volgende script uit om de bestemmingstabel te maken:

    create table RowDelimitedData  
    (  
    FirstName varchar(32),  
    LastName varchar(32),  
    Title varchar(32),  
    City varchar(32),  
    StateProvince varchar(32)  
    )  
    
    
  4. Open SQL Server Data Tools en maak een nieuw Integration Services-pakket genaamd ParseRowDelim.dtsx.

  5. Voeg een Flat File connection manager toe aan het pakket, noem het RowDelimitedData en configureer het om verbinding te maken met het rowdelimiteddata.txt bestand dat je in een vorige stap hebt aangemaakt.

  6. Voeg een OLE DB connection manager toe aan het pakket en configureer het om verbinding te maken met de instantie van SQL Server en de database waarin je de bestemmingstabel hebt aangemaakt.

  7. Voeg een Gegevensstroom-taak toe aan het pakket en klik op het tabblad Gegevensstroom van SSIS Designer.

  8. Voeg een Flat File Source toe aan de dataflow en configureer deze om de RowDelimitedData connection manager te gebruiken. Selecteer op de pagina Kolommen van de Flat File Source Editor de enige beschikbare externe kolom.

  9. Voeg een Scriptcomponent toe aan de dataflow en configureer deze als een transformatie. Verbind de uitvoer van de Flat File Source met het scriptcomponent.

  10. Klik dubbel op de Script-component om de Script Transformation Editor te tonen.

  11. Selecteer op de pagina Invoerkolommen van de Script Transformation Editor de enige beschikbare invoerkolom.

  12. Selecteer op de pagina Inputs and Outputs van de Script Transformation Editor Output 0 en zet de SynchronousInputID op Geen. Maak 5 uitvoerkolommen aan, allemaal van type string [DT_STR] met een lengte van 32:

    • Voornaam

    • Achternaam

    • Title

    • City

    • StateProvince

  13. Op de Scriptpagina van de Script Transformation Editor klik je op Script Bewerken en voer je de code in die in de ScriptMain-klasse van het voorbeeld wordt weergegeven. Sluit de scriptontwikkelingsomgeving en de Script Transformation Editor.

  14. Voeg een SQL Server-bestemming toe aan de dataflow. Configureer het om de OLE DB connection manager en de RowDelimitedData-tabel te gebruiken. Verbind de uitvoer van de Script Component met deze bestemming.

  15. Voer het pakketbestand uit. Nadat het pakket is afgerond, bekijk je de records in de SQL Server-bestemmingstabel.

Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)  
  
    Dim columnName As String  
    Dim columnValue As String  
  
    ' Check for an empty row.  
    If Row.Column0.Trim.Length > 0 Then  
        columnName = Row.Column0.Substring(0, Row.Column0.IndexOf(":"))  
        ' Check for an empty value after the colon.  
        If Row.Column0.Substring(Row.Column0.IndexOf(":")).TrimEnd.Length > 1 Then  
            ' Extract the column value from after the colon and space.  
            columnValue = Row.Column0.Substring(Row.Column0.IndexOf(":") + 2)  
            Select Case columnName  
                Case "FirstName"  
                    ' The FirstName value indicates a new record.  
                    Me.Output0Buffer.AddRow()  
                    Me.Output0Buffer.FirstName = columnValue  
                Case "LastName"  
                    Me.Output0Buffer.LastName = columnValue  
                Case "Title"  
                    Me.Output0Buffer.Title = columnValue  
                Case "City"  
                    Me.Output0Buffer.City = columnValue  
                Case "StateProvince"  
                    Me.Output0Buffer.StateProvince = columnValue  
            End Select  
        End If  
    End If  
  
End Sub  
public override void Input0_ProcessInputRow(Input0Buffer Row)  
    {  
  
        string columnName;  
        string columnValue;  
  
        // Check for an empty row.  
        if (Row.Column0.Trim().Length > 0)  
        {  
            columnName = Row.Column0.Substring(0, Row.Column0.IndexOf(":"));  
            // Check for an empty value after the colon.  
            if (Row.Column0.Substring(Row.Column0.IndexOf(":")).TrimEnd().Length > 1)  
            // Extract the column value from after the colon and space.  
            {  
                columnValue = Row.Column0.Substring(Row.Column0.IndexOf(":") + 2);  
                switch (columnName)  
                {  
                    case "FirstName":  
                        // The FirstName value indicates a new record.  
                        this.Output0Buffer.AddRow();  
                        this.Output0Buffer.FirstName = columnValue;  
                        break;  
                    case "LastName":  
                        this.Output0Buffer.LastName = columnValue;  
                        break;  
                    case "Title":  
                        this.Output0Buffer.Title = columnValue;  
                        break;  
                    case "City":  
                        this.Output0Buffer.City = columnValue;  
                        break;  
                    case "StateProvince":  
                        this.Output0Buffer.StateProvince = columnValue;  
                        break;  
                }  
            }  
        }  
  
    }  

Voorbeeld 2: Ouder- en kindrecords splitsen

Dit voorbeeld laat zien hoe je een tekstbestand, waarin een scheidingsrij voorafgaat aan een ouderrecordrij gevolgd door een onbepaald aantal rijen voor een kindrecord, en deze kunt parsen in correct genormaliseerde ouder- en kindbestemmingstabellen met behulp van de Script-component. Dit eenvoudige voorbeeld kan gemakkelijk worden aangepast voor bronbestanden die meer dan één rij of kolom gebruiken voor elk ouder- en kindrecord, zolang er een manier is om het begin en einde van elk record te identificeren.

Caution

Dit voorbeeld is uitsluitend bedoeld voor demonstratiedoeleinden. Als je de sample meer dan één keer uitvoert, worden dubbele sleutelwaarden in de bestemmingstabel geplaatst.

Voor meer informatie over hoe de Scriptcomponent wordt geconfigureerd voor gebruik als transformatie in de dataflow, zie Creating a Synchronous Transformation with the Script Component en Creating an Asynchronous Transformation with the Script Component.

Om dit voorbeeld van Script Component te configureren

  1. Maak een tekstbestand aan met de naam parentchilddata.txt dat de volgende brongegevens bevat en opslaan:

    **********  
    PARENT 1 DATA  
    child 1 data  
    child 2 data  
    child 3 data  
    child 4 data  
    **********  
    PARENT 2 DATA  
    child 5 data  
    child 6 data  
    child 7 data  
    child 8 data  
    **********  
    
    
  2. Open SQL Server Management Studio en maak verbinding met een exemplaar van SQL Server.

  3. Selecteer een bestemmingsdatabase en open een nieuw queryvenster. Voer in het queryvenster het volgende script uit om de bestemmingstabellen te maken:

    CREATE TABLE [dbo].[Parents]([ParentID] [int] NOT NULL,  
    [ParentRecord] [varchar](32) NOT NULL,  
     CONSTRAINT [PK_Parents] PRIMARY KEY CLUSTERED   
    ([ParentID] ASC))  
    GO  
    CREATE TABLE [dbo].[Children]([ChildID] [int] NOT NULL,  
    [ParentID] [int] NOT NULL,  
    [ChildRecord] [varchar](32) NOT NULL,  
     CONSTRAINT [PK_Children] PRIMARY KEY CLUSTERED   
    ([ChildID] ASC))  
    GO  
    ALTER TABLE [dbo].[Children] ADD CONSTRAINT [FK_Children_Parents] FOREIGN KEY([ParentID])  
    REFERENCES [dbo].[Parents] ([ParentID])  
    
    
  4. Open SQL Server Data Tools (SSDT) en maak een nieuw Integration Services-pakket genaamd SplitParentChild.dtsx.

  5. Voeg een Flat File connection manager toe aan het pakket, noem het ParentChildData en configureer het om verbinding te maken met het parentchilddata.txt bestand dat je in een vorige stap hebt aangemaakt.

  6. Voeg een OLE DB connection manager toe aan het pakket en configureer deze om verbinding te maken met de instantie van SQL Server en de database waarin je de bestemmingstabellen hebt gemaakt.

  7. Voeg een Gegevensstroom-taak toe aan het pakket en klik op het tabblad Gegevensstroom van SSIS Designer.

  8. Voeg een Flat File Source toe aan de dataflow en configureer deze om de ParentChildData connection manager te gebruiken. Selecteer op de pagina Kolommen van de Flat File Source Editor de enige beschikbare externe kolom.

  9. Voeg een Scriptcomponent toe aan de dataflow en configureer deze als een transformatie. Verbind de uitvoer van de Flat File Source met het scriptcomponent.

  10. Klik dubbel op de Script-component om de Script Transformation Editor te tonen.

  11. Selecteer op de pagina Invoerkolommen van de Script Transformation Editor de enige beschikbare invoerkolom.

  12. Selecteer op de pagina Inputs and Outputs van de Script Transformation Editor Output 0, hernoem het naar ParentRecords en stel de SynchronousInputID in op Geen. Maak 2 uitvoerkolommen aan:

    • ParentID (de primaire sleutel), van het type vierbyte ondertekend geheel getal [DT_I4]

    • ParentRecord, van het type string [DT_STR] met een lengte van 32.

  13. Maak een tweede output aan en noem die ChildRecords. De SynchronousInputID van de nieuwe uitvoer is al ingesteld op Geen. Maak 3 uitvoerkolommen aan:

    • ChildID (de primaire sleutel), van het type vierbyte ondertekend geheel getal [DT_I4]

    • ParentID (de vreemde sleutel), ook van het type vierbyte ondertekend geheel [DT_I4]

    • ChildRecord, van het type string [DT_STR] met een lengte van 50

  14. Klik op de Scriptpagina van de Script Transformation Editor op Script Bewerken. In de ScriptMain-klasse voer je de code in die in het voorbeeld wordt getoond. Sluit de scriptontwikkelingsomgeving en de Script Transformation Editor.

  15. Voeg een SQL Server-bestemming toe aan de dataflow. Verbind de ParentRecords-uitvoer van de Script Component met deze bestemming. Configureer het om de OLE DB-verbindingsmanager en de Parents-tabel te gebruiken.

  16. Voeg een extra SQL Server Destination toe aan de dataflow. Verbind de ChildRecords-uitvoer van de Script Component met deze bestemming. Configureer het om de OLE DB-verbindingsmanager en de Children-tabel te gebruiken.

  17. Voer het pakketbestand uit. Nadat het pakket is afgerond, bekijk je de ouder- en kindrecords in de twee SQL Server-bestemmingstabellen.

Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)  
  
    Static nextRowIsParent As Boolean = False  
    Static parentCounter As Integer = 0  
    Static childCounter As Integer = 0  
  
    ' If current row starts with separator characters,  
    '  then following row contains new parent record.  
    If Row.Column0.StartsWith("***") Then  
        nextRowIsParent = True  
    Else  
        If nextRowIsParent Then  
            ' Current row contains parent record.  
            parentCounter += 1  
            Me.ParentRecordsBuffer.AddRow()  
            Me.ParentRecordsBuffer.ParentID = parentCounter  
            Me.ParentRecordsBuffer.ParentRecord = Row.Column0  
            nextRowIsParent = False  
        Else  
            ' Current row contains child record.  
            childCounter += 1  
            Me.ChildRecordsBuffer.AddRow()  
            Me.ChildRecordsBuffer.ChildID = childCounter  
            Me.ChildRecordsBuffer.ParentID = parentCounter  
            Me.ChildRecordsBuffer.ChildRecord = Row.Column0  
        End If  
    End If  
  
End Sub  
public override void Input0_ProcessInputRow(Input0Buffer Row)  
    {  
  
    int static_Input0_ProcessInputRow_childCounter = 0;  
    int static_Input0_ProcessInputRow_parentCounter = 0;  
    bool static_Input0_ProcessInputRow_nextRowIsParent = false;  
  
        // If current row starts with separator characters,   
        // then following row contains new parent record.   
        if (Row.Column0.StartsWith("***"))  
        {  
            static_Input0_ProcessInputRow_nextRowIsParent = true;  
        }  
        else  
        {  
            if (static_Input0_ProcessInputRow_nextRowIsParent)  
            {  
                // Current row contains parent record.   
                static_Input0_ProcessInputRow_parentCounter += 1;  
                this.ParentRecordsBuffer.AddRow();  
                this.ParentRecordsBuffer.ParentID = static_Input0_ProcessInputRow_parentCounter;  
                this.ParentRecordsBuffer.ParentRecord = Row.Column0;  
                static_Input0_ProcessInputRow_nextRowIsParent = false;  
            }  
            else  
            {  
                // Current row contains child record.   
                static_Input0_ProcessInputRow_childCounter += 1;  
                this.ChildRecordsBuffer.AddRow();  
                this.ChildRecordsBuffer.ChildID = static_Input0_ProcessInputRow_childCounter;  
                this.ChildRecordsBuffer.ParentID = static_Input0_ProcessInputRow_parentCounter;  
                this.ChildRecordsBuffer.ChildRecord = Row.Column0;  
            }  
        }  
  
    }