在數據庫的觸發器中經常會用到更新前的值和更新后的值,所有要理解new和old的作用很重要。當時我有個情況是這樣的:我要插入一行數據,在行要去其他表中獲得一個單價,然后和這行的數據進行相乘的到總金額,將該行的金額替換成相乘的結果。
一開始我使用的after,然后對自身的值進行更改。
insert | update | delete | |
---|---|---|---|
old | null | 實際值 | 實際值 |
new | 實際值 | 實際值 | null |
在Oracle中用:old
和:new
表示執行前的行,和執行后的行。在MySQL中用old
和new
表示執行前和執行后的數據。
問題的起源
之前對數據庫的觸發器是這樣寫的,
1 CREATE TRIGGER triggerName after insert ON consumeinfo 2 FOR EACH ROW 3 BEGIN 4 UPDATE consumeinfo SET new.金額=0; 5 END;
觸發器創建沒問題,但是插入數據出現以下錯誤。
[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。
經過一番努力,以下是成功后的代碼,貼出來看看
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時賦值。
new和old的使用情況
下面具體說說old和new的使用情況。在對new賦值的時候只能在觸發器before中只用,在after中是不能使用的,比如(以下是正確的)。
CREATE TRIGGER updateprice BEFORE insert ON consumeinfo FOR EACH ROW BEGIN set new.金額=0; END;
這個說明對當前插入數據進行更新的時候使用before先更新完,然后才插入到數據庫中的,在after的觸發器中,new的賦值已經結束了,只能讀取內容。 如果使用after不能使用new賦值,只能取值,否則會出錯誤,比如
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在用於取值?因為賦值沒意義?