Partitioned View 是我在提出这个问题之前没有经验的东西。使用链接文章中提供的定义,我想出了这个schema and a sample insert 来验证我知道我在做什么。
我回滚了事务,所以我的dbo.Year1998Sales 视图中没有数据。然后我创建了一个新的 SSIS 包。我将 SSIS 用于 SQL Server 2012 的事实与结果无关,配置将相同。
我创建了一个新包,添加了一个数据流,添加了一个 OLE DB 连接管理器,在我的数据流中,我有一个连接到 OLE DB 目标的 OLE DB 源。
在我的源代码中,我使用了与我的 SQLFiddle 演示中相同的查询
SELECT
D.number AS OrderId
, D.number * 100 AS CustomerID
, DATEADD(D, d.number % 365, '1998-01-01') AS OrderDate
, 1+ (D.number % 12) AS OrderMonth
, DATEADD(mm, (D.number % 12), '1998-01-01') AS DeliveryDate
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS some_number
FROM
master.dbo.spt_values AS SV
) D (number)
ORDER BY D.number ASC;
我选择了dbo.Year1998Sales 作为目的地和中提琴,它可以工作。其实不,这并没有让我感到惊讶。 SSMS 中起作用的原因在数据流中出错。
[OLE DB 目标2] 错误:SSIS 错误代码 DTS_E_OLEDBERROR。一个
发生 OLE DB 错误。错误代码:0x80004005。 OLE DB 记录是
可用的。来源:“Microsoft SQL Server Native Client 11.0”
Hresult:0x80004005 描述:“分区视图
'FOO.dbo.Year1998Sales' 不可更新为批量的目标
操作。”。
分辨率
此错误消息的重要部分是“批量操作的目标”。
Table or view - fast load 或 Table name or view name variable - fast load 的数据访问模式将导致向表中批量插入,一般说这是您想要的。但是在这种情况下,这是不可能的,因此必须使用目标 Table or view 或 Table name or view name variable 的 RBAR(逐行)版本。
这确实有效,对于较小的数据集,这将是我的方法。
备选方案 1
完全绕过视图的逻辑构造,使用条件拆分重新创建逻辑并写入 N 个表。这将允许您对表使用批量更新。但是,将业务逻辑复制到您的包中以及对包进行进一步维护以保持两者同步的相关成本并非微不足道。如果底层视图中的逻辑发生更改并且这些更改没有传播到包或移植不正确,天堂会帮助您。除非我有可靠的商业理由,否则我不会走这条路。
备选方案 2
暂存您的数据。不是写入分区视图,而是将所有数据写入数据流中的临时表。在数据流之后,立即执行 SQL 任务,将数据从暂存表推送到视图中。
虽然我不确定,但我的假设是这将比备选方案 1 或原始分辨率更好,但尚未经过测试。我也没有将此列为主要解决方案,因为我知道在某些地方,例如我工作的地方,创建新表可能会引起很大争议。