Analisando formatos de arquivo de texto fora do padrão com o componente Script
Aplica-se a: Tempo de execução de integração do SSIS do SQL Server
no Azure Data Factory
Quando seus dados de origem estiverem dispostos em um formato não padrão, talvez seja mais conveniente consolidar toda a sua lógica de análise em um único script do que reunir várias transformações Integration Services para chegar ao mesmo resultado.
Exemplo 1: analisar registros delimitados por linha
Exemplo 2: dividir registros pai e filho
Observação
Se desejar criar um componente que possa ser reutilizado mais facilmente em várias tarefas de fluxo de dados e em vários pacotes, procure utilizar o código deste exemplo de componente Script como o ponto inicial de um componente de fluxo de dados personalizado. Para obter mais informações, consulte Desenvolvendo um componente de fluxo de dados personalizado.
Exemplo 1: Analisando registros delimitados por linha
Este exemplo mostra como utilizar um arquivo de texto em que cada coluna de dados aparece em uma linha separada e analisá-lo em uma tabela de destino usando o componente Script.
Para obter mais informações sobre como configurar o componente Script para uso como uma transformação no fluxo de dados, consulte Criando uma transformação síncrona com o componente Script e Criando uma transformação assíncrona com o componente Script.
Para configurar esse exemplo de componente Script
Crie e salve um arquivo de texto nomeado rowdelimiteddata.txt contendo os seguintes dados de origem:
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:
Abra o Management Studio e conecte-se a uma instância do SQL Server.
Selecione um banco de dados de destino e abra uma nova janela de consulta. Na janela de consulta, execute o seguinte script para criar a tabela de destino:
create table RowDelimitedData ( FirstName varchar(32), LastName varchar(32), Title varchar(32), City varchar(32), StateProvince varchar(32) )
Abra o SQL Server Data Tools e crie um novo pacote de Integration Services nomeado ParseRowDelim.dtsx.
Adicione um gerenciador de conexões de arquivos simples ao pacote, nomeie-o como RowDelimitedData e configure-o para conectá-lo ao arquivo rowdelimiteddata.txt criado em uma etapa anterior.
Adicione um gerenciador de conexões OLE DB ao pacote e configure-o para conectá-lo à instância do SQL Server e ao banco de dados em que você criou a tabela de destino.
Adicione uma tarefa de Fluxo de Dados ao pacote e clique na guia Fluxo de Dados do Designer SSIS.
Adicione uma Fonte de Arquivo Simples ao fluxo de dados e configure-a para usar o gerenciador de conexões do RowDelimitedData. Na página Colunas do Editor de Fonte de Arquivo Simples, selecione a única coluna externa disponível.
Adicione um Componente Script ao fluxo de dados e configure-o como uma transformação. Conecte a saída da Fonte de Arquivo Simples ao Componente Script.
Clique duas vezes no componente Script para exibir o Editor de Transformação Scripts.
Na página Colunas de Entrada do Editor de Transformação Scripts, selecione a única coluna de entrada disponível.
Na página Entradas e Saídas do Editor de Transformação Scripts, selecione Saída 0 e defina seu SynchronousInputID como Nenhum. Crie 5 colunas de saída, todas com tipo cadeia de caracteres [DT_STR] com comprimento 32:
Nome
LastName
Title
City
StateProvince
Na página Script do Editor de Transformação Scripts, clique em Editar Script e digite o código mostrado na classe ScriptMain do exemplo. Feche o ambiente de desenvolvimento de scripts e o Editor de Transformação Scripts.
Adicione um Destino de SQL Server ao fluxo de dados. Configure-o para usar o gerenciador de conexões do OLE DB e a tabela RowDelimitedData. Conecte a saída do Componente Script a este destino.
Execute o pacote. Depois da conclusão do pacote, examine os registros na tabela de destino SQL Server.
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;
}
}
}
}
Exemplo 2: Dividindo registros pai e filho
Este exemplo mostra como utilizar um arquivo de texto, em que uma linha delimitadora precede uma linha de registro pai, que é seguida de um número indefinido de linhas de registro filho, e analisa-as em tabelas de destino pai e filho, adequadamente normalizadas, através do componente Script. Esse exemplo simples pode ser facilmente adaptado para arquivos de origem que utilizam mais de uma linha ou coluna para cada registro pai e filho, desde que exista uma forma de identificar o início e o fim de cada registro.
Cuidado
Esse exemplo é utilizado apenas para fins de demonstração. Se você executar o exemplo mais de uma vez, ele inserirá valores de chave duplicados na tabela de destino.
Para obter mais informações sobre como configurar o componente Script para uso como uma transformação no fluxo de dados, consulte Criando uma transformação síncrona com o componente Script e Criando uma transformação assíncrona com o componente Script.
Para configurar esse exemplo de componente Script
Crie e salve um arquivo de texto nomeado parentchilddata.txt contendo os seguintes dados de origem:
********** 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 **********
Abra o SQL Server Management Studio e conecte-se a uma instância do SQL Server.
Selecione um banco de dados de destino e abra uma nova janela de consulta. Na janela de consulta, execute o seguinte script para criar as tabelas de destino:
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])
Abra o SQL Server Data Tools (SSDT) e crie um novo pacote Integration Services nomeado SplitParentChild.dtsx.
Adicione um gerenciador de conexões de arquivos simples ao pacote, nomeie-o como ParentChildData e configure-o para conectá-lo ao arquivo parentchilddata.txt criado em uma etapa anterior.
Adicione um gerenciador de conexões OLE DB ao pacote e configure-o para conectar-se à instância do SQL Server e ao banco de dados em que você criou as tabelas de destino.
Adicione uma tarefa de Fluxo de Dados ao pacote e clique na guia Fluxo de Dados do Designer SSIS.
Adicione uma Fonte de Arquivo Simples ao fluxo de dados e configure-a para usar o gerenciador de conexões do ParentChildData. Na página Colunas do Editor de Fonte de Arquivo Simples, selecione a única coluna externa disponível.
Adicione um Componente Script ao fluxo de dados e configure-o como uma transformação. Conecte a saída da Fonte de Arquivo Simples ao Componente Script.
Clique duas vezes no componente Script para exibir o Editor de Transformação Scripts.
Na página Colunas de Entrada do Editor de Transformação Scripts, selecione a única coluna de entrada disponível.
Na página Entradas e Saídas do Editor de Transformação Scripts, selecione Saída 0, renomeie-a como ParentRecords e defina seu SynchronousInputID como Nenhum. Crie 2 colunas de saída:
ParentID (a chave primária), de tipo inteiro assinado de quatro bytes [DT_I4]
ParentRecord, de cadeia de caracteres de tipo [DT_STR] com comprimento de 32.
Crie uma segunda saída e nomeie-a como ChildRecords. O SynchronousInputID da nova saída já está definido como Nenhum. Crie 3 colunas de saída:
ChildID (a chave primária), de tipo inteiro assinado de quatro bytes [DT_I4]
ParentID (a chave estrangeira), também de tipo inteiro assinado de quatro bytes [DT_I4]
ChildRecord, de cadeia de caracteres de tipo [DT_STR] com comprimento de 50
Na página Script do Editor de Transformação Scripts, clique em Editar Script. Na classe ScriptMain, digite o código mostrado no exemplo. Feche o ambiente de desenvolvimento de scripts e o Editor de Transformação Scripts.
Adicione um Destino de SQL Server ao fluxo de dados. Conecte a saída de ParentRecords do Componente Script a esse destino. Configure-o para usar o gerenciador de conexões OLE DB e a tabela Pais.
Adicione outro Destino de SQL Server ao fluxo de dados. Conecte a saída ChildRecords do Componente Script a esse destino. Configure-o para usar o gerenciador de conexões OLE DB e a tabela Filhos.
Execute o pacote. Depois da conclusão do pacote, examine os registros pai e filho nas duas tabelas de destino do SQL Server.
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;
}
}
}
Consulte Também
Criando uma transformação síncrona com o componente Script
Criar uma transformação assíncrona com o componente de Script
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de