如何在SSIS平面文件源中跳过错误行

4
我正在将一个17列的CSV文件读入数据库。 偶尔会有“少于17列”的行。 我试图忽略这行,但即使所有列都设置为忽略,我也无法忽略这行,导致程序失败。
如何忽略这些行?

什么错误导致程序包失败?是在读取文件还是写入数据库时失败了? - Mark Wojciechowicz
无法读取文件。谢谢。 - arcee123
什么错误? - Mark Wojciechowicz
无法在“电话类型”上找到分隔符,这表示该记录没有所有必需的信息。 “电话类型”列是字段列表中第15列(共17列),在多个记录中不存在。该文件包含超过400,000至数百万条记录。 - arcee123
1
我会使用一个带有Try..catch块的StreamReader来抛出错误行,以避免将整个文件加载到内存中:https://msdn.microsoft.com/zh-cn/library/system.io.streamreader(v=vs.110).aspx?f=255&MSPPError=-2147217396 - Mark Wojciechowicz
3个回答

4

解决方案概述

您可以通过添加一个Flat File Connection Manager,仅添加一个数据类型为DT_WSTR且长度为4000的列(假设其名称为Column0) - 所有列都被视为一个大列

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

详细解决方案

  1. 添加一个Flat file connection manager,选择文本文件
  2. 进入高级选项卡,删除除一列外的所有列
  3. 更改剩余列的数据类型为DT_WSTR,长度为4000

enter image description here

  1. 添加一个DataFlow Task
  2. 在Data Flow Task中添加Flat File Source、Script Component和OLEDB Destination

enter image description here

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

enter image description here

  1. 添加17个输出列(最佳输出列)
  2. OutputBufferSynchronousInput属性更改为None

enter image description here

  1. 将脚本语言选择为Visual Basic

enter image description here

  1. In the Script Editor write the following Script

    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. Map the Output Columns to the Destination Columns


这不是必需的。您可以使用DT_STR - Hadi

2
使用C#解决方案加载CSV并跳过没有17列的行:
使用脚本组件: 在输入/输出屏幕上添加所有带有数据类型的输出。
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?谢谢。 - arcee123
如果可能的话,我唯一想改变的是将分割方式更改为正则表达式,例如 https://dev59.com/WWMl5IYBdhLWcg3wwZTc,以便处理字符串内出现的引号和逗号等问题。 - KeithL
你可以使用流和ReadLine代替FileReadAllLines。 - KeithL
可以通过给定文件路径中的多个文件来完成吗? - SidC
@SidC - 我添加了一个关于如何处理多个文件的单独答案。 - KeithL

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
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接