2

我需要一些帮助。

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

输出到现在。

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

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

有一个类似的线程,但无法将解决方案应用于如何使用表达式来获取目标本身的行数。很久以前了,所以我创建了一个新的。

非常感谢您的帮助。

-阿克谢

4

4 回答 4

7

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

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

在此处输入图像描述

我添加了一个脚本任务来测试文件的大小。它具有对变量 AddHeader 的读/写访问权限。然后我使用这个脚本来确定文件是否为空。如果您对“空”的定义是它有一个标题行,那么我会调整 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;
    }

我循环了两次以确保生成附加场景

在此处输入图像描述

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

在此处输入图像描述

于 2013-05-07T04:41:38.817 回答
2

以下解决方案对我有用。您也可以尝试以下方法。

  1. 创建三个变量。

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".
    

平面文件连接管理器的表达式。 在此处输入图像描述

最终包装[截图]:

在此处输入图像描述

希望这可以帮助

于 2013-05-07T09:31:21.550 回答
2

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

实现您想要做的事情的一种方法是在控制流表面上有两个数据流任务,然后是一个脚本任务。这两个数据流任务将是相同的,只是它们将引用两个不同的平面文件连接管理器。同样,这两者之间的唯一区别是 ColumnsInTheFirstDataRow 的不同值;一个是真的,另一个是假的。

使用此脚本任务来决定这是第一次运行还是后续运行。保留此信息并在脚本中检查它。您可以为这些信息创建一个单独的表,或者使用一些日志表来推断它。

于 2013-05-05T16:59:04.867 回答
1

一个解法 ....

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

[@User::RowCount] < 0

现在,当您的包启动时,RowCount 的静态值为 -1 或另一个负数。当数据流在循环中首次启动时,ColumnNamesInFirstDataRow 属性的值为 TRUE。当第一个数据流完成时,行计数(即使它为零)被写入 RowCount 变量。在循环的第二次交互中,连接管理器被重新配置为不写入列名......


于 2013-05-08T13:44:38.307 回答