我想我偶然发现了一个边缘情况,ADO.NET数据源和OLDEB数据源都无法完全满足我的需求:
控制流程 - >执行SQL任务 - > ADO.NET数据源允许使用用户定义的表(表值参数)作为参数处理存储过程。
数据流 - > OLEDB数据源允许将一台服务器上的数据源结果直接传送到另一台服务器上的数据源。
Server1具有以下存储过程:
CREATE TYPE [dbo].[OrderKeyList] AS TABLE(
[OrderKey] [varchar](50) NULL
)
GO
CREATE PROCEDURE [dbo].[GetAllOrdersInOrderList] (
@OrderList dbo.OrderKeyList not null
)
AS
BEGIN
SELECT o.*
FROM dbo.Orders o
WHERE o.OrderKey in (SELECT o.OrderKey FROM @OrderList);
END
GO
SSIS包如下:
.-[Sequence Container]-----------------------------------------------.
| |
| .-[Data Flow Task - Populate User Variable User::OrderList]-. |
| | | |
| '-----------------------------------------------------------' |
| | |
| \|/ |
| .-[Execute SQL Task - call dbo.GetOrdersByOrderList]--------. |
| | | |
| '-----------------------------------------------------------' |
| | |
| \|/ |
| .-[ ?????????????????????????????????????? ]----------------. |
| | | |
| '-----------------------------------------------------------' |
'--------------------------------------------------------------------'
我能想到的唯一解决方案是在Source DB上添加第二个存储过程,该过程采用@OrderList varchar(max)而不是dbo.OrderKeyList表,并调用dbo.Split(',', @OrderList)并将其传递给真正的存储过程:
CREATE PROCEDURE [dbo].[GetAllOrdersInOrderListWrapper] (
@OrderList varchar(max)
)
AS
BEGIN
DECLARE @tmpOrderList dbo.OrderKeyList
SELECT
DISTINCT CAST(o.Data as varchar(50))
INTO @tmpOrderList
FROM dbo.Split(',', @OrderList) o;
EXEC dbo.GetAllOrdersInOrderList @tmpOrderList
END;
GO
但我真的不喜欢这种方法,因为:
答案 0 :(得分:1)
如果您使用控制流/执行SQL任务方法,则可以通过链接服务器将数据移动到另一台服务器上的表中。
如果你使用你提到的包装器存储过程方法,它将无法在ETL过程中进行可怕的扩展,即使在数千行中也是如此。如果是我,这是我会选择的选项。
答案 1 :(得分:0)
您的问题可能与尝试将对象作为用户定义的类型传递有关,我从未尝试过传递'表格'作为参数。
我会这样做: 而不是将数据推送到对象变量而是将其推送到源上的表(可能是temp)。可以使用表的名称作为参数运行存储过程,然后执行动态sql
CREATE PROCEDURE [dbo].[GetAllOrdersInOrderList] (
@OrderList varchar(500) not null
)
AS
BEGIN
Set @Sql = ' SELECT o.*
FROM dbo.Orders o
WHERE o.OrderKey in (SELECT o.OrderKey FROM ' + @OrderList +')';
Exec @Sql
END
也许其他人有办法完全按照你的描述去做,我自己会非常有兴趣看到这样的解决方案。
答案 2 :(得分:0)
在研究了一些之后,我在Stack Overflow上发现了一个suggestion,它通过@Jon Seigel - Using table-valued parameters in SSIS向我指出了这篇文章。
它的网络是将User :: OrderList作为参数传递给脚本任务,并编写一个C#程序直接使用ADO.NET,从而绕过SSIS GUI的限制。
你为什么要这样做呢?为什么不用C#编写所有内容?好吧,通过这样做,我个人仍然看到SSIS的好处,因为ETL过程的整体编排仍然是图形化的,因此应该非常容易阅读,即使写入更痛苦(哈!写SSIS并不痛苦?)。
我现在正在尝试这种方法,因为我可以看到多种好处,包括将来使用C#SqlBulkCopy类批量插入数据以加快加载的选项。