一、存储过程、触发器、事件的基本概念
1.1 存储过程
存储过程是一组为了完成特定功能的SQL 语句集,存储在数据库中经过第一次编译后再次调用时不需要再次编译。通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
DROP PROCEDURE IF EXISTS `储存名`;
delimiter ||
CREATE PROCEDURE `储存名`(
参数1 字段类型,
参数2 字段类型
)
BEGIN
SQL语句
END ||
delimiter;
1.2 触发器
触发器是一种特殊类型的存储过程,通过数据库表的Insert、Update、Delete操作自动触发执行。存储过程使用的参数是可以自定义的,触发器使用的参数是某个字段的新值(NEW.字段名)和旧值(OLD.字段名)
DROP TRIGGER IF EXISTS `触发器名称`;
delimiter ||
CREATE TRIGGER `触发器名称` 触发时机 (BEFORE/AFTER) 触发操作 (UPDATE/DELETE/INSERT) ON `表名` FOR EACH ROW
BEGIN
SQL语句
END ||
delimiter;
1.3 事件
事件(event)是MySQL在相应的时间点调用的过程式数据库对象。一个事件可调用一次,也可周期性的启动。事件是根据调度任务来启动的,所以事件也称为临时性触发器。
SET GLOBAL event_scheduler=ON;
DROP EVENT IF EXISTS `事件名称`;
delimiter ||
CREATE EVENT `事件名称` ON SCHEDULE EVERY 1 SECOND STARTS '2020-08-27 00:30:00' ON COMPLETION NOT PRESERVE ENABLE DO
SQL语句
||
delimiter;
特别说明:事件中可以调用存储过程
二、存储过程、触发器、事件的应用案例
2.1 触发器:更新当前表
更新当前表字段的内容不能在触发器中直接使用 UPDATE 语句来更新,触发器的触发点在表BEFORE UPDATE/INSERT时用SET NEW.字段 来赋值
1.应用场景:订单新增保存后,状态始终为“已创建”
DROP TRIGGER IF EXISTS `trigger_before_salesorder_update`;
delimiter ||
CREATE TRIGGER `trigger_before_salesorder_update` BEFORE INSERT ON `ld_salesorder` FOR EACH ROW
BEGIN
IF @disable_triggers IS NULL THEN
SET NEW.sostatus = '已创建';
END IF;
END ||
delimiter;
2.应用场景:单据编码定制需求
【海外营销编码规则如下】
例:
12101001 即代表21年新建的第1个新外销客户;
下一位:12102001由此递增,21年新建的第2个新外销客户
【国内渠道】
【国内租赁】
【ODM国内C+00001】(即:业务四部国内销售组)
控制字段:客户类型。
客户类型为业务四部国内销售组,编码为:C+流水号(五位数)
例:C00001 C00002
【ODM国外V+00001】(即:业务四部海外向销售组)
控制字段:客户类型。
客户类型为业务四部海外向销售组,编码为:V+流水号(五位数)
例:V00001 V00002
【特渠】
控制字段:客户类型、客户类别
第一个字母T(代表客户类型为特渠),
第二个字母取客户类别字段下拉框 Z、X、G(分别对应租赁、销售、大客户团购),
后面五位数 流水号。
如:TZ00001(客户类型为:特渠,且客户类别为:租赁)、TZ00001、TG00001。
2.2 触发器:更新其他表,反写相关单据
3.应用场景:项目合同(CustomForm04)中有4个字段需要反写
1)生产成本:取销售订单(SalesOrder)总金额,订单类型=“直发项目”或者“发往工厂”(项目合同下推关联销售订单)
2)外采成本:取销售订单(SalesOrder)总金额,订单类型=“外采合同”或者“施工费用”
3)商务报销成本:取报销单中总金额,报销单部门=“商务部”(项目合同上游单据“商机”关联“报销单”)
4)工程报销成本:取报销单中总金额,报销单部门=“工程部门”
5)项目合同上的林润率根据上面几个字段计算
2.3 带游标的存储过程、事件调用存储过程
4.应用场景:20天没有跟进记录的客户,自动生成“客户跟进记录”类型的任务单,每天早上7点计算一次。
实现思路:
1)每天执行,需要用事件定时调度
2)需要查询出哪些客户需要20天没有跟进记录,然后每个客户创建一个任务单,可以用游标来实现循环处理。
3)可以把创建任务单的功能,写成一个存储过程,方便调用。
2.4 其他应用场景
5.应用场景:逗号分隔的字段转换为多行,例如:自动共享
(1) 需要把 a,b,c 拆分显示为3行
最常用的场景是根据多选用户字段做共享,获取共享人的方法如下:
SELECT
a.projectid,
substring_index(substring_index(a.team_memberid,',', b.seq+1 ),',',- 1) AS share_to
FROM ld_project a
LEFT JOIN sequence b ON b.seq<(length(a.team_memberid)-length( REPLACE(a.team_memberid,',',''))+1)
LEFT JOIN ld_users u ON u.id=substring_index(substring_index(a.team_memberid,',', b.seq+1 ),',',- 1)
WHERE a.deleted=0
6.应用场景:自动创建表
(1) 自动创建表单需要操作表的顺序
lld_crmentity:写入新增单据ID
l单据头字段主表
l单据头自定义字段表
lld_modentity_num:更新单据编码流水号
l单据分录字段主表
l单据分录自定义字段表
(2) 脚本案例:自动创建带分录的表单,并且自动审批通过
(3) 循环自动创建多个表单的SQl例子
7. 其他应用案例
(1) 重算订单的收款、出库、开票信息
(2) 计算2个日期的天数差去掉周末的函数
(3) 每月1号自动生成业绩单
(4) 客户项目日报自动汇总并发送邮件
(5) 数字转英文单词函数