【问题标题】:SSIS and MSSQL - Importing CSV with headings on 3rd row, While using 1st and 2nd row data as wellSSIS 和 SQL - 在第 3 行导入带有标题的 CSV,同时使用第 1 行和第 2 行数据
【发布时间】:2016-04-24 14:04:57
【问题描述】:

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

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

第 3 行有一组新的标题,第 4 行下面有所有其他需要的数据。

例子:

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

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

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

但是我如何处理文件以允许读取文件(动态 - 格式不会改变,我无法在导入前调整源文件)并将带有日期和级别的行正确添加到表中(数据流中的 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

【问题讨论】:

  • 我认为唯一的方法是使用脚本任务。
  • 虽然有其自身的复杂性,但我的 VB 和 C 脚本知识还远远不够。

标签: sql-server import ssis


【解决方案1】:

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

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 中”


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


这里有一些额外的屏幕截图可以与您的解决方案进行比较...请注意,我的列顺序与您的略有不同,但这无关紧要!

【讨论】:

  • 非常感谢@MiguelH。不知何故,我得到了一个问题。在 Sub PrimeOutput 中,它的声明“子'PrimeOutput'不能被声明为'覆盖',因为它没有覆盖基类中的子。所以我按照它的建议将它更改为重载。但是这仍然有这个错误。“重载解决方案失败,因为没有可访问的“PrimeOutput”接受这个数量的参数。并且它肯定是用 sub 中的 3 定义的。对不起我真的很少vb知识实际上需要开始学习它
  • 嗯@Digi?您能否在原始问题的末尾发布您的新脚本?
  • 已添加 ^_^ 我为我拥有的最大文件添加了列
  • 几个问题..您使用的是哪个版本的 Visual Studio?脚本是否添加了 ?此错误是在脚本中发生(即当您输入“Public Overrides 等”时)还是在运行时崩溃?
  • @Digi。我已将您的代码(减去 复制到我的解决方案中并且它可以工作。我已经用一些额外的屏幕截图更新了我的答案,以便您可以对照我的解决方案检查您的解决方案。
【解决方案2】:

您可以将另一个连接管理器添加到同一个文件。将其设置为将行中的所有内容作为一列接收。然后对行进行有条件的拆分(也许使用 SUBSTRING 来获取“月末”或任何可以识别您需要的标题行。)所以只有一行会通过。然后,您可以将其写入对象变量(结果集)。要再次使用它,您需要在 For each 循环中运行它,以便将这些值分配给您可以定义的变量。

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.

希望你能明白我的意思。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-14
    • 2017-07-21
    • 2011-03-30
    • 2019-06-22
    • 2018-02-14
    • 1970-01-01
    • 2021-05-31
    • 2016-08-30
    相关资源
    最近更新 更多