SSIS和MSSQL - 在第3行导入带有标题的CSV,同时使用第1行和第2行数据

时间:2016-01-19 07:39:32

标签: sql-server import ssis

我的手上有一点难题。 我有一个定期导入csv文件的包,现在我有一个要导入的添加文件,但是这个文件的结构是挑战。

对于所有以前的文件,标题都在第1行,而下面的数据没有问题。新文件有2组标题,基本上第1行有2个标题级别和数据,第2行有这2个标题的详细信息。

第3行有一组新的标题,而第4行则包含所有其他需要的数据。

示例:

Month End       Level       
201501          CHEESE      
Region          Site        Pricing   Brand
Gauteng         Billys      100       Gouda
ECape           BeaconBay   150       Feta

现在SSIS包我通过多个foulders循环查找文件,然后导入到正确的表中,这些新文件将获得一个新表,但我不知道如何正确读取它们。我需要提取日期和级别,以及第4行的数据,第3行的标题。

我当前的软件包有一个Loop for files来查找所有这些文件,将文件路径和名称添加为变量(User :: File),并将其用于数据流。

但是我如何处理文件以允许读取文件(动态 - 格式不会改变,我无法在导入之前调整源文件)并正确地将行与日期和级别添加到表中( DataFlow中的Region_Data)。我认为它必须是在平面文件源上设置的东西?或者是否还有其他步骤?

提前感谢所有人和任何帮助。

----在@MiguelH的帮助下,我目前正在安装此设置。 (我使用Visual Studio工具进行应用程序(VB 2010)

使用的脚本是:

#Region "Imports"
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
#End Region


<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute()> _
<CLSCompliant(False)> _
Public Class ScriptMain
    Inherits UserComponent
    Dim StrMonthend As String
    Dim StrLevel As String
    Public Overrides Sub myInput_ProcessInputRow(ByVal Row As MyInputBuffer)
        do_output(Row.MyField)
    End Sub

    Public Sub do_output(ByRef data As String)
        Dim splitz() As String
        splitz = Split(data, ",")
        If splitz(0) <> "Month End" And splitz(0) <> "Region" Then
            With myoutputBuffer
                .AddRow()
                If UBound(splitz) < 2 Then
                    .MonthEnd = splitz(0)
                    .Level = splitz(1)
                    StrMonthend = splitz(0)
                    StrLevel = splitz(1)
                    .Brand = ""
                    .Description = ""
                    .Size = "0"
                    .VAT = "0"
                    .UnitsLY = "0"
                    .UnitsTY = "0"
                    .UnitsGrowth = "0"
                    .SalesInclLY = "0"
                    .SalesInclTY = "0"
                    .SalesInclGrowth = "0"
                    .SPInclLY = "0"
                    .SPInclTY = "0"
                    .SPInclGrowth = "0"
                    .Contrib = "0"
                    .BuyInd = "0"
                Else
                    .MonthEnd = StrMonthend
                    .Level = StrLevel
                    .Brand = splitz(0)
                    .Description = splitz(1)
                    .Size = splitz(2)
                    .VAT = splitz(3)
                    .UnitsLY = splitz(4)
                    .UnitsTY = splitz(5)
                    .UnitsGrowth = splitz(6)
                    .SalesInclLY = splitz(7)
                    .SalesInclTY = splitz(8)
                    .SalesInclGrowth = splitz(9)
                    .SPInclLY = splitz(10)
                    .SPInclTY = splitz(11)
                    .SPInclGrowth = splitz(12)
                    .Contrib = splitz(13)
                    .BuyInd = splitz(14)
                End If
            End With
        End If
    End Sub

    Public Overrides Sub PrimeOutput(ByVal Outputs As Integer, ByVal OutputIDs() As Integer, ByVal Buffers() As Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer)
        MyBase.PrimeOutput(Outputs, OutputIDs, Buffers)
    End Sub

    Public Overrides Sub CreateNewOutputRows()
    End Sub

End Class

如果我删除CLSComplient行,我会得到: Error 01 使用CLSComplient线路输入或输出我仍然会收到此错误。 Error 02

2 个答案:

答案 0 :(得分:0)

这是一个简单的脚本解决方案来解决您的问题。我们的想法是将单独的标题和详细记录重新格式化为单个记录。可以处理所有文件并将其输出到可扩展的文本文件。
然后,您将读取此输出文件以创建最终数据。 enter image description here 这是脚本..

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

Public Class ScriptMain
Inherits UserComponent
Dim StrMonthend As String
Dim StrLevel As String
Public Overrides Sub myInput_ProcessInputRow(ByVal Row As myinputBuffer)
    '
    ' Add your code here
    '          
    do_output(Row.Myfield)
End Sub
Public Sub do_output(ByRef data As String)
    Dim splitz() As String
    splitz = Split(data, ",")
    If splitz(0) <> "Month End" And splitz(0) <> "Region" Then
        With myoutputBuffer
            .AddRow()
            If UBound(splitz) < 2 Then
                .MonthEnd = splitz(0)
                .Level = splitz(1)
                StrMonthend = splitz(0)
                StrLevel = splitz(1)
                .Region = ""
                .Site = ""
                .Pricing = "0"
                .Brand = ""
            Else
                '
                ' detail
                '
                .MonthEnd = StrMonthend
                .Level = StrLevel
                .Region = splitz(0)
                .Site = splitz(1)
                .Pricing = splitz(2)
                .Brand = splitz(3)
            End If
        End With
    End If
End Sub
Public Overrides Sub PrimeOutput(ByVal Outputs As Integer, ByVal OutputIDs() As Integer, ByVal Buffers() As Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer)
    MyBase.PrimeOutput(Outputs, OutputIDs, Buffers)
End Sub
Public Overrides Sub CreateNewOutputRows()
End Sub
End Class

您需要在脚本转换中创建输出。我已将所有输出设置为STR。注意:确保SynchronoiusInputID中的“None” enter image description here

*********************额外的位置! *****************

以下是一些与您的解决方案进行比较的额外屏幕截图...请注意,我的列顺序与您的有点不同,但这无关紧要! enter image description here

答案 1 :(得分:0)

您可以将另一个Connection Manager添加到同一个文件中。将其设置为接收行中的所有内容作为一列。然后对行进行条件分割(也许使用SUBSTRING来获取'月末'或任何可以识别你需要的标题行的东西。)所以只有一行会经历。然后,您可以将其写入对象变量(结果集)。要再次使用它,您需要在For循环中运行它,只是为了将这些值分配给您可以定义的变量。

So to give it in steps. 1. Create new connection manager(CM) using only one column. 2. Create new data flow(DF) task. 3. In DF create flat file source and use the new CM. 4. add conditional split just below. Split values by using header identifier. 5. write to result set destination. (should only receive the one row.) 6. Outside Data flow use For each container to assign values in the result set to variables you can use.

希望你能明白我的意思。