Analysieren von nicht standardmäßigen Textdateiformaten mit der Skriptkomponente
Wenn Ihre Quelldaten in einem nicht standardmäßigen Format angeordnet sind, dann könnte es u. U. praktischer sein, Ihre gesamte Parser-Logik in einem einzigen Skript zu konsolidieren, anstatt mehrere Integration Services-Transformationen miteinander zu verketten, um das gleiche Ergebnis zu erzielen.
Beispiel 1: Analysieren von nach Zeilen getrennten Datensätzen
Beispiel 2: Teilen von übergeordneten und untergeordneten Datensätzen
Hinweis |
---|
Wenn Sie eine Komponente erstellen möchten, die Sie einfacher in mehreren Datenflusstasks und Paketen wiederverwenden können, empfiehlt es sich, den Code in diesem Skriptkomponentenbeispiel als Ausgangspunkt für eine benutzerdefinierte Datenflusskomponente zu verwenden. Weitere Informationen finden Sie unter Entwickeln einer benutzerdefinierten Datenflusskomponente. |
Beispiel 1: Analysieren von nach Zeilen getrennten Datensätzen
In diesem Beispiel wird gezeigt, wie eine Textdatei, in der sich jede Datenspalte auf einer separaten Zeile befindet, mithilfe der Skriptkomponente in eine Zieltabelle konvertiert werden kann.
Weitere Informationen zum Konfigurieren der Skriptkomponente für die Verwendung als Transformation im Datenfluss finden Sie unter Erstellen einer synchronen Transformation mit der Skriptkomponente und Erstellen einer asynchronen Transformation mit der Skriptkomponente.
So konfigurieren Sie dieses Skriptkomponentenbeispiel
Erstellen und speichern Sie eine Textdatei mit dem Namen rowdelimiteddata.txt, die die folgenden Quelldaten enthält:
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:
Öffnen Sie Management Studio, und stellen Sie eine Verbindung zu einer Instanz von SQL Server her.
Wählen Sie eine Zieldatenbank aus, und öffnen Sie ein neues Abfragefenster. Führen Sie im Abfragefenster das folgende Skript aus, um die Zieltabelle zu erstellen:
create table RowDelimitedData ( FirstName varchar(32), LastName varchar(32), Title varchar(32), City varchar(32), StateProvince varchar(32) )
Öffnen Sie BI Development Studio, und erstellen Sie ein neues Integration Services-Paket mit dem Namen ParseRowDelim.dtsx.
Fügen Sie einen Verbindungs-Manager für Flatfiles zum Paket hinzu, benennen Sie ihn RowDelimitedData und konfigurieren Sie ihn, um eine Verbindung mit der Datei rowdelimiteddata.txt, die Sie in einem vorherigen Schritt erstellt haben, herzustellen.
Fügen Sie einen OLE DB-Verbindungsmanager zum Paket hinzu und konfigurieren Sie ihn, um eine Verbindung zu der Instanz von SQL Server und zur Datenbank, in der Sie die Zieltabelle erstellt haben, herzustellen.
Fügen Sie eine Datenflusstask zum Paket hinzu und klicken Sie auf die Registerkarte Datenfluss des SSIS-Designers.
Fügen Sie eine Flatfilequelle zum Datenfluss hinzu und konfigurieren Sie sie, um den RowDelimitedData-Verbindungs-Manager zu verwenden. Wählen Sie auf der Seite Spalten im Quellen-Editor für Flatfiles die einzelne verfügbare externe Spalte.
Fügen Sie eine Skriptkomponente zum Datenfluss hinzu, und konfigurieren Sie sie als Transformation. Verbinden Sie die Ausgabe der Flatfilequelle mit der Skriptkomponente.
Doppelklicken Sie auf die Skriptkomponente, um den Transformations-Editor für Skripterstellung anzuzeigen.
Wählen Sie auf der Seite Eingabespalten im Transformations-Editor für Skripterstellung die einzelne verfügbare Eingabespalte.
Wählen Sie auf der Seite Eingaben und Ausgaben im Transformations-Editor für Skripterstellung den Ausgang 0, und legen Sie SynchronousInputID auf 0 fest. Erstellen Sie 5 Ausgabespalten, die alle eine Typzeichenfolge [DT_STR] mit einer Länge von 32 aufweisen:
FirstName
LastName
Title
City
StateProvince
Klicken Sie im Transformations-Editor für Skripterstellung auf der Seite Skript auf Skript bearbeiten, und geben Sie den in der ScriptMain-Klasse des Beispiels angegebenen Code ein. Schließen Sie die Skriptentwicklungsumgebung und den Transformations-Editor für Skripterstellung.
Fügen Sie zum Datenfluss ein SQL Server-Ziel hinzu. Konfigurieren Sie es, um den OLE DB-Verbindungs-Manager und die RowDelimitedData-Tabelle zu verwenden. Verbinden Sie die Ausgabe der Skriptkomponente mit diesem Ziel.
Führen Sie das Paket aus. Untersuchen Sie nach der Beendung des Pakets die Datensätze in der SQL Server Zieltabelle.
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;
}
}
}
}
Beispiel 2: Teilen von übergeordneten und untergeordneten Datensätzen
In diesem Beispiel wird gezeigt, wie eine Textdatei, in der eine Trennzeichenzeile einer übergeordneten Datenzeile vorausgeht, auf die eine endlose Anzahl an untergeordneten Datenzeilen folgt, mithilfe der Skriptkomponente in ordnungsgemäß normalisierte übergeordnete und untergeordnete Zieltabellen konvertiert werden kann. Dieses einfache Beispiel kann in abgewandelter Form problemlos auf Quelldateien angewendet werden, die mehr als eine Zeile oder Spalte für jeden über- und untergeordneten Datensatz verwenden, vorausgesetzt, der Anfang und das Ende jedes Datensatzes kann bestimmt werden.
Vorsicht |
---|
Dieses Beispiel dient nur Demonstrationszwecken. Wenn Sie das Beispiel mehr als einmal ausführen, fügt es doppelte Schlüsselwerte in die Zieltabelle ein. |
Weitere Informationen zum Konfigurieren der Skriptkomponente für die Verwendung als Transformation im Datenfluss finden Sie unter Erstellen einer synchronen Transformation mit der Skriptkomponente und Erstellen einer asynchronen Transformation mit der Skriptkomponente.
So konfigurieren Sie dieses Skriptkomponentenbeispiel
- Erstellen und speichern Sie eine Textdatei mit dem Namen parentchilddata.txt, die die folgenden Quelldaten enthält:
******** 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 ********
Öffnen Sie SQL Server Management Studio, und stellen Sie eine Verbindung zu einer Instanz von SQL Server her.
Wählen Sie eine Zieldatenbank aus, und öffnen Sie ein neues Abfragefenster. Führen Sie im Abfragefenster das folgende Skript aus, um die Zieltabellen zu erstellen:
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])
Öffnen Sie Business Intelligence Development Studio, und erstellen Sie ein neues Integration Services-Paket mit dem Namen SplitParentChild.dtsx.
Fügen Sie einen Verbindungs-Manager für Flatfiles zum Paket hinzu, benennen Sie ihn ParentChildData und konfigurieren Sie ihn, um eine Verbindung mit der Datei parentchilddata.txt file, die Sie in einem vorherigen Schritt erstellt haben, herzustellen.
Fügen Sie einen OLE DB-Verbindungsmanager zum Paket hinzu und konfigurieren Sie ihn, um ihn zu der Instanz von SQL Server und zur Datenbank, in der Sie die Zieltabellen erstellt haben, hinzuzufügen.
Fügen Sie eine Datenflusstask zum Paket hinzu und klicken Sie auf die Registerkarte Datenfluss des SSIS-Designers.
Fügen Sie eine Flatfilequelle zum Datenfluss hinzu und konfigurieren Sie sie, um den ParentChildData-Verbindungs-Manager zu verwenden. Wählen Sie auf der Seite Spalten im Quellen-Editor für Flatfiles die einzelne verfügbare externe Spalte.
Fügen Sie eine Skriptkomponente zum Datenfluss hinzu, und konfigurieren Sie sie als Transformation. Verbinden Sie die Ausgabe der Flatfilequelle mit der Skriptkomponente.
Doppelklicken Sie auf die Skriptkomponente, um den Transformations-Editor für Skripterstellung anzuzeigen.
Wählen Sie auf der Seite Eingabespalten im Transformations-Editor für Skripterstellung die einzelne verfügbare Eingabespalte.
Wählen Sie auf der Seite Eingaben und Ausgaben im Transformations-Editor für Skripterstellung den Ausgang 0, benennen Sie ihn in ParentRecords um, und legen Sie SynchronousInputID auf Keine fest. Erstellen Sie 2 Ausgabespalten:
ParentID (der Primärschlüssel) vom Typ 4-Byte-Ganzzahl mit Vorzeichen [DT_I4]
ParentRecord vom Typ String [DT_STR] mit einer Länge von 32.
Erstellen Sie eine zweite Ausgabe, und nennen Sie sie ChildRecords. SynchronousInputID der neuen Ausgabe ist bereits auf Keine festgelegt. Erstellen Sie 3 Ausgabespalten:
ChildID (der Primärschlüssel) vom Typ 4-Byte-Ganzzahl mit Vorzeichen [DT_I4]
ParentID (der Fremdschlüssel), ebenfalls vom Typ 4-Byte-Ganzzahl mit Vorzeichen [DT_I4]
ChildRecord vom Typ String [DT_STR] mit einer Länge von 50.
Klicken Sie im Transformations-Editor für Skripterstellung auf der Seite Skript auf Skript bearbeiten. Geben Sie in der ScriptMain-Klasse den im Beispiel gezeigten Code ein. Schließen Sie die Skriptentwicklungsumgebung und den Transformations-Editor für Skripterstellung.
Fügen Sie zum Datenfluss ein SQL Server-Ziel hinzu. Verbinden Sie den ParentRecords-Ausgang der Skriptkomponente mit diesem Ziel. Konfigurieren Sie den OLE DB-Verbindungs-Manager und die übergeordnete Tabelle.
Fügen Sie zum Datenfluss ein weiteres SQL Server-Ziel hinzu. Verbinden Sie die ChildRecords-Ausgabe der Skriptkomponente mit diesem Ziel. Konfigurieren Sie es, um den OLE DB-Verbindungs-Manager und die Children-Tabelle zu verwenden.
Führen Sie das Paket aus. Untersuchen Sie nach der Beendung des Pakets die übergeordneten und untergeordneten Datensätze in den beiden SQL Server Zieltabellen.
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;
}
}
}
|