有没有办法使用sqlite访问触发器中前一行的值?

时间:2014-08-30 15:49:40

标签: sqlite

我有一个表ops,其中包含帐户操作,此帐户的余额以及指示这些操作的时间顺序的索引。

idx    op_sum    account_balance
1      200       200
2      -30       170
4      -20       160     -- this operation has idx=4 so the balance is accurate!
3       10       180

触发器确保idx保持唯一。

CREATE TRIGGER on_insert_before BEFORE INSERT ON ops
WHEN (SELECT op_sum FROM ops WHERE idx=NEW.idx)
BEGIN
    UPDATE ops SET idx=idx+1 WHERE idx>=NEW.idx;
END;

我现在想要添加一个可以在添加新操作时计算account_balance的触发器,同时考虑时间顺序并使用高级idx更新行(如果有的话)。

例如,如果我这样做:INSERT INTO ops(idx, op_sum) VALUES(2,-90);

我的表应该是这样的:

idx    op_sum    account_balance
1      200       200
3      -30        80
5      -20        70
4       10        90
2      -90       110

我尝试过这样的事情:

CREATE TRIGGER on_insert_after AFTER INSERT ON ops
FOR EACH ROW
BEGIN
    UPDATE ops SET account_balance=
        (CASE WHEN idx=1
            THEN op_sum
            ELSE (SELECT account_balance FROM ops WHERE idx=idx-1)+op_sum
        END);
END;

但它没有用(更确切地说,这部分不起作用(SELECT account_balance FROM ops WHERE idx=idx-1))。

我也在尝试使用递归公用表表达式,这样可以得到准确的结果:

WITH RECURSIVE
    cnt(x,y,z) AS (VALUES(1,200,200) UNION ALL
    SELECT
        x+1,
        (SELECT op_sum FROM ops WHERE idx=x+1),
        z+(SELECT op_sum FROM ops where idx=x+1)
    FROM cnt where x<(select max(idx) from ops))
SELECT x,y,z FROM cnt;

但我想知道是否有办法在我的桌子内部使用触发器。

1 个答案:

答案 0 :(得分:2)

要从其他行获取新值,您必须使用correlated subquery

    UPDATE ops SET account_balance=
    (CASE WHEN idx=1
        THEN op_sum
        ELSE op_sum + (SELECT account_balance
                       FROM ops AS previous_ops
                       WHERE previous_ops.idx = ops.idx - 1)
    END);