本篇文章是Integration Services系列的第八篇,详细内容请参考原文


简介
在前面两篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcurrentExecutables属性。我们检查、演示并测试优先约束赋值为"成功"、"完成"、"失败"时对工作流的影响。
在这一篇,我们继续深入SSIS工作流管理——学习SSIS变量和优先约束表达式。
关于变量
打开Precedence.dtsx包。点击BIDS顶部的SSIS,在弹出的下拉菜单选择变量:

图8.1 选择变量工具栏
变量窗体将会如图8.2展示:

图8.2 变量窗体
在变量窗体的顶部,有一排SSIS变量使用的工具栏。这些按钮分别是(从左到右):
添加变量:添加一个变量
删除变量:刚打开时,这个按钮是禁用的,因为Precedence.dtsx包还没有配置SSIS变量
显示系统变量:许多系统变量是SSIS包的属性。部分系统变量是组成SSIS的组件和对象的属性
显示所有变量:显示SSIS包中的所有变量,忽略作用域
选择变量列:如图8.3所示,点击此按钮来设置在变量窗体显示哪些列

图8.3 选择变量列
变量名称、作用域、数据类型、值默认是显示的。你不能取消变量名称列,但你可以决定选择作业域、数据类型和值,你也可以选择命名空间和变量值更改时引发事件。
变量和命名空间
SSIS包中有两个默认的命名空间:System和User.你不能够添加系统变量,但是你可以添加用户变量并且你可以创建新的名称空间。变量名称在作用域和命名空间下必须唯一。这就意味着你可以在User命名空间有一个MyVariable变量,它的完整名称是User::MyVariable(命名空间::变量名称)。在本例中User::MyVariable作用域是Precedence.dtsx包。为了创建User2命名空间,你需要显示命名空间列,然后编辑文本从User改成User2.当你在同一作用域访问具有相同名称但不同命名空间的变量时,你应该使用完整的变量名称,否则你会收到一个类似下面的错误:
因为在不同的命名空间中存在具有该名称的变量,指定命名空间限定名称以防止歧义。
添加变量
为了演示表达式和SSIS优先约束,让我们给Precedence.dtsx包添加一个SSIS变量。点击变量窗体中的添加变量按钮。一个Int32类型的变量就会创建:

图8.4 添加变量
重命名变量为MyBool并修改其数据类型为Boolean:

图8.5 重命名变量并修改数据类型
现在我们就可以在优先约束的表达式中使用这个变量。
表达式和优先约束
右击Script Task 1和Script Task 2之间的优先约束,然后点击"编辑",打开优先约束编辑器:

图8.6 优先约束编辑器
优先约束编辑器有两个控件。它们被标记为“约束选项”和“多重约束”。当我创建SSIS包,
我自然的标记控制流任务按照自上而下的顺序执行。配置任务自上而下执行的一个积极作用:优先约束编辑器上的控件布局与优先约束在控制流的物理布局保持一致。“约束选项”设置前面任务或者优先约束"起点"的约束属性;“多重约束”设置后面任务或者优先约束"终点"的属性:

图8.7 优先约束起点和终点
在优先约束编辑器,点击"求值运算"下拉菜单检查选项列表:

图8.8 "求值运算"列表
默认选项是约束,前几篇中我们所使用的选项。选择"约束"允许我们配置何时(或是否)执行下一个任务——纯粹依赖于前一个任务的执行结果。"值"下拉列表包含约束求值的选项:成功、失败和完成。

图8.9 "值"列表
更改"求值运算"为表达式,并在表达式文本框中键入@MyBool

图8.10 修改约束选项
点击测试按钮验证文本框中的表达式。返回结果应该如下所示:

图8.11 表达式测试返回结果
注意SSIS变量MyBool的值是一个Boolean的数据类型,它的默认值设为False.键入到表达式文本框的表达式必须是True或False(布尔值)。
我可以编辑表达式为"@MyBool == True".表达式"@MyBool"和"@MyBool == True"逻辑上是等价的,因为它们生成相同的结果。
一旦配置好,关闭优先约束编辑器。你的控制流应该如下所示:

图8.12 配置为表达式约束的控制流
在BIDS下执行Precedence包,会提醒你选择Script Task 1成功或失败:

图8.13 选择Script Task 1执行结果
无论你选择哪个选项,都不会影响后面的执行。因为优先约束求值纯粹依赖SSIS变量MyBool的值。@MyBool默认是False,因此Script Task 2永远不会执行,因为优先约束永远不会等于True.
为了创建一个更有用的测试,打开Script Task 1编辑器,点击ReadWriteVariables属性的省略号。打开选择变量窗口。选择User::MyBool变量:

图8.14 选择变量
点击确定关闭选择变量窗口。你的脚本任务编辑器的ReadWriteVariables属性现在应该包含SSIS变量User::MyBool

图8.15 添加用户变量后
点击编辑脚本按钮打开脚本编辑器窗口。用代码8.1编辑Public Sub Main()中的脚本:

    Public Sub Main()
Dim sTaskName As String = Dts.Variables("TaskName").Value.ToString
Dim iResponse As Integer = MsgBox("Set MyBool to True?", MsgBoxStyle.YesNo, sTaskName)
If iResponse = MsgBoxResult.Yes Then
Dts.Variables("User::MyBool").Value = True
Else
Dts.Variables("User::MyBool").Value = False
End If Dts.TaskResult = ScriptResults.Success
End Sub

代码8.1
关闭脚本编辑器然后点击确定关闭脚本任务编辑器。在BIDS调试器下执行Precedence包:

图8.16
如果你点击"是"按钮,你会看到消息框显示Script Task 2执行完成:

图8.17
如果你点击"否"按钮,Script Task 2将不会执行:

图8.18
右击Script Task 2点击复制,然后在控制流的空白处右击选择粘贴。一个新的脚本任务添加到控制流,名称是"Script Task 2 1",重命名新脚本任务为"Script Task 3",并从Script Task 1连接一个新优先约束:

图8.19
如果你你现在在BIDS调试器下执行包,不管你将变量MyBool的值设置为True还是False,Script Task 1都会成功执行。当它成功时,Script Task 1与Script Task 3之间的优先约束求值为True,然后会显示Script Task 3完成的消息框:

图8.20
让我们编辑Script Task 1与Script Task 3之间的优先约束。右击优先约束打开优先约束编辑器,修改求值运算为"表达式",在表达式文本框键入"!@MyBool"(不需要双引号):

图8.21
"!@MyBool"表达式可以理解为"Not MyBool"——如果SSIS变量User::MyBool的值是False那么!@MyBool就是True.点击确定按钮关闭优先约束编辑器。你的控制流应该如下图所示:

图8.22
不知道你那边如何,但是我这边看起来有点凌乱。函数图标在一起了。我们可以适当调整优先约束的位置,让整体看起来明朗些:

图8.23
在BIDS调试器下执行包。如果Script Task 1的提示选择"是",Script Task 2将会执行:

图8.24
如果Script Task 1的提示选择"否",Script Task 3将会执行:

图8.25
优先约束提供巨大的视觉反馈。比如,蓝色表示一个求值运算设置为完成。但是我们的求值运算完全忽略了约束。让我们思考一下,约束的求值有:成功、失败和完成。成功意味着之前的任务成功;失败意味着之前的任务失败。成功和失败都表明完成。完成表明之前的任务已经操作但不管它是成功还是失败的。完成忽略之前任务执行的结果,不管它是成功还是失败。
当我将求值运算设置为表达式时同样会忽略之前任务执行折结果。我只关心任务是否完成。
复制禁用保存已有的任务
在我们继续前行之前,让我们先保存已经操作过的工作。从工具箱拖一个序列窗口到控制流:

图8.26
如果你在控制流的空白处点击一下,然后画/拖出一个方框覆盖三个脚本任务,你就可以把它们当做一个组来拖动它们到序列容器:

图8.27 将脚本任务拖放到序列容器
当你这样操作的时候,大多数情况下序列容器会自动调整大小以包括拖入里面的组件。如果它没有自动调整,手动调整以免引起误解。
右击序列容器点击复制。右击控制流的空白处点击粘贴。你的控制流应该如下所示:

图8.28 复制并粘贴序列容器
现在右击序列容器(原始那个)点击禁用。序列容器和它里面的组件都会被禁用(显示为灰色):

图8.29 禁用序列容器
现在我们就可以继续做新工作的时候保存已经完成的工作了。
多重约束
在序列容器1中删除Script Task 1.这也会删除Script Task 1与Script Task 2之间的约束。复制Script Task 2然后粘贴到序列容器1,并重命名为Script Task 4.移动Script Task 2让它和Script Task 4并排,然后连接Script Task 2和Script Task 3之间的优先约束;在Script Task 4与Script Task 3之间创建一个新的约束。

图8.30 创建Script Task 4并连接约束
现在,让我问你,为了让Script Task 3执行需要有什么操作?
1、Nothing.当其他任务执行后Script Task 3就会执行
2、当Script Task 4或Script Task 2执行并成功后Script Task 3就会执行
3、当Script Task 4与Script Task 2执行并成功后Script Task 3就会执行
4、Script Task 3永远不会执行
答案可以从优先约束编辑器的多重约束找到:

图8.31 多重约束"逻辑与"
记住,多重约束定义优先约束在终点如何操作。当终点任务只有一个优先约束限制时,这些选项是没有实际意义的。但是当有两个及以上约束在终点任务,这个选项就很重要。
默认是选择"逻辑与",这意味着在终点任务的所有约束必须都通过求值运算,才能执行后面的任务。本例中,Script Task 4与Script Task 2必须执行并成功后Script Task 3才会执行。让我们在BIDS调试器下执行包以验证前面的推测:

图8.32
直到Script Task 4与Script Task 2执行并成功后,Script Task 3才会开始执行(与上面的第3种情况相符)。这就是多重约束的"逻辑与"操作。接下来让我们测试"逻辑或"。停止调试,双击打开打开优先约束编辑器。更改多重约束为"逻辑或",如下图所示:

图8.33 多重约束"逻辑或"
点击确定按钮关闭优先约束编辑器。你可能注意到连接到Script Task 3的优先级约束的外观上的变化。优先约束现在都用虚线表示,如图8.34所示:

图8.34
因为多重约束配置处理终点任务,修改其中一个会影响到所有连接到终点任务的约束。
之前,在我们配置多重约束为"逻辑与"时,所有的优先约束需要先求值,之后的任务才会执行。我们现在配置为"逻辑或",让我们测试下,为了让Script Task 3执行需要有什么操作?在BIDS调试器下执行包,此时你的控制流应该类似于图8.35:

图8.35
只要Script Task 4或Script Task 2执行成功,Script Task 3就会开始执行。
混合约束和表达式运算
停止调试,双击打开Script Task 4和Script Task 3之间的优先约束编辑器。更改多重约束选项为"逻辑与"。设置求值运算为"表达式和约束",确保值设置为成功,表达式设置为@MyBool:

图8.36
为了这个约束求值,之前的任务必须执行且成功,并且SSIS变量User::MyBool必须为True.让我们查看变量,如图8.37,MyBool的值设置为Flase

图8.37
这个约束的值会为True吗?不会。因为约束(成功)的值必须为True而且表达式(MyBool)的值也必须为True.但是MyBool是Flase.因此不管Script Task 4成功或失败,MyBool是Flase会阻止约束进行求值。
测试一下。在BIDS调试器下执行包并观察结果。你永远不会看到包执行到Script Task 3:

图8.38
停止调试。让我们再次打开Script Task 4和Script Task 3之间的优先约束编辑器。修改求值运算为"表达式或约束":

图8.39
关闭优先约束编辑器,然后执行包。这一次,Script Task 3将会执行:

图8.40
因为连接到Script Task 3的优先约束的值都为True.很容易理解Script Task 2和Script Task 3之间的约束的值。但是Script Task 4和Script Task 3之间的约束是如何求值的呢?求值运算设置为"表达式或约束"意味着只要表达式或约束的值为True即可。如果两者都为True,约束还是为True.但是或条件要求至少有一个(表达式或约束)值为True.这里表达式MyBool是Flase;约束的值是True(之前的任务成功执行)。这就是为什么Script Task 3会执行。
优先约束注释
你可能已经注意一件事:当我们在求值运算中做最后一次更改时(从"表达式和约束"改为"表达式或约束"),控制流中的图标没有任何可视化的改变。有一种方法:点击选择优先约束,然后按F4打开属性窗口。把第一个属性ShowAnnotation的值设置为"ConstraintOptions":

图8.41
ShowAnnotation属性的ConstraintOptions会显示求值运算的说明:

图8.42
强化深入
首先,让我们编辑Script Task 2和Script Task 4中的Public Sub Main()如下所示:

    Public Sub Main()
Dim sTaskName As String = Dts.Variables("TaskName").Value.ToString
Dim iResponse As Integer
iResponse = MsgBox("Succeed " & sTaskName & "?", _
MsgBoxStyle.YesNo + MsgBoxStyle.Question, _
sTaskName & " Success Question")
If iResponse = vbYes Then
Dts.TaskResult = ScriptResults.Success
Else
Dts.TaskResult = ScriptResults.Failure
End If End Sub

代码8.2
代码为每一个脚本任务创建提示任务是否成功。编辑Script Task 4和Script Task 3之间的优先约束,设置求值运算为"表达式和约束",值设置为失败,表达式设置为@MyBool

图8.43
编辑Script Task 2和Script Task 3之间的优先约束,设置求值运算为"表达式",表达式设置为!@MyBool

图8.44
如果两个优先约束的ShowAnnotation属性都设置为ConstraintOptions,你的控制流看起来应该如图8.45所示:

图8.45
注意,将求值运算设置为表达式会引起ConstraintOptions显示为"完成和表达式"。正如文章的前面提到,这是符合逻辑操作的。
执行包,条件选择Script Task 4为失败(否),Script Task 2为成功(是):

图8.46
This is a trick question.Script Task 3永远不会执行。因为优先约束的多重约束设置为"逻辑与"。所有约束的值都必须为True才会允许Script Task 3执行。但是它们含有对SSIS变量MyBool的互斥条件:一个约束当MyBool为True时为真,另一个约束当MyBool为Flase时为真。MyBool不可能同时为True和Flase.如果存在互斥条件,你必须将相应的多重约束设置为"逻辑或"。
让我们编辑Script Task 2和Script Task 3之间的优先约束,修改表达式为@MyBool:

图8.47
修改SSIS变量MyBool的值为True:

图8.48
如果我在BIDS调试器执行包,条件选择Script Task 4为失败,Script Task 2为成功/失败;Script Task 3就会执行:

图8.49
一旦我们移除互斥条件,设置为逻辑与的多重约束就会为真,然后执行下面的任务。
Another "Gotcha"
之前我们禁用了序列容器。现在让我们禁用Script Task 4:

图8.50
当我们在BIDS调试器下执行包,Script Task 4不会执行,但是Script Task 3也不会执行:

图8.51
为什么?MyBool的值为True而且Script Task 2完成。Script Task 4直接跳过去了。当Script Task 4禁用后,控制流断言它是成功的。这就意味着失败优先约束不会进行求值。
总结
这一篇,我们使用SSIS变量控制优先约束的求值,检查多重约束,and took a look at a couple “gotchas” to avoid when configuring precedence constraints to control workflow in an SSIS package.

【译】第八篇 Integration Services:高级工作流管理的更多相关文章

  1. 第八篇 Integration Services:高级工作流管理

    本篇文章是Integration Services系列的第八篇,详细内容请参考原文. 简介在前面两篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcu ...

  2. 【译】第九篇 Integration Services:控制流任务错误

    本篇文章是Integration Services系列的第九篇,详细内容请参考原文. 简介在前面三篇文章,我们创建了一个新的SSIS包,学习了脚本任务和优先约束,并检查包的MaxConcurrentE ...

  3. 【译】第二篇 Integration Services:SSIS数据泵

    本篇文章是Integration Services系列的第二篇,详细内容请参考原文. 简介SSIS用于移动数据.数据流任务提供此功能.因为这个原因,当介绍SSIS时我喜欢从数据流任务开始.数据流任务的 ...

  4. 【译】第一篇 Integration Services:SSIS是什么

    本篇文章是Integration Services系列的第一篇,详细内容请参考原文. Integration Services是一种在SQL Server中最受欢迎的子系统.允许你在各种数据源之间提取 ...

  5. 【译】第七篇 Integration Services:中级工作流管理

    本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...

  6. 【译】第十二篇 Integration Services:高级日志记录

    本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...

  7. 【译】第十篇 Integration Services:高级事件行为

    本篇文章是Integration Services系列的第十篇,详细内容请参考原文. 简介在前一篇, we introduced fault tolerance by examining method ...

  8. 【译】第六篇 Integration Services:初级工作流管理

    本篇文章是Integration Services系列的第六篇,详细内容请参考原文. 简介在前几篇文章中,我们关注使用增量加载方式加载数据.在本篇文章,我们将关注使用优先约束管理SSIS控制流中的工作 ...

  9. 第七篇 Integration Services:中级工作流管理

    本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...

随机推荐

  1. [转帖]通俗解释 AWS 云服务每个组件的作用

    你有听说过 ContainerCache,ElastiCast 和 QR72 这些 AWS 的新服务吗? 没有就对了,这些都是我编的:) 不过,AWS 有 50 多个服务,从名称也不能看出这些服务是做 ...

  2. 在MFC中显示图片(opencv Mat类型)

    1,在MFC窗体中添加picture control控件,并添加对应的变量名 2,在窗体的初始化窗口中添加: namedWindow(); HWND hWnd = (HWND)cvGetWindowH ...

  3. 每日一问(如何在List中加入、设置、获取和删除其中的元素?)

    作为集合接口的一部分,对List接口所做的操作,最常见的就是增删查改了.这里总结下JAVA 中List接口及实现该接口的类实现这些操作的方法. 一.增加新的元素的方法 在Collection接口中定义 ...

  4. python参数传递方式

    原文地址:http://www.cnblogs.com/zhaopengcheng/p/5492183.html python中一切皆对象,函数中参数传递的是对象的引用. 1在函数中改变变量指向的对象 ...

  5. 学习Spring Boot:(五)使用 devtools热部署

    前言 spring-boot-devtools 是一个为开发者服务的一个模块,其中最重要的功能就是自动应用代码更改到最新的App上面去.原理是在发现代码有更改之后,重新启动应用,但是比速度比手动停止后 ...

  6. 【Cf #503 C】Sergey's problem(有趣的构造)

    感觉这种构造题好妙啊,可我就是想不到诶. 给出一张无自环的有向图,回答一个独立集,使得图中任意一点都可以被独立集中的某一点两步之内走到. 具体构造方案如下: 下标从小到大枚举点,如果该点没有任何标记, ...

  7. 洛谷 P2431 正妹吃月饼 解题报告

    P2431 正妹吃月饼 题目描述 今天是中秋节.\(uim\)带来了一堆大小不同且味道各异的月饼. 这些月饼的质量分别是\(1g\),\(2g\),\(4g\),\(8g\),\(16g\)....后 ...

  8. 使用LD_Preload的Linux权限升级技巧

      0x00 前言 共享库是程序在启动时加载的库.正确安装共享库后,之后启动的所有程序将自动使用新的共享库. 0x01 共享库名称 每个共享库都有一个名为soname的特殊名称.soname有前缀li ...

  9. 单点登录(七)-----实战-----cas server去掉https验证

    我们在搭建cas中已经说过如果不搭建https证书体系的需要去掉https的验证: 单点登录(二)----实战------简单搭建CAS---测试认证方式搭建CAS 因为cas4.2以上的代码做了一些 ...

  10. 解题:洛谷2093 JZPFAR

    题面 初见K-D Tree 其实这样的题(欧几里得距离第$x$近点对)不应该用K-D Tree做,因为会被构造数据卡成$O(n^2)$,随机的另说. 但是并没有找到合适的K-D Tree的题(区域统计 ...