對數據庫觸發器new和old的理解

在數據庫的觸發器中常常會用到更新前的值和更新後的值,全部要理解new和old的做用很重要。當時我有個狀況是這樣的:我要插入一行數據,在行要去其餘表中得到一個單價,而後和這行的數據進行相乘的到總金額,將該行的金額替換成相乘的結果。sql

一開始我使用的after,而後對自身的值進行更改。數據庫

  insert update delete
old null 實際值 實際值
new 實際值 實際值 null

在Oracle中用:old:new表示執行前的行,和執行後的行。在MySQL中用oldnew表示執行前和執行後的數據。this

問題的起源

以前對數據庫的觸發器是這樣寫的,spa

1 CREATE TRIGGER triggerName after insert ON consumeinfo
2     FOR EACH ROW
3     BEGIN
4       UPDATE consumeinfo SET new.金額=0;
5     END;
 

觸發器建立沒問題,可是插入數據出現如下錯誤。code

[Err] 1442 - Can't update table 'consumeinfo' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

可是經過上網搜索的結果說對本表進行修改不用使用update consumeinfo,直接使用SET new.金額=0。這個作法對的,由於這樣使用new先對當前的金額改變了,而後存到數據庫中的,不用使用update consumeinfo。blog

通過一番努力,如下是成功後的代碼,貼出來看看ci

CREATE TRIGGER addnewReco BEFORE INSERT ON consumeinfo FOR EACH ROW
BEGIN
SET new.金額 = (
    SELECT `單價`
    FROM pricenow
    WHERE `類型` = new.類型
    ) * new.數量;
END;

後來在吃飯打湯喝的時候忽然想到new和old在after和before上使用狀況不一樣。其實仍是由於new不能在after進行賦值,只能進行讀取,複製要在before時賦值。it

new和old的使用狀況

下面具體說說old和new的使用狀況。在對new賦值的時候只能在觸發器before中只用,在after中是不能使用的,好比(如下是正確的)。io

CREATE TRIGGER updateprice
BEFORE insert
ON consumeinfo
FOR EACH ROW
BEGIN
   set new.金額=0;
END;

這個說明對當前插入數據進行更新的時候使用before先更新完,而後才插入到數據庫中的,在after的觸發器中,new的賦值已經結束了,只能讀取內容。 若是使用after不能使用new賦值,只能取值,不然會出錯誤,好比table

1 CREATE TRIGGER updateprice
2 AFTER insert
3 ON consumeinfo
4 FOR EACH ROW
5 BEGIN
6     set new.金額=0;
7 END;

出現這樣的錯誤:

[Err] 1362 - Updating of NEW row is not allowed in after trigger
 
 

總結:new在before觸發器中賦值,取值;在after觸發器中取值。old在用於取值?由於賦值沒意義?

相關文章
相關標籤/搜索