【问题标题】:how to skip a bad row in ssis flat file source如何跳过 ssis 平面文件源中的坏行
【发布时间】:2018-06-11 20:48:35
【问题描述】:

我正在将一个 17 列的 CSV 文件读入数据库。 有时,该文件有一个“少于 17 列”的行。 我试图忽略该行,但即使所有列都设置为忽略,我也无法忽略该行并且包失败。

如何忽略这些行?

【问题讨论】:

  • 什么错误导致打包失败?读取文件或写入数据库时​​是否失败?
  • 读取文件失败。谢谢。
  • 错误是什么?
  • 无法在“电话类型”上找到分隔符,它表示没有所有必要信息的记录。 “电话类型”列是字段列表中 17 列中的第 15 列,在几条记录中它不存在。该文件在给定文件中有超过 400,000 到几百万条记录。
  • 知道了,我会使用带有 Try..catch 块的 StreamReader 来丢弃坏行。这将避免将整个文件加载到内存中:msdn.microsoft.com/en-us/library/…

标签: sql-server csv ssis etl flat-file


【解决方案1】:

这是我的另一个答案中的@SidC评论。

这让您可以处理多个文件:

        //set up variables
        string line;
        int ctr = 0;

        string[] files = System.IO.Directory.GetFiles(@"c:/path", "filenames*.txt");
        foreach(string file in files)
        {
            var str = new System.IO.StreamReader(file);
            while((line = str.ReadLine()) != null)
            {
                // Work with line here similar to the other answer
            }
        }

【讨论】:

    【解决方案2】:

    解决方案概述

    您可以通过添加一个Flat File Connection Manager 来做到这一点,只添加一个数据类型为DT_WSTR 且长度为4000 的列(假设它的名称是Column0) - 所以所有列都被视为一列大专栏

    • Dataflow task 中,在Flat File Source 之后添加Script Component
    • Column0标记为输入列并添加17个输出列
    • Input0_ProcessInputRow方法中,通过分隔符拆分Column0,然后检查数组的长度是否为= 17然后将值分配给输出列,否则忽略该行。

    详细解决方案

    1. 添加平面文件连接管理器,选择文本文件
    2. 进入高级选项卡,删除除一列以外的所有列
    3. 将remianing Column的数据类型更改为DT_WSTR和length = 4000

    1. 添加数据流任务
    2. 在数据流任务中添加平面文件源、脚本组件和 OLEDB 目标

    1. 在脚本组件中选择Column0作为输入列

    1. 增加17个输出列(最优输出列)
    2. OutputBuffer SynchronousInput 属性更改为None

    1. 选择脚本语言为Visual Basic

    1. 在脚本编辑器中编写以下脚本

      Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
      
          If Not Row.Column0_IsNull AndAlso
                  Not String.IsNullOrEmpty(Row.Column0.Trim) Then
      
      
              Dim strColumns As String() = Row.Column0.Split(CChar(";"))
      
              If strColumns.Length <> 17 Then Exit Sub
      
      
              Output0Buffer.AddRow()
              Output0Buffer.Column = strColumns(0)
              Output0Buffer.Column1 = strColumns(1)
              Output0Buffer.Column2 = strColumns(2)
              Output0Buffer.Column3 = strColumns(3)
              Output0Buffer.Column4 = strColumns(4)
              Output0Buffer.Column5 = strColumns(5)
              Output0Buffer.Column6 = strColumns(6)
              Output0Buffer.Column7 = strColumns(7)
              Output0Buffer.Column8 = strColumns(8)
              Output0Buffer.Column9 = strColumns(9)
              Output0Buffer.Column10 = strColumns(10)
              Output0Buffer.Column11 = strColumns(11)
              Output0Buffer.Column12 = strColumns(12)
              Output0Buffer.Column13 = strColumns(13)
              Output0Buffer.Column14 = strColumns(14)
              Output0Buffer.Column15 = strColumns(15)
              Output0Buffer.Column16 = strColumns(16)
      
          End If
      
      End Sub
      
    2. 将输出列映射到目标列

    【讨论】:

    • 没必要。您可以使用DT_STR
    【解决方案3】:

    加载 CSV 并跳过没有 17 列的行的 C# 解决方案:

    使用脚本组件: 在输入/输出屏幕上添加所有带有数据类型的输出。

    string fName = @"C:\test.csv" // Full file path: it should reference via variable
    
    string[] lines = System.IO.File.ReadAllLines(fName);
    
    //add a counter
    int ctr = 1;
    
    foreach(string line in lines)
    {
        string[] cols = line.Split(',');
    
        if(ctr!=1) //Assumes Header row. elim if 1st row has data
        {
        if(cols.Length == 17)
        {
              //Write out to Output
              Output0Buffer.AddRow();
              Output0Buffer.Col1 = cols[0].ToString(); //You need to cast to data type
              Output0Buffer.Col2 = int.Parse(cols[1]) // example to cast to int
              Output0Buffer.Col3 = DateTime.Parse(cols[2]) // example of datetime
              ... //rest of Columns
        }
        //optional else to handle skipped lines
        //else 
        // write out line somewhere
        }
        ctr++; //increment counter
    }
    

    【讨论】:

    • 嗨 Keith....这是很棒的代码。你可以为非常大的文件调整它吗? > 1Gb?谢谢。
    • 如果可能的话,我唯一会改变的是将拆分更改为正则表达式,即stackoverflow.com/questions/18144431/regex-to-split-a-csv,以处理字符串中出现的问题,如引号中的引号和引号中的逗号跨度>
    • 您可以使用流和 ReadLine 代替 FileReadAllLines
    • 这可以通过给定文件路径中的多个文件来完成吗?
    • @SidC - 我添加了一个关于如何处理多个文件的单独答案。
    猜你喜欢
    • 2017-05-16
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多