2014-08-30 53 views
1

我有一個表ops包含一個帳戶的操作,這個帳戶的餘額和一個索引給出這些操作的時間順序。有沒有辦法使用sqlite訪問觸發器中前一行的值?

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; 

我現在想添加一個觸發器添加新的操作時,在考慮按時間順序排列,並具有超強的idx如果任何更新行,可以計算account_balance

舉個例子,如果我這樣做: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; 

但我想知道是否有辦法做到這一點我的表內,與觸發。

+0

'idx'和'idx'指的是相同的值。你已經在另一個觸發器中使用了'NEW'。閱讀[documentation](http://www.sqlite.org/lang_createtrigger.html)。 – 2014-08-30 15:55:38

+0

@CL'WHERE idx = NEW.idx-1'觸發器不會遍歷整個表,並且不會更新具有上級idx的行。 – jkd 2014-08-30 16:04:31

回答

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); 
相關問題