Mysql觸發(fā)器字段雙向更新方式
Mysql觸發(fā)器字段雙向更新
業(yè)務(wù)場景
不同的業(yè)務(wù)系統(tǒng)共用余額,hjmallind_user和ims_cjdc_user兩個表不同的余額字段,但是共用余額值。
觸發(fā)器定義
DROP TRIGGER IF EXISTS `test-up_ds_wallet`;
CREATE TRIGGER `test-up_ds_wallet` AFTER UPDATE ON `ims_cjdc_user`
FOR EACH ROW
BEGIN
DECLARE ds_money decimal(10,2);
IF new.wallet <> old.wallet THEN
select money into ds_money from hjmallind_user where ptuserid=new.id;
#解決觸發(fā)器死循環(huán)
IF ds_money <> new.wallet THEN
UPDATE hjmallind_user set money=new.wallet where ptuserid=new.id;
END IF ;
END IF ;
END;
DROP TRIGGER IF EXISTS `test-up_wm_wallet`;
CREATE TRIGGER `test-up_wm_wallet` AFTER UPDATE ON `hjmallind_user`
FOR EACH ROW
BEGIN
DECLARE wm_wallet decimal(10,2);
IF new.money <> old.money THEN
select wallet into wm_wallet from ims_cjdc_user where id=new.ptuserid;
#解決觸發(fā)器死循環(huán)
IF wm_wallet <> new.money THEN
UPDATE ims_cjdc_user set wallet=new.money where id=new.ptuserid;
END IF ;
END IF ;
END;校驗代碼
select id,wallet from ims_cjdc_user where id=164438; select id,ptuserid,money from hjmallind_user where ptuserid=164438; -- update hjmallind_user set money=money+50 where ptuserid=8426; update ims_cjdc_user set wallet=wallet+20.50 where id=164438; select id,wallet from ims_cjdc_user where id=164438; select id,ptuserid,money from hjmallind_user where ptuserid=164438;
對數(shù)據(jù)庫觸發(fā)器new和old的理解
在數(shù)據(jù)庫的觸發(fā)器中經(jīng)常會用到更新前的值和更新后的值,所有要理解new和old的作用很重要。
當(dāng)時我有個情況是這樣的:
我要插入一行數(shù)據(jù),在行要去其他表中獲得一個單價,然后和這行的數(shù)據(jù)進行相乘的到總金額,將該行的金額替換成相乘的結(jié)果。
一開始我使用的after,然后對自身的值進行更改。
| insert | update | delete | |
|---|---|---|---|
| old | null | 實際值 | 實際值 |
| new | 實際值 | 實際值 | null |
在Oracle中用 :old 和 :new 表示執(zhí)行前的行,和執(zhí)行后的行。
在MySQL中用 old 和 new 表示執(zhí)行前和執(zhí)行后的數(shù)據(jù)。
問題的起源
之前對數(shù)據(jù)庫的觸發(fā)器是這樣寫的,
CREATE TRIGGER triggerName after insert ON consumeinfo
FOR EACH ROW
BEGIN
UPDATE consumeinfo SET new.金額=0;
END;觸發(fā)器創(chuàng)建沒問題,但是插入數(shù)據(jù)出現(xiàn)以下錯誤。
[Err] 1442 - Can't update table 'consumeinfo' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
但是通過上網(wǎng)搜索的結(jié)果說對本表進行修改不用使用 update consumeinfo ,直接使用 SET new.金額=0 。
這個做法對的,因為這樣使用new先對當(dāng)前的金額改變了,然后存到數(shù)據(jù)庫中的,不用使用update consumeinfo。
經(jīng)過一番努力,以下是成功后的代碼,貼出來看看
CREATE TRIGGER addnewReco BEFORE INSERT ON consumeinfo FOR EACH ROW
BEGIN
SET new.金額 = (
SELECT `單價`
FROM pricenow
WHERE `類型` = new.類型
) * new.數(shù)量;
END;后來在吃飯打湯喝的時候突然想到new和old在after和before上使用情況不同。
其實還是因為new不能在after進行賦值,只能進行讀取,復(fù)制要在before時賦值。
new和old的使用情況
下面具體說說old和new的使用情況。
在對new賦值的時候只能在觸發(fā)器before中只用,在after中是不能使用的,比如(以下是正確的)。
CREATE TRIGGER updateprice BEFORE insert ON consumeinfo FOR EACH ROW BEGIN set new.金額=0; END;
這個說明對當(dāng)前插入數(shù)據(jù)進行更新的時候使用before先更新完,然后才插入到數(shù)據(jù)庫中的,在after的觸發(fā)器中,new的賦值已經(jīng)結(jié)束了,只能讀取內(nèi)容。
如果使用after不能使用new賦值,只能取值,否則會出錯誤,比如
CREATE TRIGGER updateprice
AFTER insert
ON consumeinfo
FOR EACH ROW
BEGIN
set new.金額=0;
END;出現(xiàn)這樣的錯誤:
[Err] 1362 - Updating of NEW row is not allowed in after trigger
總結(jié)
new在before觸發(fā)器中賦值,取值;在after觸發(fā)器中取值。
old在用于取值?因為賦值沒意義?
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
與MSSQL對比學(xué)習(xí)MYSQL的心得(六)--函數(shù)
這一節(jié)主要介紹MYSQL里的函數(shù),MYSQL里的函數(shù)很多,我這里主要介紹MYSQL里有而SQLSERVER沒有的函數(shù)2014-08-08
Sql查詢MySql數(shù)據(jù)庫中的表名和描述表中字段(列)信息
這篇文章主要介紹了Sql查詢獲取MySql數(shù)據(jù)庫中的表名和描述表中列名數(shù)據(jù)類型,長度,精度,是否可以為null,默認值,是否自增,是否是主鍵,列描述等列信息2017-12-12
MySQL中幾種數(shù)據(jù)統(tǒng)計查詢的基本使用教程
這篇文章主要介紹了幾種MySQL中數(shù)據(jù)統(tǒng)計查詢的基本使用教程,包括平均數(shù)和最大最小值等的統(tǒng)計結(jié)果查詢方法,是需要的朋友可以參考下2015-12-12
MySQL數(shù)據(jù)庫IP白名單的安全設(shè)置指南
本文詳細指導(dǎo)如何在MySQL服務(wù)器上安全地設(shè)置IP白名單,包括登錄、查看權(quán)限、使用GRANT語句、刷新權(quán)限以及防火墻和云服務(wù)注意事項,確保數(shù)據(jù)庫安全,防止未經(jīng)授權(quán)訪問,需要的朋友可以參考下2025-08-08
MySQL中表復(fù)制:create table like 與 create table as select
這篇文章主要介紹了MySQL中表復(fù)制:create table like 與 create table as select,需要的朋友可以參考下2014-12-12
MySQL按時間維度對億級數(shù)據(jù)表進行平滑分表
本文將以一個真實的4億數(shù)據(jù)表分表案例為基礎(chǔ),詳細介紹如何在不影響線上業(yè)務(wù)的情況下,完成按時間維度分表的完整過程,感興趣的小伙伴可以了解一下2025-08-08

