我遇到的问题涉及AFTER Insert触发器中使用的MERGE语句。情况是我们有一个表是库存事务的历史记录,调用此表A.当记录插入表A时,会触发AFTER INSERT触发器。此触发器包含两个MERGE语句以更新表B,然后更新表C.表C的MERGE连接到表B,因此我们不重复计算。表B和表C是两个单独的库存交易汇总,以显示可用的库存。下面我贴了一些伪代码的触发器。
80%的时间都有效。另外20%的时间没有发生更新。我已经验证这不是一个逻辑问题,好像我们手动运行插入记录的合并语句,然后他们将适当地更新表B和表C中的目标记录。使用了探查器和扩展事件来尝试捕获未正确更新的实例,但无法正常处理数千个事务。触发器是我认为唯一的选项,因为客户端要求更新是实时的。我已经验证了我的所有合并语句都是正确的,它似乎就像触发器触发时它没有从插入的表中适当地拾取记录。我通过在合并中匹配的唯一键分组插入了多个记录,因此不是这个。不知所措,并会采取任何建议。
编辑:用实际代码替换伪代码
CREATE TRIGGER [dbo].[trig_HBS2013_ILTHUpdateILCandILBC_DW]
ON [RELLDW].[dbo].[ItemLotTransactionHistory]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
EXECUTE AS LOGIN = 'relldom\hbsprocessad'
MERGE [dbo].[ItemLotCurrent] WITH (HOLDLOCK) AS target
USING (SELECT
----On Hand (LocalExtAmt)
SUM(CAST(
ISNULL(ILC.ILC_dc_lclExtAmtCostOnHand, 0)
+ CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_TransactionType = 'WIP Out'
THEN ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0)
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType = 'WIP In'
THEN ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0) * -1
END
AS decimal(23, 10))) AS ILC_dc_lclExtAmtCostOnHand,
----On Hand (QtyBase)
SUM(CAST(
ISNULL(ILC.ILC_dc_QtyOnHand, 0) +
CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_TransactionType = 'WIP Out'
THEN ISNULL(ILTH.ILTH_dc_QuantityBase, 0)
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType = 'WIP In'
THEN ISNULL(ILTH.ILTH_dc_QuantityBase, 0) * -1
END
AS decimal(23, 10))) AS ILC_dc_QtyOnHand,
MAX(CAST(ILTH.ILTH_id_ItemCode AS uniqueidentifier)) AS ILC_id_Item,
CAST(MAX(ILTH.ILTH_id_lotcode) AS uniqueidentifier) AS ILC_id_ItemLot
FROM inserted AS ILTH
--Item Lot Curent
LEFT JOIN RELLDW.dbo.ItemLotCurrent AS ILC
ON ILTH.ILTH_id_LotCode = ILC.ILC_id_ItemLot
WHERE ILTH.ILTH_nv_recordtype <> 'TRANS' AND ILTH.ILTH_id_LotCode IS NOT NULL
GROUP BY
ILTH.ILTH_id_lotcode
)
AS source (
ILC_dc_lclExtAmtCostOnHand,
ILC_dc_QtyOnHand,
ILC_id_Item,
ILC_id_ItemLot
)
ON (target.ILC_id_itemlot = source.ILC_id_itemlot)
WHEN MATCHED THEN
UPDATE SET
ILC_dc_lclExtAmtCostOnHand = source.ILC_dc_lclExtAmtCostOnHand,
ILC_dc_QtyOnHand = source.ILC_dc_QtyOnHand,
ILC_id_Item = source.ILC_id_Item,
ILC_id_ItemLot = source.ILC_id_ItemLot,
WHEN NOT MATCHED THEN
INSERT (,
ILC_dc_lclExtAmtCostOnHand,
ILC_dc_QtyOnHand,
ILC_id_Item,
ILC_id_ItemLot
)
VALUES (
source.ILC_dc_lclExtAmtCostOnHand,
source.ILC_dc_QtyOnHand,
source.ILC_id_Item,
source.ILC_id_ItemLot
);
UPDATE dbo.ItemLotTransactionHistory
SET ILTH_nv_ILCUpdate='Updated'
WHERE ILTH_ID IN (select ilth_id from inserted);
MERGE [dbo].[ItemLotBinCurrent] WITH (HOLDLOCK) AS target
USING (
SELECT
CAST(CASE
WHEN ILBCSub.CostType = 861430003
THEN (ISNULL(ILC.ILC_dc_lclExtAmtCostOnHand,0) /(CASE WHEN (ISNULL(ILC.ILC_dc_QtyOnHand,0) = 0 )THEN 1 ELSE ISNULL(ILC.ILC_dc_QtyOnHand,0) END)) * (ISNULL(ILBCSub.ILBC_dc_OldQtyBase,0)+ISNULL(ILBCSub.ILBC_dc_Qtybase,0))
ELSE
CASE
WHEN (ISNULL(ILBCSub.ILBC_dc_OldqtyBase,0) + ISNULL(ILBCSub.ILBC_dc_QtyBase,0)) <= 0
THEN 0
ELSE (ISNULL(ILC.ILC_dc_lclExtAmtCostOnHand,0) /(CASE WHEN ISNULL(ILC.ILC_dc_QtyOnHand,0) = 0 THEN 1 ELSE ISNULL(ILC.ILC_dc_QtyOnHand,0) END)) * (ISNULL(ILBCSub.ILBC_dc_OldQtyBase,0)+ISNULL(ILBCSub.ILBC_dc_Qtybase,0))
END
END AS decimal(23,10)) AS ILBC_dc_localExtAmt,
ISNULL(ILBCSub.ILBC_dc_OldQtyBase,0)+ISNULL(ILBCSub.ILBC_dc_Qtybase,0) AS ILBC_dc_QuantityBase,
ILBCSub.ILBC_id_BaseUOM AS ILBC_id_BaseUOM,
ILBCSub.ILBC_id_Bin AS ILBC_id_bin,
ILBCSub.ILBC_id_Item AS ILBC_id_item,
ILBCSub.ILBC_id_LocalCurrency AS ILBC_id_localCurrency,
ILBCSub.ILBC_id_Lot AS ILBC_id_lot,
ILBCSub.ILBC_id_warehouse AS ILBC_id_warehouse,
ILBCSub.ILBC_nv_baseuomcode AS ILBC_nv_baseuomcode,
ILBCSub.ILBC_nv_bincode AS ILBC_nv_bincode,
ILBCSub.ILBC_nv_itemcode AS ILBC_nv_itemcode,
ILBCSub.ILBC_nv_itemshortdesc AS ILBC_nv_itemshortdesc,
ILBCSub.ILBC_nv_LocalCurrencyCode AS ILBC_nv_localcurrencycode,
ILBCSub.ILBC_nv_localcurrencyshortdesc AS ILBC_nv_localcurrencyshortdesc,
ILBCSub.ILBC_nv_lot AS ILBC_nv_lot,
ILBCSub.ILBC_nv_WarehouseCode AS ILBC_nv_warehousecode
FROM(SELECT
ISNULL(ILBCSum.ILBC_dc_localextamt,0) AS ILBC_dc_lclextamt,
ISNULL(ILBCSum.ILBC_dc_quantityBase,0) AS ILBC_dc_qtyBase,
ILBCSum.ILBC_id_BaseUOM AS ILBC_id_BaseUOM,
COALESCE(ILBCSum.ILBC_id_Bin, ILBC.ILBC_id_bin) AS ILBC_id_bin,
ILBCSum.ILBC_id_Item AS ILBC_id_item,
ILBCSum.ILBC_id_LocalCurrency AS ILBC_id_localCurrency,
COALESCE(ILBCSum.ILBC_id_Lot, ILBC.ILBC_id_lot) AS ILBC_id_lot,
ILBCSum.ILBC_id_warehouse AS ILBC_id_warehouse,
ILBCSum.ILBC_nv_baseuomcode AS ILBC_nv_baseuomcode,
ILBCSum.ILBC_nv_bincode AS ILBC_nv_bincode,
ILBCSum.ILBC_nv_itemcode AS ILBC_nv_itemcode,
ILBCSum.ILBC_nv_itemshortdesc AS ILBC_nv_itemshortdesc,
ILBCSum.ILBC_nv_LocalCurrencyCode AS ILBC_nv_localcurrencycode,
ILBCSum.ILBC_nv_localcurrencyshortdesc AS ILBC_nv_localcurrencyshortdesc,
ILBCSum.ILBC_nv_lot AS ILBC_nv_lot,
ILBCSum.ILBC_nv_WarehouseCode AS ILBC_nv_warehousecode,
ILBCSum.CostType AS CostType,
ILBC.ILBC_dc_quantitybase AS ILBC_dc_OldQtyBase
FROM dbo.ItemLotBinCurrent AS ILBC
----Sum up the net transaction
FULL JOIN(
SELECT
SUM(ISNULL(ILBCNet.ILBC_dc_localExtAmt,0)) AS ILBC_dc_LocalExtAmt,
SUM(ISNULL(ILBCNet.ILBC_dc_QuantityBase,0)) AS ILBC_dc_QuantityBase,
MAX(ILBCNet.ILBC_id_BaseUOM) AS ILBC_id_BaseUOM,
ILBCNet.ILBC_id_Bin AS ILBC_id_bin,
MAX(ILBCNet.ILBC_id_Item) AS ILBC_id_item,
MAX(ILBCNet.ILBC_id_LocalCurrency) AS ILBC_id_localCurrency,
ILBCNet.ILBC_id_Lot AS ILBC_id_lot,
MAX(ILBCNet.ILBC_id_warehouse) AS ILBC_id_warehouse,
MAX(ILBCNet.ILBC_nv_baseuomcode) AS ILBC_nv_baseuomcode,
MAX(ILBCNet.ILBC_nv_bincode) AS ILBC_nv_bincode,
MAX(ILBCNet.ILBC_nv_itemcode) AS ILBC_nv_itemcode,
MAX(ILBCNet.ILBC_nv_itemshortdesc) AS ILBC_nv_itemshortdesc,
MAX(ILBCNet.ILBC_nv_LocalCurrencyCode) AS ILBC_nv_localcurrencycode,
MAX(ILBCNet.ILBC_nv_localcurrencyshortdesc) AS ILBC_nv_localcurrencyshortdesc,
MAX(ILBCNet.ILBC_nv_lot) AS ILBC_nv_lot,
MAX(ILBCNet.ILBC_nv_WarehouseCode) AS ILBC_nv_warehousecode,
MAX(ILBCNet.ILBC_int_costtype) AS CostType
----POSITIVE TRANSACTIONS---
FROM(
SELECT
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR' OR ILTH.ILTH_nv_TransactionType='WIP Out'
THEN ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0)
WHEN ILTH.ILTH_nv_TransactionType = 'TRANS'
THEN
CASE
WHEN ILTH.ILTH_id_BinIn = ILTH.ILTH_id_BinOut
THEN 0
ELSE ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0)
END
ELSE 0
END AS decimal(23,10)) AS ILBC_dc_localExtAmt,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR' OR ILTH.ILTH_nv_TransactionType ='WIP Out'
THEN ISNULL(ILTH.ILTH_dc_QuantityBase, 0)
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN
CASE
WHEN ILTH.ILTH_id_BinIn = ILTH.ILTH_id_BinOut
THEN 0
ELSE ISNULL(ILTH.ILTH_dc_QuantityBase, 0)
END
ELSE 0
END AS decimal(23,10))AS ILBC_dc_QuantityBase,
CAST(ILTH.ILTH_id_BaseUofMCode AS uniqueidentifier)AS ILBC_id_BaseUOM,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_transactionType = 'WIP Out'
THEN ILTH.ILTH_id_binin
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_id_binin
END AS uniqueidentifier)AS ILBC_id_Bin,
CAST(ILTH.ILTH_id_ItemCode AS uniqueidentifier)AS ILBC_id_Item,
CAST(ILTH.ILTH_id_LocalCurrencyCode AS uniqueidentifier)AS ILBC_id_LocalCurrency,
CAST(ILTH.ILTH_id_LotCode AS uniqueidentifier)AS ILBC_id_Lot,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_transactionType = 'WIP Out'
THEN ILTH.ILTH_id_WarehouseCodein
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_id_WarehouseCodein
END AS uniqueidentifier)AS ILBC_id_warehouse,
CAST(ILTH.ILTH_nv_BaseUofMCode AS nvarchar(64))AS ILBC_nv_baseuomcode,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_transactionType = 'WIP Out'
THEN ILTH.ILTH_nv_Binin
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_nv_Binin
END AS nvarchar(64))AS ILBC_nv_bincode,
CAST(ILTH.ILTH_nv_ItemCode AS nvarchar(64))AS ILBC_nv_itemcode,
CAST(ILTH.ILTH_nv_ItemShortDesc AS nvarchar(128))AS ILBC_nv_itemshortdesc,
CAST(ILTH.ILTH_nv_LocalCurrencyCode AS nvarchar(64))AS ILBC_nv_LocalCurrencyCode,
CAST(WHS.WHS_nv_LclCurrencyShortDesc AS nvarchar(128))AS ILBC_nv_localcurrencyshortdesc,
CAST(ILTH.ILTH_nv_LotCode AS nvarchar(64))AS ILBC_nv_lot,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'POR'
OR ILTH.ILTH_nv_transactionType = 'WIP Out'
THEN ILTH.ILTH_nv_WarehouseCodein
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_nv_WarehouseCodein
END AS nvarchar(64))AS ILBC_nv_WarehouseCode,
CAST(ILTH.ILTH_int_costtype AS nvarchar(64)) AS ILBC_int_costtype
FROM inserted AS ILTH
LEFT JOIN dbo.warehouseprofile AS WHS
ON ILTH.ILTH_id_warehousecodein = WHS.WHS_id_warehouse
WHERE ILTH.ILTH_id_warehousecodein IS NOT NULL
AND ILTH.ILTH_id_binin IS NOT NULL
AND ILTH.ILTH_nv_TrnType NOT IN ('IL Adj Up Out' , 'IL Adj Up In' , 'IL Adj Down Out', 'IL Adj Down In')
AND (ILTH.ILTH_nv_RecordType = 'POR' OR ILTH.ILTH_nv_TransactionType IN ('WIP Out','TRANS'))
-----NEGATIVE TRANSACTIONS---
UNION ALL
SELECT
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL' OR ILTH.ILTH_nv_TransactionType='WIP In'
THEN ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0) * -1
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN
CASE
WHEN ILTH.ILTH_id_BinIn = ILTH.ILTH_id_BinOut
THEN 0
ELSE ISNULL(ILTH.ILTH_dc_LocalExtAmt, 0) * -1
END
ELSE 0
END AS decimal(23, 10)) AS ILBC_dc_LocalExtAmt,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL' OR ILTH.ILTH_nv_TransactionType ='WIP In'
THEN ISNULL(ILTH.ILTH_dc_quantityBase, 0) * -1
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN
CASE
WHEN ILTH.ILTH_id_BinIn = ILTH.ILTH_id_BinOut
THEN 0
ELSE ISNULL(ILTH.ILTH_dc_quantityBase, 0) * -1
END
ELSE 0
END AS decimal(23,10))AS ILBC_dc_QuantityBase,
CAST(ILTH.ILTH_id_BaseUofMCode AS uniqueidentifier)AS ILBC_id_BaseUOM,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType ='WIP In'
THEN ILTH.ILTH_id_BinOut
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_id_BinOut
END AS uniqueidentifier)AS ILBC_id_Bin,
CAST(ILTH.ILTH_id_ItemCode AS uniqueidentifier)AS ILBC_id_Item,
CAST(ILTH.ILTH_id_LocalCurrencyCode AS uniqueidentifier)AS ILBC_id_LocalCurrency,
CAST(ILTH.ILTH_id_LotCode AS uniqueidentifier)AS ILBC_id_Lot,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType ='WIP In'
THEN ILTH.ILTH_id_WarehouseCodeOut
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_id_WarehouseCodeOut
END AS uniqueidentifier)AS ILBC_id_warehouse,
CAST(ILTH.ILTH_nv_BaseUofMCode AS nvarchar(64))AS ILBC_nv_baseuomcode,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType ='WIP In'
THEN ILTH.ILTH_nv_BinOut
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_nv_BinOut
END AS nvarchar(64))AS ILBC_nv_bincode,
CAST(ILTH.ILTH_nv_ItemCode AS nvarchar(64))AS ILBC_nv_itemcode,
CAST(ILTH.ILTH_nv_ItemShortDesc AS nvarchar(128))AS ILBC_nv_itemshortdesc,
CAST(ILTH.ILTH_nv_LocalCurrencyCode AS nvarchar(64))AS ILBC_nv_LocalCurrencyCode,
CAST(WHS.WHS_nv_LclCurrencyShortDesc AS nvarchar(128))AS ILBC_nv_localcurrencyshortdesc,
CAST(ILTH.ILTH_nv_LotCode AS nvarchar(64))AS ILBC_nv_lot,
CAST(CASE
WHEN ILTH.ILTH_nv_RecordType = 'FUL'
OR ILTH.ILTH_nv_TransactionType ='WIP In'
THEN ILTH.ILTH_nv_WarehouseCodeOut
WHEN ILTH.ILTH_nv_TransactionType='TRANS'
THEN ILTH.ILTH_nv_WarehouseCodeOut
END AS nvarchar(64))AS ILBC_WarehouseCode,
CAST(ILTH.ILTH_int_costtype AS nvarchar(64)) AS ILBC_int_costtype
FROM inserted AS ILTH
LEFT JOIN dbo.warehouseprofile AS WHS
ON ILTH.ILTH_id_warehousecodein = WHS.WHS_id_warehouse
WHERE ILTH.ILTH_id_warehousecodeout IS NOT NULL
AND ILTH.ILTH_id_binout IS NOT NULL
AND ILTH.ILTH_nv_TrnType NOT IN ('IL Adj Up Out' , 'IL Adj Up In' , 'IL Adj Down Out', 'IL Adj Down In')
AND (ILTH.ILTH_nv_RecordType = 'FUL'OR ILTH.ILTH_nv_TransactionType IN ('WIP In','TRANS'))
) AS ILBCNet
WHERE ILBCNet.ILBC_id_bin is not null
GROUP BY
ILBCNet.ILBC_id_bin,
ILBCNet.ILBC_id_lot
) AS ILBCSum
ON ILBC.ILBC_id_lot = ILBCSum.ILBC_id_lot
AND ILBC.ILBC_id_bin = ILBCSum.ILBC_id_bin
WHERE ISNULL(ILBC.ILBC_id_lot,ILBCSum.ILBC_id_lot) IN (Select ILTH.ILTH_id_lotcode From inserted AS ILTH GROUP BY ILTH.ILTH_id_lotcode)
OR
ISNULL(ILBCSum.ILBC_id_lot,ILBC.ILBC_id_lot) IN (Select ILTH.ILTH_id_lotcode From inserted AS ILTH GROUP BY ILTH.ILTH_id_lotcode)
) AS ILBCSub
LEFT JOIN dbo.ItemLotCurrent AS ILC
ON ILBCSub.ILBC_id_lot=ILC.ILC_id_itemlot
)AS source
(
ILBC_dc_LocalExtAmt,
ILBC_dc_QuantityBase,
ILBC_id_BaseUOM,
ILBC_id_Bin,
ILBC_id_Item,
ILBC_id_LocalCurrency,
ILBC_id_Lot,
ILBC_id_Warehouse,
ILBC_nv_BaseUOMCode,
ILBC_nv_BinCode,
ILBC_nv_ItemCode,
ILBC_nv_ItemShortDesc,
ILBC_nv_LocalCurrencyCode,
ILBC_nv_LocalCurrencyShortDesc,
ILBC_nv_Lot,
ILBC_nv_WarehouseCode
)
ON target.ILBC_id_lot = source.ILBC_id_lot
AND target.ILBC_id_bin=source.ILBC_id_bin
WHEN MATCHED THEN
UPDATE SET
ILBC_dc_LocalExtAmt=source.ILBC_dc_LocalExtAmt,
ILBC_dc_QuantityBase=source.ILBC_dc_QuantityBase,
ILBC_ModifiedOn=GetDate()
WHEN NOT MATCHED THEN
INSERT (
ILBC_dc_LocalExtAmt,
ILBC_dc_QuantityBase,
ILBC_id_BaseUOM,
ILBC_id_Bin,
ILBC_id_Item,
ILBC_id_LocalCurrency,
ILBC_id_Lot,
ILBC_id_Warehouse,
ILBC_nv_BaseUOMCode,
ILBC_nv_BinCode,
ILBC_nv_ItemCode,
ILBC_nv_ItemShortDesc,
ILBC_nv_LocalCurrencyCode,
ILBC_nv_LocalCurrencyShortDesc,
ILBC_nv_Lot,
ILBC_nv_WarehouseCode,
ILBC_CreatedOn,
ILBC_ModifiedOn
)
VALUES (
source.ILBC_dc_LocalExtAmt,
source.ILBC_dc_QuantityBase,
source.ILBC_id_BaseUOM,
source.ILBC_id_Bin,
source.ILBC_id_Item,
source.ILBC_id_LocalCurrency,
source.ILBC_id_Lot,
source.ILBC_id_Warehouse,
source.ILBC_nv_BaseUOMCode,
source.ILBC_nv_BinCode,
source.ILBC_nv_ItemCode,
source.ILBC_nv_ItemShortDesc,
source.ILBC_nv_LocalCurrencyCode,
source.ILBC_nv_LocalCurrencyShortDesc,
source.ILBC_nv_Lot,
source.ILBC_nv_WarehouseCode,
GetDate(),
GetDate()
);
UPDATE dbo.ItemLotTransactionHistory
SET ILTH_nv_ILBCUpdate='Yes'
WHERE ILTH_ID IN (SELECT ILTH_ID from inserted)
;
END