MySQL 触发器、函数
触发器有时也称作事件-条件-动作规则,或者ECA规则。
触发器语法
DROP TRIGGER IF EXISTS tr_after_delete_distribution_goods;
delimiter //
CREATE TRIGGER tr_after_delete_distribution_goods
AFTER DELETE ON t_distribution_goods FOR EACH ROW
trig:BEGIN
DECLARE var_warehouseCode SMALLINT;-- 定义变量
SELECT f_warehouseCode INTO var_warehouseCode FROM t_distribution WHERE f_distNumber=OLD.f_distNumber;
UPDATE t_stock_total SET f_lockedQuantity=f_lockedQuantity-OLD.f_distQuantity WHERE f_goodsId=OLD.f_goodsId AND f_warehouseCode=var_warehouseCode;
END;
//
delimiter ;
设置触发器条件,当f_flag为“已作废”时执行更新语句
DROP TRIGGER IF EXISTS tr_after_update_distribution;
delimiter //
CREATE TRIGGER tr_after_update_distribution
AFTER UPDATE ON t_distribution FOR EACH ROW
trig:BEGIN
DECLARE var_goodsId INT;
DECLARE var_distQuantity INT;
if (NEW.f_flag='INVALID') then
SELECT f_goodsId,f_distQuantity INTO var_goodsId,var_distQuantity FROM t_distribution_goods WHERE f_distNumber=OLD.f_distNumber;
UPDATE t_stock_total SET f_lockedQuantity=f_lockedQuantity-var_distQuantity WHERE f_goodsId=var_goodsId AND f_warehouseCode=OLD.f_warehouseCode;
end if;
END;
//
delimiter ;
插入 触发器
DROP TRIGGER IF EXISTS tr_after_insert_commodity_stock;
delimiter //
CREATE TRIGGER tr_after_insert_commodity_stock
AFTER INSERT ON t_commodity FOR EACH ROW
trig:BEGIN
DECLARE var_warehouseCode INT;
SELECT f_warehouseCode INTO var_warehouseCode FROM t_stock WHERE f_purchaseNumber=NEW.f_purchaseNumber AND f_goodsId=NEW.f_goodsId;
UPDATE t_stock SET f_inQuantity=f_inQuantity+1 WHERE f_purchaseNumber=NEW.f_purchaseNumber AND f_goodsId=NEW.f_goodsId;
UPDATE t_stock_total SET f_quantity=f_quantity+1 WHERE f_goodsId=NEW.f_goodsId AND f_warehouseCode=var_warehouseCode;
END;
//
delimiter ;
查看触发器
SELECT TRIGGER_NAME FROM information_schema.`TRIGGERS`;
触发器详细代码
SHOW CREATE TRIGGER tr_after_update_stock;
推荐参考链接:http://www.cnblogs.com/fengxw/p/6076150.html
MySQL 存储过程
-- 生成一个RFID
-- 参数var_goodsId,var_quantity
DROP PROCEDURE IF EXISTS p_next_sheet_rfid;
delimiter //
CREATE PROCEDURE p_next_sheet_rfid (
OUT var_return VARCHAR(30),-- 输出值
IN var_goodsId INT,-- 输入值
IN var_quantity INT
)
BEGIN
DECLARE var_category SMALLINT;-- 临时变量
DECLARE var_brand INT;
DECLARE var_goods INT;
DECLARE var_maxRfid INT;
DECLARE var_str VARCHAR(20) DEFAULT '';
-- 异常时回滚跳出
-- DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
SET var_return='0';
START TRANSACTION;
-- 临时变量赋值
SELECT f_id,f_categoryCode,f_brandCode,f_lastRfidNumber INTO var_goods, var_category, var_brand, var_maxRfid FROM t_goods WHERE f_id=var_goodsId;
SET var_maxRfid = var_maxRfid % 100000000;
UPDATE t_goods SET f_lastRfidNumber=var_maxRfid+var_quantity WHERE f_id=var_goodsId;
-- concat连接各参数,LPAD(str,len,padstr)用字符串 padstr对 str进行左边填补直至它的长度达到 len个字符长度,然后返回 str。如果 str的长度长于 len',那么它将被截除到 len个字符。RPAD(str,len,padstr)为右边
SELECT CONCAT(LPAD(var_category, 3, '0'), LPAD(var_brand, 4, '0'), LPAD(var_goods, 5, '0'), LPAD(var_maxRfid+1, 8, '0')) INTO var_str;
SET var_return = RIGHT(var_str, 20);
COMMIT;
END;
//
delimetr;
存储过程,使用游标循环遍历数据表修改另一张表
-- 逐条从t_goods_temp导入货品到t_goods.
DROP procedure IF EXISTS p_import_goods_from_temp;
delimiter //
CREATE PROCEDURE p_import_goods_from_temp ()
BEGIN
DECLARE var_categoryCode SMALLINT;
DECLARE var_name VARCHAR(120);
DECLARE var_brandCode SMALLINT;
-- DECLARE var_brandName VARCHAR(18);
DECLARE var_superCategoryName VARCHAR(18);
DECLARE var_categoryName VARCHAR(18);
DECLARE var_saleSpec VARCHAR(18);
DECLARE var_unitCode SMALLINT;
-- DECLARE var_unitName VARCHAR(12);
DECLARE var_marketPrice DECIMAL(6, 2);
DECLARE var_done INT DEFAULT 0;
DECLARE var_warning INT DEFAULT 0;
DECLARE cur_goods_temp CURSOR FOR -- 定义游标,设置结果集
SELECT f_name, f_brandCode, f_superCategoryName, f_categoryName, f_saleSpec, f_unitCode, f_marketPrice
FROM v_goods_temp;
-- 声明异常处理
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET var_done = 1; -- 若没有数据返回,程序继续,并将变量var_done设为1 类似于DECLARE CONTINUE HANDLER FOR NOT FOUNDSET var_done = 1;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET var_warning = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
START TRANSACTION;-- 开启事务
SET var_done = 0;
OPEN cur_goods_temp; -- 打开游标
REPEAT-- 开始循环
FETCH cur_goods_temp INTO var_name, var_brandCode, var_superCategoryName, var_categoryName, var_saleSpec, var_unitCode, var_marketPrice;
-- SELECT f_categoryCode, var_brandCode, var_unitCode, var_name, var_saleSpec, var_marketPrice, now(), var_done
-- FROM v_category WHERE f_superCategoryName=var_superCategoryName AND f_categoryName=var_categoryName LIMIT 1;
-- SELECT 'cur_goods_return_out var_done: ', var_done;
IF NOT var_done THEN -- var_done=0,异常标识
INSERT INTO t_goods (f_categoryCode, f_brandCode, f_unitCode, f_name, f_saleSpec, f_marketPrice, f_creationTime)
SELECT f_categoryCode, var_brandCode, var_unitCode, var_name, var_saleSpec, var_marketPrice, now()
FROM v_category WHERE f_superCategoryName=var_superCategoryName AND f_categoryName=var_categoryName LIMIT 1;
IF var_warning THEN
SHOW warnings;
CALL p_debug(CONCAT('warning for ', var_categoryName), false);
END IF;
END IF;
UNTIL var_done END REPEAT; -- 出错时退出循环
CLOSE cur_goods_temp; -- 关闭游标
COMMIT; -- 提交数据
END;
//
delimiter ;
添加判断条件的,在游标定义语句之前不能使用SELECT定义变量,if条件判断使用=,而不是==
DROP procedure IF EXISTS p_update_distribution_stock;
delimiter //
CREATE PROCEDURE p_update_distribution_stock(
IN var_distNumber INT,
IN var_flag VARCHAR(10)
)
trig:BEGIN
DECLARE var_goodsId INT;
DECLARE var_distQuantity INT;
DECLARE var_done INT DEFAULT 0;
DECLARE var_warning INT DEFAULT 0;
DECLARE var_warehouseCode INT;
DECLARE cur_disribution CURSOR FOR
SELECT f_goodsId,f_distQuantity FROM t_distribution_goods WHERE f_distNumber=var_distNumber;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET var_done = 1;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET var_warning = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
START TRANSACTION;
SET var_done = 0;
OPEN cur_disribution;
REPEAT
FETCH cur_disribution INTO var_goodsId,var_distQuantity;
IF NOT var_done THEN
IF (var_flag = 'INVALID') THEN
SELECT f_warehouseCode INTO var_warehouseCode FROM t_distribution WHERE f_distNumber=var_distNumber;
UPDATE t_stock_total SET f_lockedQuantity=f_lockedQuantity-var_distQuantity WHERE f_goodsId=var_goodsId AND f_warehouseCode=var_warehouseCode;
ELSEIF (var_flag = 'CLEAR') THEN
SELECT f_warehouseCode INTO var_warehouseCode FROM t_distribution WHERE f_distNumber=var_distNumber;
UPDATE t_stock_total SET f_lockedQuantity=f_lockedQuantity+var_distQuantity WHERE f_goodsId=var_goodsId AND f_warehouseCode=var_warehouseCode;
ELSEIF var_warning THEN
SHOW warnings;
CALL p_debug(CONCAT('warning for ', var_goodsId), false);
END IF;
END IF;
UNTIL var_done END REPEAT;
CLOSE cur_disribution;
COMMIT;
END;
//
delimiter ;