【问题标题】:How to Import Flat File in SSIS with different first Row Header Columns and Appending Headers to each data row如何在 SSIS 中导入具有不同第一行标题列并将标题附加到每个数据行的平面文件
【发布时间】:2015-06-30 22:23:47
【问题描述】:

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

  1. 需要使用与其下方数据不同的固定宽度进行解析,并且
  2. 需要将第一行的解析数据附加到每个 在它下面的数据中的项目,在该数据被单独解析之后。

解决此问题的最佳方法是什么?我对 SSIS 比较陌生,所以我尝试使用行计数和条件拆分来分离第一行,但我不确定如何在平面文件导入器之外解析数据。我读过使用脚本转换可以工作,但我不知道代码应该是什么......

例如,如果我有如下所示的平面数据:

汉密尔顿海滩 20150410 阳光明媚
Bob 男 蓝色 黑色
比尔男 BrownBrown
GeorgeMale GreenBlonde
JackieFemaleGreenBlack
吉尔女蓝黑

它应该在输出表中为:

汉密尔顿海滩,20150410,阳光明媚,鲍勃,男,蓝,黑
汉密尔顿海滩, 20150410, 阳光明媚, 比尔, 男, 布朗, 布朗
汉密尔顿海滩, 20150410, 阳光明媚, 乔治, 男, 绿色, 金发女郎
汉密尔顿海滩,20150410,阳光明媚,杰姬,女,绿色,黑色
汉密尔顿海滩,20150410,晴,吉尔,女,蓝,黑

【问题讨论】:

    标签: sql visual-studio ssis flat-file


    【解决方案1】:

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

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

    阅读第一行

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

    使用此答案中的代码

    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 header rows 的值从 0 更改为 1。这表示在我们读取前 N 行之前不应开始验证数据和解析。像往常一样定义你的连接管理器。

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

    如果您注意到右侧的列指示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
    

    【讨论】:

    • 这很有帮助,但我不确定如何安排控制流或 DFT 中的元素以使其工作。我需要两个平面文件连接流吗?另外,我希望将第一行解析为 3 个不同的组件。那么,我是否必须将这些传递给变量,然后将它们添加为列?如果是这样,这是怎么做到的?)...我觉得我在这里需要一个 ELI5...
    • @user3236992 不确定 ELI5 是什么,但我没有在这里使用。这都是原生 SSIS。将第一行解析为字符串。然后根据您需要的任何规则对其进行拆分。您会发现我假设标题也是固定宽度,但使用的大小与数据本身不同。只有你会知道这是否是正确的方法。
    猜你喜欢
    • 2020-08-20
    • 2019-11-10
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2011-12-15
    相关资源
    最近更新 更多