如何Mysql觸發(fā)器中拋出一個(gè)異常
當(dāng)想Mysql出發(fā)其中插入或者更新一條數(shù)據(jù)的時(shí)候,我希望使用觸發(fā)器進(jìn)行一些檢查工作。雖然這些工作可以使用PHP來(lái)完成,但考慮到公司做PHP的小伙子是個(gè)新手,為了簡(jiǎn)化PHP端的業(yè)務(wù),使用觸發(fā)器來(lái)實(shí)現(xiàn)可靠性應(yīng)該更強(qiáng), 在平時(shí)的應(yīng)用中我們經(jīng)常使用觸發(fā)器來(lái)做一些關(guān)聯(lián)表的字段值的更新操作。這次,我想做的事,在插入數(shù)據(jù)之前進(jìn)行一次檢查。
當(dāng)前的應(yīng)用場(chǎng)景是,當(dāng)創(chuàng)建訂單的時(shí)候,先檢查用戶賬戶的余額,余額不足則終止訂單創(chuàng)建操作。通過(guò)查閱資料,從Mysql 5.5 開(kāi)始為我們提供了SIGNAL函數(shù)來(lái)實(shí)現(xiàn)這個(gè)功能。
CREATE TRIGGER `tg_order_create` AFTER INSERT ON `tp_order` FOR EACH ROW BEGIN
DECLARE msg varchar(200);
/*凍結(jié)金額*/
IF 2=NEW.condition THEN
UPDATE `tp_user` SET `frozen_amount`=`frozen_amount`+NEW.amount WHERE `id`=NEW.uid AND `amount`-`frozen_amount` > NEW.amount;
/*如果余額不足,產(chǎn)生一個(gè)錯(cuò)誤*/
IF ROW_COUNT() <> 1 THEN
set msg = "用戶余額不足以完成支付.";
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = msg;
END IF;
/*扣除金額*/
ELSEIF 3=NEW.condition THEN
UPDATE `tp_user` SET `amount`=`amount`-NEW.amount WHERE `id`=NEW.uid AND `amount`-`frozen_amount` > NEW.amount;
/*如果余額不足,產(chǎn)生一個(gè)錯(cuò)誤*/
IF ROW_COUNT() <> 1 THEN
set msg = "用戶余額不足以完成支付.";
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = msg;
END IF;
END IF;
END;
這里這條觸發(fā)器的功能是庫(kù)存操作,當(dāng)庫(kù)存足夠的時(shí)候 減少庫(kù)存,否則 拋出一個(gè)異常并報(bào)告商品庫(kù)存不足:
CREATE TRIGGER `TG_order_detail_dec_stock` BEFORE INSERT ON `tp_order_detail` FOR EACH ROW BEGIN
DECLARE msg VARCHAR(200);
UPDATE `tp_stock` SET `num`=`num`-NEW.num WHERE `goods_id`=NEW.goods_id AND `mid`=NEW.mid AND `num`>=NEW.num;
IF ROW_COUNT() <> 1 THEN
SELECT CONCAT(`name`, ' 庫(kù)存不足.') INTO msg FROM `tp_goods` WHERE `id`=NEW.goods_id;
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = msg;
END IF;
END;
在PHP端的處理(注:使用ThinkPHP框架):
//前面省略若干行....
try {
if (false === ($order_pk = $tbl_order->add($order))) {
$tbl->rollback();
echo json_encode(array('success' => -1, 'message' => "創(chuàng)建訂單失敗!."), JSON_UNESCAPED_UNICODE);
return;
}
}catch (PDOException $e){
$errInfo=$e->errorInfo[2];
$tbl->rollback();
echo json_encode(array('success' => -1, 'message' => "創(chuàng)建訂單失敗!,{$errInfo}"), JSON_UNESCAPED_UNICODE);
return;
}
//后面省略若干行....
參考資料:
Mysql5.5 ?SINGAL 語(yǔ)法(英文)