我创建了一个触发器来触发表AFTER UPDATE
的{{1}}。这应该是在销售订单的状态更改为“已选择”时进行监控,以便在此阶段生成要创建高级装运通知的请求。
SOP_Head
当我尝试使用以下更新触发此触发器时,它仅触发第一个和最后一个订单号(ORD117196 AND ORD117199)。
CREATE TRIGGER OrderPickedCreateASN ON SOP_Head AFTER UPDATE
AS
BEGIN
-- Check the new status of the order
DECLARE @sopstatus SMALLINT
SELECT @sopstatus=SOPSTATUS FROM inserted
-- Get the SOPNUMBE
DECLARE @sopnumbe CHAR(21)
SELECT @sopnumbe=SOPNUMBE FROM inserted
-- A SOPSTATUS of 4 means the order has been set to picked
-- At this stage, create an ASN export request
IF @sopstatus=4
BEGIN
-- Create the ASN export record
EXEC AddOrderASNExportRequest @in_sopnumbe=@sopnumbe
END
-- If any other status, remove any existing requests
ELSE
BEGIN
EXEC RemoveOrderASNExportRequest @in_sopnumbe=@sopnumbe
END
END
GO
如果我将上述语句调整为仅包含未生成ASN导出请求的两个剩余订单(ORD117197和ORD117198),则会创建它们而不会出现问题。
为什么UPDATE SOP_Head SET SOPSTATUS=4
WHERE SOPNUMBE IN ('ORD117196','ORD117197','ORD117198','ORD117199')
的所有四次更新都没有触发触发器?
答案 0 :(得分:2)
您的代码假定inserted
只有一行。 inserted
是一个可以包含多行的视图。
这是完全错误的。您将需要遍历inserted
以执行每次更新的一个exec。
可能最安全的方法是使用游标 - 因为您在触发器中使用存储过程。这使得代码比原本需要的要复杂得多。
如果你有一个唯一的ID,我可能会这样做:
declare @i int;
declare @n int;
select @n = count(*), @i = 1 from inserted;
while @i <= n
begin
with i as (
select i.*, row_number() over (order by id) as seqnum
from inserted
)
select @sopstatus = SOPSTATUS, @sopnumbe = SOPNUMBE
from inserted
where seqnum = @i;
set @i := @i + 1;
IF @sopstatus=4
BEGIN
-- Create the ASN export record
EXEC AddOrderASNExportRequest @in_sopnumbe=@sopnumbe
END
-- If any other status, remove any existing requests
ELSE
BEGIN
EXEC RemoveOrderASNExportRequest @in_sopnumbe=@sopnumbe
END
end; -- while
如果可以同时插入行,这实际上比游标贵一点,但我觉得编码更容易。
答案 1 :(得分:1)
我可以想到两个解决问题的一般方法。
其中一个实际上是您实现的 - 使用存储过程。但是,我建议从SOP_Head中为大量记录触发一次存储过程的执行。 SQL的强大功能在于处理一组记录,而不是逐个循环。当然,这需要对您的SP进行一些重新设计。可能的实现可能如下:
--this UDTT could be defined in a more generic way for a good reuse
CREATE TYPE dbo.SopNrArray AS TABLE
(
SopNumber CHAR(21) PRIMARY KEY
)
GO
CREATE TRIGGER OrderPickedCreateASN ON SOP_Head AFTER UPDATE
AS
BEGIN
DECLARE @sopstatusADD dbo.SopNrArray;
INSERT @sopstatusADD
SELECT DISTINCT SOPNUMBE FROM inserted WHERE SOPSTATUS=4;
--consider removing DISTINCT if all SOPNUMBE would be unique
DECLARE @sopstatusREM dbo.SopNrArray;
INSERT @sopstatusREM
SELECT DISTINCT SOPNUMBE FROM inserted WHERE SOPSTATUS!=4;
--consider removing DISTINCT if all SOPNUMBE would be unique
-- This check could eventually be removed if considered to be more optimal
IF EXISTS (SELECT NULL FROM @sopstatusADD)
BEGIN
-- Create the ASN export record
EXEC AddOrderASNExportRequest @sopstatusADD
END
-- This check could eventually be removed if considered to be more optimal
IF EXISTS (SELECT NULL FROM @sopstatusREM)
BEGIN
EXEC RemoveOrderASNExportRequest @sopstatusREM
END
END
GO
另一种方法是使用另一个专用表实现某种FIFO队列,然后使用经常足够的预定SQL代理作业来处理记录。这有以下主要优点:
对于未来的实施,它有很多可扩展性
不会影响主流的性能。