如何在SSIS中导入具有不同的第一个行标题列和将标题添加到每个数据行的平面文件

时间:2015-04-23 00:35:56

标签: sql visual-studio ssis flat-file

我试图从SSIS(2008 R2)中的固定宽度平面文件加载数据,但第一行包含以下数据:

  1. 需要使用与其下方数据不同的固定宽度进行解析
  2. 第一行的解析数据需要附加到每一行 在该数据被单独解析后,它下面的数据中的项目。
  3. 最好的方法是什么?我对SSIS比较陌生,所以我尝试使用行计数和条件拆分来分离第一行,但我不确定如何解析Flat文件之外的数据进口商。我已经读到使用脚本转换可以工作,但我不知道代码应该是什么......

    举例来说,如果我的平面数据看起来像:

      

    Hamilton Beach 20150410 Sunny
      鲍勃男蓝黑色
      Bill Male BrownBrown
      GeorgeMale GreenBlonde
      JackieFemaleGreenBlack
      Jill FemaleBlue Black

    它应该在输出表中:

      

    Hamilton Beach,20150410,Sunny,Bob,Male,Blue,Black
      Hamilton Beach,20150410,Sunny,Bill,Male,Brown,Brown
      Hamilton Beach,20150410,Sunny,George,Male,Green,Blonde
      Hamilton Beach,20150410,Sunny,Jackie,Female,Green,Black
      Hamilton Beach,20150410,Sunny,Jill,Female,Blue,Black

1 个答案:

答案 0 :(得分:0)

你很幸运。 SSIS不支持混合记录类型,但您可以使用它,因为您只有1个标题行。

我的实现看起来像一个脚本任务,它读取我文件的第一行和一个读取其余数据的数据流任务。

enter image description here

阅读第一行

这个很简单。创建一个SSIS变量,将其命名为String类型FirstLine。将该值作为读/写值传递到脚本任务中。

enter image description here

使用此答案中的代码

Read only the first few lines of text from a file

现在您只需要将line1的值推入我们的SSIS级别变量。看起来像是

Dts.Variables["User::FirstLine"].Value = line1;

这假设您希望将整行存储到FirstLine中。如果您需要将其分配到单个字段中,那么您将需要实现该逻辑。您没有提供有关如何将“Hamilton Beach 20150410 Sunny”划分为单个部分的指导,但上述逻辑仍然适用。解析并分配到不同的SSIS级别变量。

我的具体实现创建了3个SSIS变量,所有类型字符串

  • 用户:: HeaderIHaveNoIdeaWhatThisIs
  • 用户:: HeaderObservationDate
  • 用户:: HeaderWeather

以下代码表示已经链接的内容

using System;
using System.Data;
using System.IO;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;

namespace ST_7edd5e6df63a4837afac15b86c21d639.csproj
{
    [System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {

        #region VSTA generated code
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion


        public void Main()
        {
            // User::HeaderIHaveNoIdeaWhatThisIs,User::HeaderObservationDate,User::HeaderWeather

            // https://stackoverflow.com/questions/9439733/read-only-the-first-few-lines-of-text-from-a-file
            string line1 = string.Empty;

            using (StreamReader reader = new StreamReader(@"C:\ssisdata\so_29811494.txt"))
            {
                line1 = reader.ReadLine();
            }

            // Magic here to understand how to split this out. Assuming this is also fixed width
            // Horrible, hard coded brittle approach taken
            //Hamilton Beach      20150410    Sunny
            string h1, h2, h3;
            h1 = line1.Substring(0, 20).TrimEnd();
            h2 = line1.Substring(20, 12).TrimEnd();
            h3 = line1.Substring(32, line1.Length - 32);

            Dts.Variables["User::HeaderIHaveNoIdeaWhatThisIs"].Value = h1;
            Dts.Variables["User::HeaderObservationDate"].Value = h2;
            Dts.Variables["User::HeaderWeather"].Value = h3;

            Dts.TaskResult = (int)ScriptResults.Success;
        }
    }
}

阅读其余数据

在平面文件连接管理器中,您希望将Skip标题行的值从0更改为1.这表示在我们读取前N行之前,不应开始验证数据和解析。像往常一样定义连接管理器。

enter image description here

enter image description here

将数据流任务连接到上面的脚本任务。在数据流任务中,使用平面文件源并连接派生列组件。派生列组件是我们如何将SSIS变量中的值传递到数据流中的。添加名为HeaderColumn的新列,并使用类似@[User::FirstLine]的表达式。

enter image description here

enter image description here

如果您注意到右侧的列表示数据类型为DT_NTEXT,则可能与目标列定义不匹配。您可能需要执行类似变量SUBSTRING(@[User::FirstLine], 1, 20)的子字符串。这导致数据类型为DT_WSTR,长度为20.您的目标是使此匹配成为目标定义。

您可能还需要使用DT_STR数据类型而不是DT_WSTR。在这种情况下,请在子字符串操作(DT_STR, 20, 1252)SUBSTRING(@[User::FirstLine], 1, 20)

中添加显式强制转换

源数据

我根据提供的数据定义了我的文件(点击编辑问题以获取定义而不剥离空格)

Hamilton Beach      20150410    Sunny
Bob   Male  Blue Black
Bill  Male  BrownBrown
GeorgeMale  GreenBlonde
JackieFemaleGreenBlack 
Jill  FemaleBlue Black