如何在 SSIS 控制流任务中创建一个临时表,然后在数据流任务中使用它?

Posted

技术标签:

【中文标题】如何在 SSIS 控制流任务中创建一个临时表,然后在数据流任务中使用它?【英文标题】:How to create a temporary table in SSIS control flow task and then use it in data flow task? 【发布时间】:2011-08-03 14:42:39 【问题描述】:

我有一个控制流,我使用 T-SQL 命令在其中创建一个临时数据库和表。当我添加一个数据流时,我想查询该表,但我不能,因为该表不存在以从中获取信息。当我尝试登录时出现错误,因为数据库不存在(尚)。我有延迟验证为真。

如果我手动创建数据库和表,然后使用查询添加数据流并删除它粘贴的数据库,但它似乎不是一个干净的解决方案。

如果有更好的方法来创建临时暂存数据库并在数据流中查询它,请告诉我。

【问题讨论】:

我可能会改用一个变量,毕竟 SSIS 旨在在内存中工作。 【参考方案1】:

解决方案:

Connection Manager上的RetainSameConnection属性设置为True,这样在一个控制流任务中创建的临时表就可以保留在另一个任务中。

这是一个用 SSIS 2008 R2 编写的示例 SSIS 包,用于说明如何使用临时表。

演练:

创建一个存储过程,该过程将创建一个名为##tmpStateProvince 的临时表并填充少量记录。示例 SSIS 包将首先调用存储过程,然后获取临时表数据以将记录填充到另一个数据库表中。示例包将使用名为 Sora 的数据库,使用下面的创建存储过程脚本。

USE Sora;
GO

CREATE PROCEDURE dbo.PopulateTempTable
AS
BEGIN
    
    SET NOCOUNT ON;

    IF OBJECT_ID('TempDB..##tmpStateProvince') IS NOT NULL
        DROP TABLE ##tmpStateProvince;

    CREATE TABLE ##tmpStateProvince
    (
            CountryCode     nvarchar(3)         NOT NULL
        ,   StateCode       nvarchar(3)         NOT NULL
        ,   Name            nvarchar(30)        NOT NULL
    );

    INSERT INTO ##tmpStateProvince 
        (CountryCode, StateCode, Name)
    VALUES
        ('CA', 'AB', 'Alberta'),
        ('US', 'CA', 'California'),
        ('DE', 'HH', 'Hamburg'),
        ('FR', '86', 'Vienne'),
        ('AU', 'SA', 'South Australia'),
        ('VI', 'VI', 'Virgin Islands');
END
GO

创建一个名为 dbo.StateProvince 的表,该表将用作目标表以填充临时表中的记录。使用下面的创建表脚本来创建目标表。

USE Sora;
GO

CREATE TABLE dbo.StateProvince
(
        StateProvinceID int IDENTITY(1,1)   NOT NULL
    ,   CountryCode     nvarchar(3)         NOT NULL
    ,   StateCode       nvarchar(3)         NOT NULL
    ,   Name            nvarchar(30)        NOT NULL
    CONSTRAINT [PK_StateProvinceID] PRIMARY KEY CLUSTERED
        ([StateProvinceID] ASC)
) ON [PRIMARY];
GO

使用 Business Intelligence Development Studio (BIDS) 创建一个 SSIS 包。右键单击包底部的 Connection Managers 选项卡,然后单击 New OLE DB Connection... 以创建新连接以访问 SQL Server 2008 R2 数据库。

配置 OLE DB 连接管理器上单击 New...

连接管理器对话框中执行以下操作。

Provider 中选择 Native OLE DB\SQL Server Native Client 10.0,因为包将连接到 SQL Server 2008 R2 数据库 输入服务器名称,如MACHINENAME\INSTANCE登录到服务器部分或任何您喜欢的部分中选择Use Windows Authentication。 从Select or enter a database name中选择数据库,示例使用数据库名称Sora。 点击Test Connection测试连接成功消息上单击OK。 在连接管理器上单击OK

新创建的数据连接将出现在配置 OLE DB 连接管理器上。点击OK

OLE DB 连接管理器KIWI\SQLSERVER2008R2.Sora 将出现在包底部的连接管理器 选项卡下。右键单击连接管理器,然后单击 Properties

将连接 KIWI\SQLSERVER2008R2.Sora 上的属性 RetainSameConnection 设置为值 True

右键单击包内的任意位置,然后单击 Variables 以查看变量窗格。创建以下变量。

一个名为 PopulateTempTable 的新变量,其数据类型为 String,位于包范围 SO_5631010 中,并使用值 EXEC dbo.PopulateTempTable

一个名为 FetchTempData 的新变量,其数据类型为 String,位于包范围 SO_5631010 中,并使用值 SELECT CountryCode, StateCode, Name FROM ##tmpStateProvince

Execute SQL Task 拖放到 控制流 选项卡上。双击执行 SQL 任务以查看 执行 SQL 任务编辑器

执行 SQL 任务编辑器General页面上,执行以下操作。

名称设置为Create and populate temp table连接类型设置为OLE DB连接设置为KIWI\SQLSERVER2008R2.SoraSQLSourceType中选择VariableSourceVariable中选择User::PopulateTempTable 点击OK

Data Flow Task 拖放到 控制流 选项卡上。将数据流任务重命名为 Transfer temp data to database table。将 Execute SQL Task 中的绿色箭头连接到 Data Flow Task

双击Data Flow Task 切换到数据流 选项卡。将 OLE DB Source 拖放到 Data Flow 选项卡上。双击OLE DB Source,查看OLE DB Source Editor

OLE DB Source EditorConnection Manager页面上,执行以下操作。

OLE DB 连接管理器中选择KIWI\SQLSERVER2008R2.Sora数据访问模式中选择SQL command from variable变量名中选择User::FetchTempData 点击Columns页面

点击OLE DB Source Editor上的Columns页面会显示如下错误,因为在source命令中指定了表##tmpStateProvince变量不存在,SSIS 无法读取列定义。

要修复错误,请在数据库 Sora 上使用 SQL Server Management Studio (SSMS) 执行语句 EXEC dbo.PopulateTempTable,这样存储过程将创建临时表。执行完存储过程后,点击OLE DB Source Editor上的Columns页面,会看到列信息。点击OK

OLE DB Destination 拖放到 数据流 选项卡上。将绿色箭头从 OLE DB 源 连接到 OLE DB 目标。双击 OLE DB Destination 以打开 OLE DB 目标编辑器

OLE DB 目标编辑器Connection Manager页面上,执行以下操作。

OLE DB 连接管理器中选择 KIWI\SQLSERVER2008R2.Sora数据访问模式中选择Table or view - fast load 从表或视图的名称中选择[dbo].[StateProvince] 点击Mappings页面

单击OLE DB 目标编辑器 上的Mappings 页面,如果输入和输出列名相同,则会自动映射列。点击OK。列 StateProvinceID 没有匹配的输入列,它在数据库中被定义为 IDENTITY 列。因此,不需要映射。

Data Flow 选项卡在配置完所有组件后应如下所示。

单击数据流选项卡上的OLE DB Source,然后按F4查看Properties。将属性 ValidateExternalMetadata 设置为 False,以便 SSIS 在包执行的验证阶段不会尝试检查临时表是否存在。

SQL Server Management Studio (SSMS) 中执行查询 select * from dbo.StateProvince 以查找表中的行数。在执行包之前它应该是空的。

执行包。控制流显示成功执行。

在数据流选项卡中,您会注意到包成功处理了 6 行。本文前面创建的存储过程将 6 行插入到临时表中。

SQL Server Management Studio (SSMS) 中执行查询 select * from dbo.StateProvince 以找到成功插入到表中的 6 行。数据应与存储过程中找到的行匹配。

上面的例子说明了如何在包中创建和使用临时表。

【讨论】:

如果我无法控制原始查询 - 有没有办法将数据重定向到,比如说,内存缓存,用 SQL 转换它,然后将它重定向到其他地方(例如平面文件)?此时,我似乎需要创建一个临时表,每次使用时都需要截断它。 我见过的最详细准确的答案之一【参考方案2】:

我参加这个聚会迟到了,但我想为 user756519 的彻底、出色的答案添加一点内容。根据我最近的经验,我认为“连接管理器上的 RetainSameConnection”属性与此实例无关。就我而言,相关点是他们建议将“ValidateExternalMetadata”设置为 False。

我使用临时表来方便将数据从一个数据库(和服务器)复制到另一个,因此“RetainSameConnection”的原因与我的特定情况无关。我也不认为完成这个例子中发生的事情很重要,尽管它是彻底的。

【讨论】:

我刚刚对另一个答案投了赞成票,因为我错过了 Retain Same Connection 属性。我在一个单独的任务中创建了表,但是使用临时表的任务在我更改 RETAIN 属性之前无法读取它们。为什么不能使用 GLOBAL TEMP 表,我不知道。

以上是关于如何在 SSIS 控制流任务中创建一个临时表,然后在数据流任务中使用它?的主要内容,如果未能解决你的问题,请参考以下文章

SSIS: 一步步教你在SSIS 中使用临时表

如何在打开游标之前在存储过程中创建一个临时表?

如何在 Oracle 数据库中创建临时表?

如何在 ADO.NET 源 SSIS 中传递参数

在SSIS脚本组件中创建时,变量不包含回车符

SSIS 包不想获取临时表的元数据