开篇介绍

Execute SQL Task 这个控件在微软BI ETL 项目中使用的频率还是非常高的,也是大部分入门 SSIS 初学者最早接触到的几个控制流控件。
我们通常使用 Execute SQL Task 的场景包含但不止于以下几类:
  1. 在从源端加载数据到 Staging 表之前使用 Execute SQL Task 执行一些 Truncate 操作。
  2. 执行一些 Log 的插入,更新操作。
  3. ETL 过程中的 Merge 语句操作。
  4. XML 的输出处理。
关于如何使用 Execute SQL Task 就不在本文讲解了,包括参数传递 Input,存储过程返回值 Output,包括 Return Value ,还有 SQL Source Type 等不同方式以及 OLD DB,ADO.NET 区别等基础概念文本也不会涉及到。
 
本文要讲解的内容是针对 ResultSet 的几种类型:None, Single row, Full result set, XML。其中 None 不用讲解,关于 XML 的内容大家可以参考我的另一篇文章 两种将 SQL Server 数据库数据输出成 XML 文件的方法,因此在这里只讲解 Single Row 和 Full Result Set 的处理方法。

Single Row

首先,Single Row 指的就是在 Execute SQL Task 中返回的就是一个单行的记录,允许多列。
通常在 Execute SQL Task 中使用 Single Row 的时候是为了在控制流中控制流程的流转,满足一定的条件走一个分支流程,不满足则走另外一个流程。
比如,在包执行之初查询数据库检查一下包的某些状态,或者数据的某些状态,只有在满足达到一定条件下才能执行剩下的流程,否则则不执行包或者报错。这类设计在各种不同的BI项目中可能都存在,那么其原型就是利用 Execute SQL Task 中的 Single Row返回的值来控制流程。
有以下几个步骤:
  1. SQL Statement 中的语句返回单行记录,可以多列。
  2. 需要在包中实现定义变量用来接收 Single Row 的某列上的值。
  3. 使用 Precedence Constraint 和变量来控制流程。

Single Row 案例

一条简单的查询语句返回一个单行双列的记录。
设置好连接并放好SQL语句,选择 Single Row。
添加三个变量
  1. EXISTING_COUNT - 用来接收查询中的返回的COUNT数。
  2. MAX_DATE - 用来接收查询中返回的最大时间。
  3. TEST_DATE - 测试时间,比如说 2014-01-01。

0 表示 Single Row 中的第一列,1 表示 Single Row 中的第二列。
下面放两个空的 Data Flow Task 并关联到 Execute SQL Task,点击连接线设置条件控制。
DFT_TEST_AFTER_MAX 上的连接线条件判断为:DATEDIFF( "dd", (DT_DBDATE) (@[User::TEST_DATE]) , (DT_DBDATE) (@[User::MAX_DATE])) >=0
DFT_TEST_BEFORE_MAX上的判断表达式为:DATEDIFF( "dd", (DT_DBDATE) (@[User::TEST_DATE]) , (DT_DBDATE) (@[User::MAX_DATE])) <0
左右两个数据流下各加入一个 Script Task 显示一下这几个变量的值,代码如下:
public void Main()
{
// TODO: Add your code here
//User::EXISTING_COUNT,User::MAX_DATE,User::TEST_DATE
string existing_count = Dts.Variables["User::EXISTING_COUNT"].Value.ToString();
string max_date = Dts.Variables["User::MAX_DATE"].Value.ToString();
string test_date = Dts.Variables["User::TEST_DATE"].Value.ToString(); MessageBox.Show("Existing Count - " + existing_count + ", test date - " + test_date + ", max date - " + max_date);
Dts.TaskResult = (int)ScriptResults.Success;
}

保存并执行包,流程走了右边,因为 MAX DATE 要比 TEST DATE 大。

修改 TEST_DATE,那么 TEST DATE 要比 MAX DATE 大。
这就是 Execute SQL Task 中 Single Row 的使用方法。

FULL Result Set

通常在 Execute SQL Task 中使用到 FULL Result Set 就一定会结合 Foreach Loop 来使用,所适用的场景是循环便利查询结果集中的每一行数据,将每一行的数据其中某几列取出来放入到变量中,然后同样在 Foreach Loop 中的其它控制流控件使用这些变量做一些操作。

疑问

像这种遍历为什么不放到数据库中直接遍历不是更好吗?问题就在于,有时操作的对象并不仅仅是数据库中的表对象,而是涉及到不同的文件处理,这时就需要使用这种方式了。比如,我的目标数据源中有几百个文件,且文件的命名包括产品的名称,现在表中有产品名称的记录。需要循环遍历表中的产品,并对比哪些文件命名包含有这些产品名称,包含产品名称的文件则抽取数据,不包含产品名称的文件则移到其它目录。
下面使用这个查询作为一个示例结果集 -
 
使用 FULL RESULT SET  
定义如下几个变量 - ORDER_SET 用来保存 Execute SQL Task 查询中的结果集,其它变量用来在循环每一行的时候保存每一列的值。注意:返回的结果集要使用 OBJECT 类型的变量来保存,这个 OBJECT 类型在内部以集合的形式存在并保存整个查询结果集。
EXECUTE SQL TASK 的 Mapping。

Foreach 下的设置

我们可以通过 Foreach 的方式循环遍历这个返回的集合。添加一个 Foreach 控件,并设置遍历方式 - Foreach ADO Enumerator 和要遍历的集合对象。
遍历这个集合的时候,每次返回一行,这一行也是一个集合,通过设置索引0,1,2 将这个集合的元素赋值给各个变量。
在 Foreach 控件中添加一个 Script Task 用来显示每一行中各列的内容。
Script 中的脚本代码如下:
public void Main()
{
// TODO: Add your code here
//User::PRODUCT_ID,User::SALES_ORDER_DETAIL_ID,User::UNIT_PRICE
string detailID = Dts.Variables["User::SALES_ORDER_DETAIL_ID"].Value.ToString();
string productID = Dts.Variables["User::PRODUCT_ID"].Value.ToString();
string unitPrice = Dts.Variables["User::UNIT_PRICE"].Value.ToString(); MessageBox.Show("Detail ID - " + detailID+", Product ID - "+productID +", Unite Price - "+ unitPrice);
Dts.TaskResult = (int)ScriptResults.Success;
}

保存并执行包,第一次循环的结果是失败的,但是可以看出来我们的结果集返回是没有问题的。

出错的原因如下:
Error: The type of the value (String) being assigned to variable "User::SALES_ORDER_DETAIL_ID" differs from the current variable type (Int32). Variables may not change type during execution. Variable types are strict, except for variables of type Object.
Error: The type of the value (String) being assigned to variable "User::PRODUCT_ID" differs from the current variable type (Int32). Variables may not change type during execution. Variable types are strict, except for variables of type Object.
Error: The type of the value (String) being assigned to variable "User::UNIT_PRICE" differs from the current variable type (Decimal). Variables may not change type during execution. Variable types are strict, except for variables of type Object.
这是由于在集合中的数据默认都是 String 类型的,是不能够直接转换成我们定义的变量所指定的类型,因此需要修改我们的变量类型。
再次执行就可以看到遍历的效果,第一次 -

最后一次 -

Script Task 中的循环遍历

同样的 Object 对象,不仅仅可以在 Foreach 中循环遍历,也可以直接在 Script Task 中循环遍历。
添加一个 Script Task,把结果集对象放入变量列表中。
脚本代码如下 - 
using System.Data.OleDb;

public void Main()
{
// TODO: Add your code here
OleDbDataAdapter adapter = new OleDbDataAdapter();
DataTable dataTable = new DataTable(); adapter.Fill(dataTable, Dts.Variables["User::ORDER_SET"].Value); foreach (DataRow row in dataTable.Rows)
{
MessageBox.Show(row[] + "," + row[] + "," + row[]);
} Dts.TaskResult = (int)ScriptResults.Success;
}

一样可以实现遍历的效果 -

最后一条记录-

总结

通过讲解 Execute SQL Task 的两种查询结果返回方式 Single Row 和 Full Result Set,实际上由此引申出了何时使用 Single Row 以及 Full Result Set 的场景。熟悉和掌握这些场景可以帮助我们在复杂的 ETL 项目中找出各种不同的解决方案,可以非常灵活的解决一些实际问题。
再次,特别通过 Foreach Loop Container 以及 Script Task 学习到了两种解析 Full Result Set 的方式,其中涉及到的知识点以及细节还是比较多的,特意总结下来希望可以帮助到大家。

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。

微软BI 之SSIS 系列 - Execute SQL Task 中的 Single Row 与 Full Result Set 的处理技巧的更多相关文章

  1. 微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件

    原文:微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件 开篇介绍 大多数情况下我们的 SSIS 包都会配置在 SQL Agent ...

  2. 微软BI 之SSIS 系列 - 使用 SQL Profilling Task (数据探测) 检测数据源数据

    开篇介绍 SQL Profilling Task 可能我们很多人都没有在 SSIS 中真正使用过,所以对于这个控件的用法可能也不太了解.那我们换一个讲法,假设我们有这样的一个需求 - 需要对数据库表中 ...

  3. 微软BI 之SSIS 系列 - 使用 Multicast Task 将数据同时写入多个目标表,以及写入Audit 与增量处理信息

    开篇介绍 在 SSIS Data Flow 中有一个 Multicast 组件,它的作用和 Merge, Merge Join 或者 Union All 等合并数据流组件对比起来作用正好相反.非常直观 ...

  4. 微软BI 之SSIS 系列 - 在 SQL 和 SSIS 中实现行转列的 PIVOT 透视操作

    开篇介绍 记得笔者在 2006年左右刚开始学习 SQL Server 2000 的时候,遇到一个面试题就是行转列,列转行的操作,当时写了很长时间的 SQL 语句最终还是以失败而告终.后来即使能写出来, ...

  5. 微软BI 之SSIS 系列 - MVP 们也不解的 Scrip Task 脚本任务中的一个 Bug

    开篇介绍 前些天自己在整理 SSIS 2012 资料的时候发现了一个功能设计上的疑似Bug,在 Script Task 中是可以给只读列表中的变量赋值.我记得以前在 2008 的版本中为了弄明白这个配 ...

  6. 微软BI 之SSIS 系列 - 在 SSIS 中导入 ACCESS 数据库中的数据

    开篇介绍 来自 天善学院 一个学员的问题,如何在 SSIS 中导入 ACCESS 数据表中的数据. 在 SSIS 中导入 ACCESS 数据库数据 ACCESS 实际上是一个轻量级的桌面数据库,直接使 ...

  7. 微软BI 之SSIS 系列 - 使用 Script Component Destination 和 ADO.NET 解析不规则文件并插入数据

    开篇介绍 这一篇文章是 微软BI 之SSIS 系列 - 带有 Header 和 Trailer 的不规则的平面文件输出处理技巧 的续篇,在上篇文章中介绍到了对于这种不规则文件输出的处理方式.比如下图中 ...

  8. 微软BI 之SSIS 系列 - 数据仓库中实现 Slowly Changing Dimension 缓慢渐变维度的三种方式

    开篇介绍 关于 Slowly Changing Dimension 缓慢渐变维度的理论概念请参看 数据仓库系列 - 缓慢渐变维度 (Slowly Changing Dimension) 常见的三种类型 ...

  9. 微软BI 之SSIS 系列 - Lookup 中的字符串比较大小写处理 Case Sensitive or Insensitive

    开篇介绍 前几天碰到这样的一个问题,在 Lookup 中如何设置大小写不敏感比较,即如何在 Lookup 中的字符串比较时不区分大小写? 实际上就这个问题已经有很多人提给微软了,但是得到的结果就是 C ...

随机推荐

  1. cf 1041C双指针

    比赛的时候想着用单调队列做... 打完发现其实就是个双指针 /* 构造双指针解决即可 */ #include<iostream> #include<cstring> #incl ...

  2. python 全栈开发,Day113(方法和函数的区别,yield,反射)

    一.方法和函数的区别 面向对象 初级 class StarkConfig(object): def __init__(self,model_class): self.model_class = mod ...

  3. Pycharm里面使用PIL库之后,为什么调用Image的方法不能弹出代码提示,怎样能让代码提示弹出?

    之前也碰到了这个问题,安装了pillow后没有代码提示,最后查了半天,发现问题原来非常简单,解决方法也很无厘头. 之所以没有代码提示,仅仅是因为Pycharm没法判断Image.open()返回的对象 ...

  4. linux命令之grep用法

    grep是linux中很常用的一个命令,主要功能就是进行字符串数据的对比,能使用正则表达式搜索文本,并将符合用户需求的字符串打印出来.grep全称是Global Regular Expression ...

  5. Star HDU1541

    看到图和坐标就想到了用二维数组来写   但是连数组的开不下   写好了也爆内存 没看到题目是按照y坐标升序给的坐标 这样就可以忽略y坐标 进行一维的树状数组 #include<bits/stdc ...

  6. 063 日志分析(pv  uv  登录人数  游客人数  平均访问时间  二跳率  独立IP)

    1.需求分析 分析指标 pv uv 登录人数 游客人数 平均访问时间 二跳率 独立IP 2.使用的日志(一号店),会话信息 3.创建数据库 4.创建源表,存储源数据 5.创建我们需要的use表 6.创 ...

  7. C++语言实现-邻接矩阵

    一. 图的概念 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合.在图中的数据元素,我们称之为顶点( ...

  8. Linux学习之用户管理命令与用户组管理命令(十五)

    Linux学习之用户管理命令与用户组管理命令 目录 用户管理命令 用户添加命令useradd 修改用户密码passwd 修改用户信息usermod 修改用户密码状态chage 删除用户userdel ...

  9. linux中top命令使用及查看tcp连接

    Linux top命令 介绍:top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,Linux top命令用于实时显示 process 的动态,即可以通过用户按键来不断 ...

  10. LoRaWAN 1.1 网络协议规范 - 4 MAC 帧格式 Part II

    LoRaWAN 1.1 网络协议规范 LoRaWAN 1.1 版本封稿很久了也没有完整啃过一遍,最近边啃边翻译,趁着这个机会把它码下来. 如果觉得哪里有问题,欢迎留言斧正. 翻译不易,转载请申明出处和 ...