-1

我有一个触发器(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 条记录。

您可能会争辩说,触发器每批次触发一次,我同意,但在这种情况下,我有一批只有一条记录。

我正在考虑一个 sp,但我不想为如此微不足道的事情增加另一个级别的复杂性,据说。

有任何想法吗?

谢谢。

4

2 回答 2

5

我认为这根本与 SSIS 无关,而是与您的触发器有关。而不是IN你在那里,尝试JOIN在你的查询中使用 a :

INSERT INTO ORDERS_ARCHIVE 
SELECT O.* 
FROM ORDERS O
INNER JOIN INSERTED I
     ON O.ORderID = I.OrderID
于 2013-02-14T19:14:43.627 回答
3

我同意拉马克,故意拼写错误,对你的触发器的评估是不正确的。

您为触发器提供的逻辑无法编译。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值。

于 2013-02-15T04:11:28.373 回答