【问题标题】:SSIS: execute first task if condition met else skip to nextSSIS:如果条件满足则执行第一个任务,否则跳到下一个
【发布时间】:2012-03-02 09:40:18
【问题描述】:

我开始了解 SSIS,如果问题太简单,我深表歉意。

我在 foreach-loop-容器中有一组任务
第一个任务只需要某个用户变量不为空或不为空的情况下执行。
否则,流程应跳过第一个任务并继续执行第二个。

我将如何(详细)实现这一点?

【问题讨论】:

标签: sql-server ssis


【解决方案1】:

问题1:有两种方法可以解释您的逻辑:“...某个用户变量不为null或为空”:

  1. (变量不为空)或(变量为空)。
  2. (变量不为空)或(变量不为空)。

    这都是关于“不”这个词的对象。差异很细微,但会影响 Foreach 循环中的第一个任务执行的时间。出于演示目的,我假设您打算使用 #1。

    问题2:第一个任务不再是第一个。为了在 BIDS 环境中使用 SSIS 完成您希望完成的任务,您需要在以前称为“第一个任务”的任务前面放置另一个任务。这样您就可以从新的第一个任务对前一个第一个任务设置优先约束。 通过从托管代码动态设计 SSIS 可以实现您想要的,但我认为这个问题不保证与该设计选择相关的开销。 我喜欢使用一个空的序列容器作为“锚”任务——一个仅作为优先约束的起始端点而存在的任务。我大量记录它们。我不希望任何人删除“不必要的空容器”并在大厅里漫游几天摇头并重复“安迪,安迪,安迪......”但我离题了。

    在下面的示例中,我有两个优先约束留下空的序列容器。一个转到可以跳过的任务,另一个转到有时可以跳过的任务之后的任务。在有时可以跳过的任务和后面的任务之间需要第三个优先约束。重要的是要注意必须编辑此第三个优先约束并将“多个约束”选项设置为“或”。这允许在采用互斥的先前路径中的任何一个时执行后续任务。默认情况下,这设置为 AND 并且需要 both 路径才能执行。根据定义,这不会 - 可以不会 - 发生在互斥路径上。

    我测试了一个名为@MyVar 的 SSIS 字符串变量的值,看看它是 Null 还是 Empty。我对离开空序列容器的约束使用了仅表达式评估选项。表达方式各不相同,但建立了表达方式的互斥性。我的 Foreach 循环容器如下所示:

我希望这会有所帮助。

:{>

【讨论】:

    【解决方案2】:

    最好的办法是在表达式中使用“禁用属性”并根据条件给出表达式。只需搜索如何使用 disable 属性即可。

    【讨论】:

    • 这个问题对于下一个开发者来说并不明显。我用过,只是需要好好评论一下。
    【解决方案3】:

    用一个简单的解决方案代替已经给出的一些更复杂的解决方案怎么样?对于要有条件地跳过的任务,将表达式添加到 disabled 属性。任何产生真假结果的表达式都可以使用,因此对于问题示例,您可以使用:

    ISNULL(@[User::MY_VAR]) || @[User::MY_VAR]==""
    

    唯一的缺点是它可能不像其他一些解决方案那样可见,但实施起来要容易得多。

    【讨论】:

    • 我建议不要通过表达式设置禁用属性。很明显,disabled 属性是在之前评估的,但它发生在包生命周期的早期(在任何任务执行之前)。这可能会导致在 SSIS 已经评估 disabled 属性之后设置表达式中使用的变量的时间问题。在执行命中包时,表达式可能为真,但任务未被禁用(因为表达式之前为假并标记为启用)。更多信息:sqlis.com/sqlis/post/Disabling-tasks-Through-Expressions.aspx
    【解决方案4】:

    我将围绕需要具有以下条件的条件的任务创建一个For Loop Container@i 是循环计数器,@foo 是您要测试的用户变量):

    1. 初始化表达式@i=0
    2. 评估表达式@i<1 && !ISNULL(@Foo) && @Foo!=""
    3. 赋值表达式@i=@i+1

    【讨论】:

    • 首先使用循环似乎很奇怪,但我认为这是最好的解决方案,因为它也适用于更复杂的情况。您会看到此时发生了一些重要的事情(可读性)。
    【解决方案5】:

    无需创建“脚本” 我认为最好(也是更简单)的方法是在“第一个任务”之前在循环容器中添加一个空白脚本任务,将绿色箭头从它拖到“第一个任务”(显然将成为第二个任务)并使用进行检查的优先约束。

    为此,双击箭头,在“求值操作”中选择“表达式”并写下您的表达式。点击 OK 后箭头会变成蓝色,表示它不是一个简单的优先约束,它有一个分配给它的表达式。

    【讨论】:

    • 我认为您误解了这个问题。您在一个 for 循环中有多个任务。使用您的方法,整个过程可能会停止。
    • 不,一点也不。我使用这种方法。由于检查在循环内,它只会停止该交互并将一个移动到下一个
    【解决方案6】:

    希望我没有误解这个问题,但可能的解决方案如下所示。

    我创建了一个示例 ForEach 循环。循环本身是一个项目枚举器。它枚举数字 1、2、3。实际值存储在一个名为 LoopVariable 的变量中。

    还有一个名为FirstShouldRun 的变量,它是一个布尔变量,显示foreach 循环中的第一个任务是否应该运行。我将此变量的 EvaluateAsExpression 属性设置为 true,其表达式为 (@[User::LoopVariable] % 2) == 0。我想以此证明,每两次都应该开始第一个任务。

    这两个任务什么都不做,只是显示一个消息框,表明任务已经开始。

    我启动了包,第一次和第三次第一个任务没有启动。在第二个循环中,出现了 MessageBox(显示 "First started")。

    之后,您应该根据需要设置FirstShouldRun 变量。

    正如我在对 OP 的第一条评论中提到的,此解决方案基于 another answer 中编写的 Amos Wood 的想法。

    【讨论】:

      【解决方案7】:

      这有点棘手。

      您必须创建一个脚本任务并检查您的变量是否不为空。

      所以首先你有一个脚本任务,你的 Main() 函数中将包含以下代码:

      public void Main()
      {
          if (Dts.Variables["User::yourVariable"].Value != null)
          {
              Dts.TaskResult = (int)ScriptResults.Failure;
          }
          else
          {
              Dts.TaskResult = (int)ScriptResults.Success;
          }
      }
      

      然后,您从脚本任务创建两个连接,一个连接到您的变量不为空时需要执行的任务,另一个连接到下一个任务(或另一个脚本,如果您需要再次检查,如果变量不为空)。

      然后右键单击第一个连接的(绿色)箭头并选择“失败”。右键单击与下一个任务/脚本的连接并将其设置为“完成”。

      它应该看起来像这样:

      就是这样。

      【讨论】:

        猜你喜欢
        • 2021-01-28
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多