防止平面文件目标中的重复标头 - SSIS

时间:2013-05-05 12:08:32

标签: ssis

我需要一些帮助。

我从oledb源导入.csv文件中的一些数据。我不希望标题在目标中出现两次。如果我取消选中“第一个数据行中的列名”属性,则在第一次执行时也不会填充标题。

截至目前的输出。

Col1,Col2
A,B
Col1,Col2
C,D

如何以这样的方式运行包:如果文件为空,则插入标头。然后,如果再次执行,则不包括标题,只包括数据。

有一个类似的线程,但无法应用解决方案作为如何使用表达式来获取目标本身的行数。它回来了,所以我创造了一个新的。

非常感谢您的帮助。

-Akshay

4 个答案:

答案 0 :(得分:7)

也许我错过了一些东西,但这对我有用。我没有使用ColumnNamesInFirstDataRow的唯一问题

我创建了一个名为AddHeader的包级变量,输入Boolean并将其设置为True。我添加了一个名为FFCM的平面文件连接管理器,并将其配置为使用2列HeadCount(int),AddHeader(boolean)的CSV输出。在Connection Manager的属性中,我为属性“ColumnNamesInFirstDataRow”添加了一个Expression,并为其赋值@[User::AddHeader]

enter image description here

我添加了一个脚本任务来测试文件的大小。它具有对Variable AddHeader的读/写访问权限。然后我使用此脚本来确定文件是否为空。如果你的“empty”定义是它有一个标题行,那么我会调整if检查中的逻辑以匹配该长度。

    public void Main()
    {

        string path = Dts.Connections["FFCM"].ConnectionString;

        System.IO.FileInfo stats = null;
        try
        {
            stats = new System.IO.FileInfo(path);
            // checking length isn't bulletproof based on how the disk is configured
            // but should be good enough
            // http://stackoverflow.com/questions/3750590/get-size-of-file-on-disk
            if (stats != null && stats.Length != 0)
            {
                this.Dts.Variables["AddHeader"].Value = false;
            }
        }
        catch
        {
            // no harm, no foul
        }
        Dts.TaskResult = (int)ScriptResults.Success;
    }

我循环了两次,以确保我生成追加方案

enter image description here

我删除了我的文件并运行了包,只有一个标题。

enter image description here

答案 1 :(得分:2)

控制列名是否包含在输出文件中的属性是ColumnNamesInFirstDataRow。这是一个只读的财产。

实现您尝试执行的操作的一种方法是在控制流表面上有两个数据流任务,前面是脚本任务。这两个数据流任务将是相同的,除了它们将引用两个不同的平面文件连接管理器。同样,这两者之间的唯一区别是ColumnsInTheFirstDataRow的不同值;一个是真的,另一个是假的。

使用此脚本任务来确定这是第一次运行还是后续运行。保留此信息并在脚本中进行检查。您可以为此信息设置单独的表,也可以使用某个日志表来推断它。

答案 2 :(得分:2)

以下解决方案适合我。您还可以尝试以下方法。

  1. 创建三个变量。
  2. IsHeaderRequired RowCount TargetFilePath

    1. 使用执行SQL任务获取源行计数并将其保存 RowCount变量。
    2. 有脚本任务。添加只读变量TargetFilePathRowCount。添加读写变量IsHeaderRequired
    3. 编辑脚本并添加以下代码行。

          string targetFilePath = Dts.Variables["TargetFilePath"].Value.ToString();
          int rowCount = (int)Dts.Variables["RowCount"].Value;
      
          System.IO.FileInfo targetFileInfo = new System.IO.FileInfo(targetFilePath);
      
          if (rowCount > 0)
          {
              if (targetFileInfo.Length == 0)
              {
                  Dts.Variables["IsHeaderRequired"].Value = true;
              }
              else
              {
                  Dts.Variables["IsHeaderRequired"].Value = false;
              }
          }
      
          Dts.TaskResult = (int)ScriptResults.Success;
      
    4. 将脚本组件连接到数据库

    5. 点击平面文件的连接管理器[即你的目标文件]然后去 属性。在表达式中,请参阅如下所示 截图。

      Map the connectionString to variable "TargetFilePath".
      Map the ColumnNamesInFirstDataRow to "IsHeaderRequired".
      
    6. 平面文件连接管理器的表达式。 enter image description here

      最终包[screenshot]:

      enter image description here

      希望这有帮助

答案 3 :(得分:1)

解决方案......

首先,在Foreach循环范围内添加一个SSIS整数变量或更高 - 我将调用此RowCount - 并使其默认值为负(这很重要!)。接下来,向数据流添加行计数,并将结果分配给我们刚刚创建的RowCount SSIS变量。第三步,选择Connection Manager(不要双击)并打开“属性”窗口(F4)。找到Expressions属性,选择它,然后点击省略号(...)按钮。选择ColumnNamesInFirstDataRow属性,并使用如下表达式:

[@ User :: RowCount]< 0

现在,当您的包启动时,RowCount的静态值为-1或另一个负数。当数据流在循环中第一次启动时,ColumnNamesInFirstDataRow属性的值将为TRUE。当第一个数据流完成时,行计数(即使它为零)将写入RowCount变量。在循环的第二次交互中,然后将Connection Manager重新配置为NOT write column names ...