0

我有一个带有简单查询的 OLE DB 源,该查询将平面 csv 文件写入网络。如果我只这样做,行会从源代码写入文件。但是,如果有超过 0 行,我只想这样做。

因此,我添加了一个变量 (apptCount) 和一个条件拆分。(第一次使用这些)数据查看器显示行在 oledb 数据源和映射到变量 apptCount 的行计数对象之间。数据查看器显示行也在行计数对象和条件拆分对象之间。在有条件的吐口水中,我将案例 1 设置为 @[User::apptCount]>0

但是,不会将任何行写入 csv 文件。任何帮助表示赞赏。/jb

4

2 回答 2

0

这不起作用,所以我退出并使用控制流中的 returnValue 直接在执行 sql 事件中设置变量,然后使用表达式约束。比尝试在数据流中设置行数要容易得多。

于 2020-07-21T14:49:12.620 回答
0

只有在数据流开始和完成时才会读取/写入变量。当 DF 正在运行时,条件拆分将使用@[User::apptCount]数据流开始之前的值(可能是设计时值 0,除非您以其他方式对其进行了初始化)。

您的选择是运行两次查询(执行获得预期行数的 SQL 任务),然后根据需要启用/禁用 DF。或者让它 OLEDB Source -> Row Count -> Flat File 目标,然后如果 Row Count 变量为零,则进入条件文件系统任务并删除文件。

您还可以检查,因为如果 DF 启动,我认为它会将您的输出初始化为一个空文件,这可能是您系统的预期行为,也可能不是。如果文件的存在意味着你有数据,消费者可能会失望地看到它是空的。

滚动您自己的行数转换

作为一个思想实验,让我们将行计数转换实现为脚本组件。这是一个微不足道的组件。

将行计数变量添加@[User::apptCount]到 ReadWriteVariables 集合

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    int mRowCount;

    public override void PreExecute()
    {
        base.PreExecute();
        this.mRowCount = 0;
    }

    public override void PostExecute()
    {
        base.PostExecute();
        this.Variables.apptCount = this.mRowCount;
    }

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        mRowCount++;
    }
}

而已。1 个局部变量 mRowCount,我们在PreExecute. 在 PostExecuted 中,我们将局部成员变量的值分配给我们传入的全局/SSIS 变量。在 *ProcessInputRow 方法中,我们只是增加成员变量。

如果您尝试在 Pre/Post Execute 之外的任何地方访问或修改 apptCount 的值,则它将无法正常工作。我认为在某一时刻(2005 天),它可以让你这样做,但不会发生任何变化,但现在我认为它正确地引发了异常。数据查看器可能正在做类似的事情。它批量处理 100 行或其他任何内容并将它们显示在网格框中,但这只是内部/成员变量。数据查看器无法执行“将此行发送到错误路径”之类的操作。这只是检查。

SSIS 执行引擎旨在尽可能并行。除了像 PostExecute 这样的协调/线程安全方法外,没有办法让内部部分暴露给外部部分。

我想如果你愿意,你可以编写一个异步脚本组件,如果至少接收到一行,它只会将行发送到输出缓冲区。我不会那样做的。这是一个没有任何好处的维护和繁琐的编码,但它是一种选择。

于 2020-07-16T16:38:07.097 回答