我有一个触发器(SQL 2008 R2)执行一个简单的操作,但结果不合逻辑。 以下是概述:
文本文件被送到SSIS包,其中包含一行(一条记录),将其加载到“ORDERS_IN_PROCESS”表中。数据访问模式在“OLE DB目标”中设置为“表或视图”,以允许触发触发。
这是我的ORDERS表:
OrderID ItemNo
--------- ---------
9813 1
9813 2
9813 3
9817 1
所以,SSIS执行和 ORDERS_IN_PROCESS获取一个插入的记录,即OrderID 9813
触发了触发器:
INSERT INTO ORDERS_ARCHIVE SELECT * FROM ORDERS WHERE OrderID=INSERTED.OrderID
到目前为止非常简单......
我在ORDERS_ARCHIVE(与ORDERS相同的布局)表中得到的结果是
OrderId ItemNo
--------- ----------
9813 3
2个订单项的其余部分在哪里?
注意,它只将从ORDERS表中读取的最后一行插入到ORDERS_ARCHIVE中。
我需要ORDERS_ARCHIVE中的所有3个。
为什么会这样?
我认为它与SSIS使用“OLE DB Destination”处理它的方式有关,因为如果我手动将记录插入到RLFL中,触发器就会完全按照它应该执行的操作并从BACK插入所有3条记录。 / p>
你可能会说每次触发器触发一次,我同意,但在这种情况下,我只有一批记录。
我正在考虑一个sp,但我宁愿不为那些如此微不足道的东西增加另一层次的复杂性。
有什么想法吗?
感谢。
答案 0 :(得分:5)
我认为这根本不与SSIS有关,而是与你的触发器有关。您可以在查询中使用IN
,而不是JOIN
。
INSERT INTO ORDERS_ARCHIVE
SELECT O.*
FROM ORDERS O
INNER JOIN INSERTED I
ON O.ORderID = I.OrderID
答案 1 :(得分:2)
我同意Lamark,故意拼写错误,对你的触发器的评估是不正确的。
您为触发器提供的逻辑无法编译。 WHERE子句无效。我假设,正如Lamak所做的那样,你的意图是基于OrderID加入。
create table dbo.ORDERS_ARCHIVE
(
OrderID int
, ItemNo int
)
GO
create table dbo.ORDERS
(
OrderID int
, ItemNo int
)
GO
create trigger
trUpdate
ON
dbo.ORDERS
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- This doesn't work
-- Msg 4104, Level 16, State 1, Procedure trUpdate, Line 12
-- The multi-part identifier "INSERTED.OrderID" could not be bound.
--INSERT INTO dbo.ORDERS_ARCHIVE
--SELECT *
--FROM ORDERS
--WHERE OrderID=INSERTED.OrderID;
-- I think you meant
INSERT INTO dbo.ORDERS_ARCHIVE
SELECT *
FROM ORDERS
WHERE OrderID=(SELECT INSERTED.OrderID FROM INSERTED);
END
GO
然后我开始编写一个简单的SSIS包,我有一个数据源,提供您指定的4行并写入dbo.ORDERS.
我运行了包2次,每个包在ORDERS_ARCHIVE表中共4行。 3行9813,1每行9817。
我在那里获得正确的行数,所以我相信触发器正在正确触发。相反,正在发生的是逻辑不正确。由于OrderID在ORDERS表中不是唯一的,因此数据库引擎将选择恰好满足搜索条件的第一行。只是碰巧它每次都选择相同的行(ItemNo = 1),但由于没有ORDER BY
子句就没有保证顺序,这只是随机的或者引擎选择但没有行为的工件我将继续保持一致。
修复触发器。仅在OrderID上连接到插入的虚拟表会导致多行满足条件。
create trigger
trUpdate
ON
dbo.ORDERS
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- This trigger will add all the rows from the ORDERS table
-- that match what was just inserted based on OrderID and ItemNo
INSERT INTO dbo.ORDERS_ARCHIVE
SELECT O.*
FROM dbo.ORDERS O
INNER JOIN INSERTED I
ON O.OrderID = I.OrderID
AND O.ItemNo = I.ItemNo;
END
现在,当我运行ETL时,我在ORDERS_ARCHIVE中看到4行,其中包含正确的ItemNo
值。