如何Mysql觸發(fā)器中拋出一個異常
當(dāng)想Mysql出發(fā)其中插入或者更新一條數(shù)據(jù)的時候,我希望使用觸發(fā)器進(jìn)行一些檢查工作。雖然這些工作可以使用PHP來完成,但考慮到公司做PHP的小伙子是個新手,為了簡化PHP端的業(yè)務(wù),使用觸發(fā)器來實現(xiàn)可靠性應(yīng)該更強(qiáng), 在平時的應(yīng)用中我們經(jīng)常使用觸發(fā)器來做一些關(guān)聯(lián)表的字段值的更新操作。這次,我想做的事,在插入數(shù)據(jù)之前進(jìn)行一次檢查。
當(dāng)前的應(yīng)用場景是,當(dāng)創(chuàng)建訂單的時候,先檢查用戶賬戶的余額,余額不足則終止訂單創(chuàng)建操作。通過查閱資料,從Mysql 5.5 開始為我們提供了SIGNAL函數(shù)來實現(xiàn)這個功能。
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)生一個錯誤*/
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)生一個錯誤*/
IF ROW_COUNT() <> 1 THEN
set msg = "用戶余額不足以完成支付.";
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = msg;
END IF;
END IF;
END;
這里這條觸發(fā)器的功能是庫存操作,當(dāng)庫存足夠的時候 減少庫存,否則 拋出一個異常并報告商品庫存不足:
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`, ' 庫存不足.') 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 語法(英文)