将分号分隔文件导出到SQL Server的问题

时间:2018-05-26 19:45:31

标签: c# sql sql-server ssis

好吧,正如主题所说,我面临着将数据导出到SQL Server的问题 我有一个分号分隔文件,但是当我在文本中找到分号时我也会出现,例如:

ID;DESCRIPTION;VALUE
1;TEXT1;35
2;TEXT;2;45
3;TE;XT3;50

因为你可以看到我有一些我想删除的垃圾,因为这会改变列。

我有一些想法,比如制作一个标准的分号,在这种情况下,它将按行分为2个分号并删除多余的分号。

在我的情况下,这总是发生在1列,特别是地址列和补充,所以我确切知道列的编号是什么。

我无法询问处理此文件的人,因为系统是一个旧系统,他们不能像双引号那样放置限定符或只是更改分隔符。

我知道我可以通过脚本任务完成这项任务,但我对编程知之甚少,所以我试图寻找另一种方式。

我想再次说明这个问题发生在源文件上,所以当我配置平面文件连接时,它已经移动了列,所以我不能像派生列或其他任何东西那样进行任何处理。在将其加载到SSIS之前,我必须对文件本身进行更改。

我一直在寻找任何类型的论坛上的日子,我没有看到任何类似的问题和解决方案来解决这个问题,因为大多数人的示例文件已经有资格或类似的东西,如果你能帮助我,我真的很感激!

2 个答案:

答案 0 :(得分:0)

您提到您几乎没有编程知识,但脚本只是可以处理未包含的字段中的分隔符的解决方案。幸运的是,只有一个问题字段,因为除非您有其他规则来确定实际字段的开始和结束位置,否则无法解析模糊分隔符。

只要您确定只有一个带嵌入分隔符的字段,一个方法就是数据流源脚本组件。以下是创建一个的步骤:

  • 将脚本组件添加到数据流,并选择类型为

  • 的Source
  • 将平面文件连接管理器添加到脚本属性Connection Managers集合

  • 在脚本属性组件输入和输出

  • 下添加每个字段作为输出列
  • 编辑脚本源并使用下面的版本代码替换模板'CreateOutputRows()'方法代码。

请参阅脚本中的注释,指出实际文件需要自定义的位置。此版本将与3个字段的示例文件一起使用,第二个字段具有嵌入的分隔符。

public override void CreateNewOutputRows()
{

    const char FIELD_DEMIMITER = ';';
    ////*** change this to the zero-based index of the problem field
    const int BAD_FIELD_INDEX = 1;

    ////*** change this to the connection added to script componenent connection manager
    var filePath = this.Connections.FlatFileSource.ConnectionString; 

    string record = "";
    using (var inputFile = new System.IO.StreamReader(filePath))
    {
        record = inputFile.ReadLine();
        if(record != null)
        {
            //count header record fields to get expected field count for data records
            var headerFieldCount = record.Split(FIELD_DEMIMITER).Length;
            while (record != null)
            {

                record = inputFile.ReadLine();
                if(record == null)
                {
                    break; //end of file
                }

                var fields = record.Split(FIELD_DEMIMITER);
                var extraFieldCount = fields.Length - headerFieldCount;
                if (extraFieldCount < 0)
                {
                    //raise an error if fewer fields that we expect
                    throw new DataException(string.Format("Invalid record. {0} fields read, {1} fields in header.", fields.Length, headerFieldCount));
                }

                if (extraFieldCount > 0)
                {

                    var newFields = new string[headerFieldCount];
                    //copy preceding good fields
                    for (var i = 0; i < BAD_FIELD_INDEX; ++i)
                    {
                        newFields[i] = fields[i];
                    }

                    //combine segments of bad field into single field
                    var sourceFieldIndex = BAD_FIELD_INDEX;
                    var combinedField = new System.Text.StringBuilder();
                    while (sourceFieldIndex <= extraFieldCount + BAD_FIELD_INDEX)
                    {
                        combinedField.Append(fields[sourceFieldIndex]);
                        if(sourceFieldIndex < extraFieldCount + BAD_FIELD_INDEX)
                        {
                            combinedField.Append(FIELD_DEMIMITER); //add delimiter back to field value
                        }
                        ++sourceFieldIndex;
                    }
                    newFields[BAD_FIELD_INDEX] = combinedField.ToString();

                    //copy subsquent good fields
                    var targetFieldIndex = BAD_FIELD_INDEX + 1;
                    while (sourceFieldIndex < fields.Length)
                    {
                        newFields[targetFieldIndex] = fields[sourceFieldIndex];
                        ++sourceFieldIndex;
                        ++targetFieldIndex;
                    }
                    fields = newFields;
                }

                //create output record and copy fields
                this.Output0Buffer.AddRow();
                //*** change the code below to map source fields to the columns defined as script component output
                Output0Buffer.ID = fields[0];
                Output0Buffer.DESCRIPTION = fields[1];
                Output0Buffer.VALUE = fields[2];

            }
        }

    }

    this.Output0Buffer.SetEndOfRowset();

}

答案 1 :(得分:0)

您可以做的另一件事是将文本文件导入单个列(varchar(max))登台表,然后使用TSQL解析记录并将它们导入到最终目标表。