如何在 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.Sora
从SQLSourceType中选择Variable
从SourceVariable中选择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 Editor的Connection Manager
页面上,执行以下操作。
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
页面上,执行以下操作。
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 控制流任务中创建一个临时表,然后在数据流任务中使用它?的主要内容,如果未能解决你的问题,请参考以下文章