微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql-server – 由CROSS APPLY触发时的顺序SQL插入

此过程有几个步骤,这些步骤反映在数据库的各个表中:

生产 – >使用类似的东西更新到库存表

UPDATE STOR SET
    STOR.BLOC1 = T.BLOC1,STOR.BLOC2 = T.BLOC2,STOR.BLOC3 = T.BLOC3,STOR.PRODUCTION = T.PROD,STOR.DELTA = T.DELTA
FROM BLDG B INNER JOIN STOR S
ON S.B_ID = B.B_ID
CROSS APPLY dbo.INVENTORIZE(B.B_ID) AS T;

上面提供了一个带有TRIGGER的日志表,如下所示:

CREATE TRIGGER trgrCYCLE
ON STOR
FOR UPDATE
AS
INSERT INTO dbo.INVT
    (TS,BLDG,PROD,ACT,VAL)
    SELECT CURRENT_TIMESTAMP,B_ID,PRODUCTION,CASE WHEN DELTA < 0 THEN 'SELL' ELSE 'BUY' END,DELTA
    FROM inserted WHERE COALESCE(DELTA,0) <> 0

最后,每次更新都应该将一行插入到我在上面添加到TRIGGER的财务表中:

INSERT INTO dbo.FINS
    (COMPANY,TS,COST2,BAL)
    SELECT CORP,CURRENT_TIMESTAMP,COST,((SELECT TOP 1 BAL FROM FINS WHERE COMPANY = CORP ORDER BY TS DESC)- COST)
    FROM inserted WHERE COALESCE(COST,0) <> 0

问题出在这一行:

((SELECT TOP 1 BAL FROM FINS WHERE COMPANY = CORP ORDER BY TS DESC)- COST)

这是为了计算帐户的最新余额.但是因为CROSS APPLY将所有INSERTS视为一个批处理,所以计算是从同一个最后一个记录完成的,并且得到了一个不正确的余额数字.例:

COST    BALANCE
----------------
          1,000   <-- initial balance
 -150       850
 -220       780   <-- should be 630

解决这个问题的方法是什么? FINS表上的触发器而不是余额计算?

解决方法

了解查询中的现有逻辑

对于满足连接条件的集合或批处理,UPDATE语句将仅触发一次触发器,Inserted语句将具有正在更新的所有记录.这是因为BATCH处理不是因为CROSS APPLY而是因为UPDATE.

在你的这个查询

SELECT CORP,0) <> 0

对于来自外部查询的每个CORP,将返回相同的BAL.

(SELECT TOP 1 BAL FROM FINS WHERE COMPANY = CORP ORDER BY TS DESC)

话虽这么说,每当CORP =’XYZ’时,你的内部查询将被1000(你的例子中使用的值)替换

SELECT CORP,(1000- COST)        
    FROM inserted WHERE COALESCE(COST,0) <> 0

现在你的inserted语句包含了所有要插入的记录.所以每个记录的成本将减去1000.因此你得到了意想不到的结果.

建议的解决方

根据我的理解,你想要计算一些累积频率类型的东西.或者上次运行总计

问题陈述的数据准备.用我的虚拟数据给你一个想法.

--Sort data based on timestamp in desc order
SELECT PK_LoginId AS Bal,FK_RoleId AS Cost,AddedDate AS TS,ROW_NUMBER() OVER (ORDER BY AddedDate DESC) AS Rno 
INTO ##tmp 
FROM dbo.M_Login WHERE AddedDate IS NOT NULL


--Check how data looks
SELECT Bal,Cost,Rno,TS FROM ##tmp

--Considering ##tmp as your inserted table,--I just added Row_Number to apply Top 1 Order by desc logic 

+-----+------+-----+-------------------------+
| Bal | Cost | Rno |           TS            |
+-----+------+-----+-------------------------+
| 172 |   10 |   1 | 2012-12-05 08:16:28.767 |
| 171 |   10 |   2 | 2012-12-04 14:36:36.483 |
| 169 |   12 |   3 | 2012-12-04 14:34:36.173 |
| 168 |   12 |   4 | 2012-12-04 14:33:37.127 |
| 167 |   10 |   5 | 2012-12-04 14:31:21.593 |
| 166 |   15 |   6 | 2012-12-04 14:30:36.360 |
+-----+------+-----+-------------------------+

从上次运行余额中减去成本的替代逻辑.

--Start a recursive query to subtract balance based on cost
;WITH cte(Bal,Rno)
AS
(
    SELECT t.Bal,t.Rno FROM ##tmp t WHERE t.Rno = 1
    UNION ALL
    SELECT c.Bal - t.Cost,t.Cost,t.Rno FROM ##tmp t 
      INNER JOIN cte c ON t.RNo - 1 = c.Rno
)
SELECT * INTO ##Fin FROM cte;

SELECT * FROM ##Fin

产量

+-----+------+-----+
| Bal | Cost | Rno |
+-----+------+-----+
| 172 |    0 |   1 |
| 162 |   10 |   2 |
| 150 |   12 |   3 |
| 138 |   12 |   4 |
| 128 |   10 |   5 |
| 113 |   15 |   6 |
+-----+------+-----+

您必须稍微发布您的列以将此功能添加到您的触发器中.

原文地址:https://www.jb51.cc/mssql/78340.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐