如何使用SSIS包自动执行存储过程?

时间:2012-10-30 16:21:14

标签: sql-server tsql stored-procedures ssis

我有一个使用执行SQL任务通过SQL SSIS执行的存储过程。

该任务具有以下内容:

USE [OPPY_DWUSD]
GO
DECLARE @return_value int
EXEC    @return_value = [dbo].[generate_merge_scdbk]
    @Schema = N'dim',
    @Dimension = N'VARIETY',
    @ETLSchema = N'stg',
    @ETLTable = N'vw_VARIETY',
    @Execute = 1

SELECT  'Return Value' = @return_value
GO

现在,我有这个设置的方式,我有多个具有相同代码但不同值的执行SQL任务,大约20个执行SQL任务。

是否有更清洁的方法来解决这个问题?

2 个答案:

答案 0 :(得分:7)

这是一种做到这一点的方法。该示例使用带有SQL Server 2012后端的SSIS 2008 R2。

创建一个表来存储参数值。假设表名是 dbo.SProcValues 。根据您的存储过程定义,表模式将如下所示。

CREATE TABLE dbo.SProcValues(
    Id int IDENTITY(1,1) NOT NULL,
    SProcName nvarchar(40) NOT NULL,
    SchemaName nvarchar(20) NOT NULL,
    Dimension nvarchar(40) NOT NULL,
    ETLSchema nvarchar(20) NOT NULL,
    ETLTable nvarchar(40) NOT NULL,
    IsExecute bit NOT NULL
) 
GO

让我们使用以下脚本插入一些示例数据。

INSERT INTO dbo.SProcValues 
    (SProcName, SchemaName, Dimension, ETLSchema, ETLTable, IsExecute) VALUES
    ('dbo.sp_generate_merge', 'dim1', 'dimension1', 'stg1', 'table1', 1),
    ('dbo.sp_generate_merge_scdbk', 'dim2', 'dimension2', 'stg2', 'table2', 1),
    ('dbo.sp_generate_merge_scdbk', 'dim3', 'dimension3', 'stg3', 'table3', 0),
    ('dbo.sp_generate_merge', 'dim4', 'dimension4', 'stg4', 'table4', 0);
GO

在SSIS包上,假设您已经建立了数据源和连接管理器。创建以下变量。变量 SProcValues 将保存我们存储在上述表中的参数集。变量 SQLInnerQuery 将保存稍后将在内部执行SQL任务中使用的查询。其他变量与表中可用的每个列相关,因此我们可以遍历每一行并将其保存在变量中。

将以下查询粘贴到变量 SQLGetParameters

的值中

SELECT SProcName, SchemaName, Dimension, ETLSchema, ETLTable, IsExecute FROM dbo.SProcValues

Variables

选择变量 SQLInnerQuery ,然后按F4查看属性。将属性 EvaluateAsExpression 设置为 True ,然后针对 Expression 属性单击省略号按钮。

SQLInnerQuery

我们需要设置一个表达式,该表达式将评估EXEC存储过程语句,该语句稍后可以提供给内部的Execute SQL Task。设置以下表达式。

"EXEC " + @[User::SProcName] + " @Schema = ?, @Dimension = ?, @ETLSchema = ?, @ETLTable = ?, @IsExecute = ?"

如果单击编辑器上的“评估表达式”按钮,则可以查看表达式将评估的内容。您还会注意到下面的屏幕截图中没有存储过程名称,因为包变量SProcName当前没有任何值。在运行时,将为SProcName分配表中的值,该表达式将自动解析。 Expression

在SSIS包上,拖放执行SQL任务。此任务将运行以下查询以获取存储在表dbo.SProcValues中的参数值列表。在Execute SQL Task上配置General页面,如下所示。该示例使用OLEDB连接,连接管理器/数据源名为Practice。

First Execute SQL Task - General

配置“执行SQL任务”的“结果集”页面,将查询中的结果集存储到对象变量中。

First Execute SQL Task - Result Set

现在,第一个执行SQL任务被配置为获取应传递给存储过程的参数值列表,您需要遍历记录。

拖放Foreach循环容器。将Execute SQL Task的优先级容器连接到Foreach循环容器。配置Foreach循环容器的Collection页面,如下所示。我们使用ADO枚举器循环遍历结果集。

Foreach loop - Collection

在Foreach循环容器上配置“变量映射”页面,如下所示。当我们遍历每一行时,我们将列值存储在各自的变量中,以便我们可以将它传递给下一个执行SQL任务来运行存储过程。

Foreach loop - Variable Mappings

在Foreach循环容器中拖放一个执行SQL任务,以便每次循环结果集中的一行时执行此任务。配置执行SQL任务,如下所示。

注意

您可能希望根据您的要求在此第二个执行SQL任务上配置 ResultSet 属性。如果选择ResultSet,则需要配置适当的对象变量以接受结果集。我把它留作 None 这个例子。

Second Execute SQL Task - General

配置要作为参数传递给存储过程的值。

Second Execute SQL Task -  Parameter Mapping

最后,控制流看起来像这样。

Control Flow

当程序包运行时,循环将执行存储过程,因为上面提到的SELECT查询返回了许多记录,前提是您已在表中定义的所有存储过程在数据库中可用。我创建了具有相同参数定义的存储过程dbo.sp_generate_merge_scdbkdbo.sp_generate_merge。这就是包成功执行的原因。

Execution

答案 1 :(得分:3)

你有正确的概念,只需要在执行SQL任务中使用一些概念,如变量,foreach循环和参数。

控制流程

您的控制流程看起来像这样

control flow

变量

我在SSIS中定义了6个变量

  • 尺寸|字符串|品种
  • ETLSchema |字符串| STG
  • ETLTable |字符串| vw_VARIETY
  • 执行| Int32 | 1
  • RecordSet |对象| System.Object的
  • 架构|字符串|暗淡

第一个执行SQL任务将是一个查询或类似的可枚举的东西。目前,有一个硬编码查询来生成提供的查询值。您的解决方案可能只是SELECT的UNIONed链。此步骤的目标是填充RecordSet变量。

我的执行SQL任务返回完整的结果集 Execute SQL

然后我将其推入我的对象

Result set tab

ForEach循环容器(ADO Recordset)

ForEach循环容器将消耗我们事先建立的可枚举的东西。它将遍历每一行,我们将从对象中弹出值并将它们分配给局部变量。

将枚举器更改为Foreach ADO Enumerator。选择我们使用结果User::RecordSet填充的对象,然后使用枚举模式Rows in first table

FELC

在Variable Mappings选项卡中,我们将识别值的基于序数的位置(第0列映射到变量X)。这里唯一的技巧是确保您的SSIS Variable数据类型与源查询的结果集中的数据类型匹配。请注意它是基于零的序数系统。

FELC Variable Mappings

此时,如果单击“运行”,则会看到它枚举您已发送到RecordSet变量的所有行。我发现此时运行它有助于确保我的所有数据类型都已对齐。

内部执行SQL任务

我已经接受了您的查询并用占位符替换了硬编码值。 OLEDB连接将使用?,而ADO.NET将使用名为@varname

Execute SQL General

在“参数映射”选项卡中,只需将这些局部变量映射到占位符。

Execute SQL Parameter Mapping

现在你有一个很好的模板来运行具有不同值的相同proc。