5.mysql中的触发器
创建存储过程和函数
触发器
● create trigger语句用来创建一个触发器,触发器的作用是当表上有对应SQL语句发生时,则触发执行
● 触发器创建时需要指定对应的表名tbl_name
create
[definer = {user | current_user}]
trigger trigger_name
trigger_time trigger_event
on tbl_name for each row
[trigger_order]
trigger_body
trigger_time: {before | after}
trigger_event: {insert | update | delete}
trigger_order: {follows | precedes}
● Definer关键词用来指定trigger的安全环境
● Trigger_time指定触发器的执行时间,BEFORE和AFTER指定触发器在表中的每行数据修改前或者后执行
● Trigger_event指定触发该触发器的具体事件
○ INSERT当新的一行数据插入表中时触发,比如通过执行insert,load data,replace语句插入新数据
○ UPDATE当表的一行数据被修改时触发,比如执行update语句时
○ DELETE当表的一行数据被删除时触发,比如执行delete,replace语句时
● 当执行insert into … on duplicate key update语句时,当碰到重复行执行update时,则触发update下的触发器
● 从5.7.2版本开始,可以创建具有相同trigger_time和trigger_event的同一个表上的多个触发器,默认情况下按照创建的时间依次执行,通过指定FOLLOWS/PRECEDES改变执行顺序,即FOLLOWS时表示新创建的触发器后执行,PRECEDES则表示新触发器先执行
● Trigger_body表示触发器触发之后要执行的一个或多个语句,在内部可以引用涉及表的字段,OLD.col_name表示行数据被修改或删除之前的字段数据,NEW.col_name表示行数据被插入或修改之后的字段数据
• delimiter //
• create trigger simple_trigger
• after update
• on students for each row
• begin
• insert into students_bak values(old.sid,old.sname,new.sname,old.sex,new.sex,now());
• end;
• //
• delimiter ;
● Drop trigger语句用来删除一个触发器
drop trigger [if exists] [schema_name].trigger_name
● 当你执行drop table时,表上的触发器也被drop掉了
存储过程创建语句
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
[begin_label:] BEGIN
[statement_list]
……
END [end_label]
说明:
函数与存储过程最大的区别就是函数调用有返回值,调用存储过程用call语句,而调用函数就直接引用函数名+参数即可
Definer和sql security子句指定安全环境
- Definder是MySQL的特殊的访问控制手段,当数据库当前没有这个用户权限时,执行存储过程可能会报错
- definer:在执行存储过程前验证definer对应的用户如:cdq@127.0.0.1是否存在,以及是否具有执行存储过程的权限,若没有则报错
- invoker:在执行存储过程时判断inovker即调用该存储过程的用户是否有相应权限,若没有则报错
in out inout只适用于存储过程
- IN输入参数用于把数值传入到存储过程中;
- 需要注意变量的生效范围,是局部变量还是全局变量,如果是全局变量,虽然在存储过程中被修改,但任然不会变化
- OUT输出参数将数值传递到调用者,初始值是NULL;
- INOUT输入输出参数把数据传入到存储过程,在存储过程中修改之后再传递到调用者
Delimiter命令是改变语句的结束符,MySQL默认的结束符为;号,由于procedure和function中 的;号并不代表创建的结束,所以要替换成另外的结束符以便表示创建的结束
Rontine_body子句可以包含一个简单的SQL语句,也可以包含多个SQL语句,通过begin…end将这多个SQL语句包含在一起
MySQL存储过程和函数中也可以包含类似create和drop等DDL语句
Comment子句用来写入对存储过程和函数的注释
Language子句用来表示此存储过程和函数的创建语言
存储过程和函数被标注为deterministic表明当输入相同的参数是会返回相同的结果,反之如果是not deterministic则表示相同参数不会是相同结果,默认是not deterministic
delimiter 的用法
delimiter //
create function simplefunc(param1 int)
returns int
begin
update students set sex=1 where sid = param1;
select count(*) into @a from students where sid > param1;
return @a;
end;
//
相关属性短语只有咨询含义,并不是强制性的约束
- Contains sql表明此存储过程或函数不包含读或者写数据的语句,这是默认属性
- NO SQL表示此存储过程或函数不包含SQL语句
- Reads sql data表示此存储过程包含诸如select的查询数据的语句,但不包含插入或删除数据的语句
- Modifies sql data表示此存储过程包含插入或删除数据的语句
drop procedure / function语句
drop {procedure | function} [if exists] sp_name;
Begin…end复合语句
- Begin…end语句通常出现在存储过程、函数和触发器中,其中可以包含一个或多个语句,每个语句用;号隔开
[begin_label:]begin
[statement_list]
end [end_label]
标签label可以加在begin…end语句以及loop, repeat和while语句
语句中通过iterate和leave来控制流程,iterate表示返回指定标签位置,leave表示跳出标签
[begin_label:] begin
[statement_list]
end [end_label]
[begin_label:] loop
statement_list
end loop [end_label]
[begin_label:] repeat
statement_list
until search_condition
end repeat [end_label]
[begin_label:] while search_condition do
statement_list
end while [end_label]
CREATE PROCEDURE doiterate(IN p1 INT, OUT p2 int)
• -> BEGIN
• -> label1: LOOP
• -> SET p1 = p1 + 1;
• -> IF p1 < 10 THEN ITERATE label1; END IF;
• -> LEAVE label1;
• -> END LOOP label1;
• -> set p2=p1;
• -> END;
• -> //
• Query OK, 0 rows affected (0.00 sec) • mysql> delimiter ;
declare语句
Declare语句通常用来声明本地变量、游标、条件或者handler
Declare语句只允许出现在begin … end语句中而且必须出现在第一行
Declare的顺序也有要求,通常是先声明本地变量,再是游标,然后是条件和handler
存储过程中的变量
- 本地变量可以通过declare语句进行声明
- 声明后的变量可以通过select … into var_list进行赋值,或者通过set语句赋值,或者通过定义游标并使用fetch … into var_list赋值
- 通过declare声明变量方法:
declare var_name [, var_name] ... type [default value]
- 使用default指定变量的默认值,如果没有指定默认值则初始值为NULL
- Type指明该变量的数据类型
- 声明的变量作用范围为被声明的begin … end语句块之间
- 声明的变量和被引用的数据表中的字段名要区分开来
存储过程中的变量
delimiter //
CREATE PROCEDURE sp1 (v_sid int)
BEGIN
DECLARE xname VARCHAR(5) DEFAULT 'bob';
DECLARE xsex INT;
SELECT sname, sex INTO xname, xsex
FROM students WHERE sid= v_sid;
SELECT xname,xsex;
END;
//
delimiter ;
流程控制语句
- MySQL支持if,case,iterate,leave,loop,while,repeat语句作为存储过程和函数中的流程控制语句,另外return语句也是函数中的特定流程控制语句
case case_value
when when_value then statement_list
[when when_value then statement_list] ...
[else statement_list]
end case
case
when search_condition then statement_list
[when search_condition then statement_list]
[else statement_list]
end case
delimiter //
CREATE PROCEDURE exp_case(v_sid int)
BEGIN
DECLARE v INT DEFAULT 1;
select sex into v from students where sid=v_sid;
CASE v
WHEN 0 THEN update students set sex=1 where sid=v_sid;
WHEN 1 THEN update students set sex=0 where sid=v_sid;
ELSE
update students set sex=-1 where sid=v_sid; • END CASE;
END;
//
delimiter ;
delimiter //
CREATE PROCEDURE exp_case2(v_sid int)
BEGIN
DECLARE v INT DEFAULT 1;
select sex into v from students where sid=v_sid;
CASE
WHEN v=0 THEN update students set sex=1 where sid=v_sid;
WHEN v=1 THEN update students set sex=0 where sid=v_sid; • ELSE
update students set sex=-1 where sid=v_sid; • END CASE;
END;
//
delimiter ;
- 流程控制语句
if
if search_condition then statement_list
[elsif search_condition then statement_list] ...
[else statement_list]
end if
IF语句中如果search_condition满足true/1的条件,则执行对应的statement_list,否则再判断elseif中的search_condition是否满足true/1的条件,如果都不满足则执行else中的statement_list语句
Statement_list中可以包含一个或多个SQL语句
• DELIMITER //
• CREATE FUNCTION SimpleCompare(n INT, m INT)
• RETURNS VARCHAR(20)
• BEGIN
• DECLARE s VARCHAR(20);
• IF n > m THEN SET s = '>';
• ELSEIF n = m THEN SET s = '=';
• ELSE SET s = '<';
• END IF;
• SET s = CONCAT(n, ' ', s, ' ', m);
• RETURN s;
• END //
• DELIMITER ;
- Iterate语句仅出现在loop,repeat,while循环语句中,其含义表示重新开始此循环
iterate
iterate label
label表示自定义的标签名
Leave语句表明退出指定标签的流程控制语句块
通常会用在begin…end,以及loop,repeat,while的循环语句中
leave label
# label表名要退出的标签名
• mysql> delimiter //
• mysql> CREATE PROCEDURE doiterate(IN p1 INT, OUT p2 int) • -> BEGIN
• -> label1: LOOP
• -> SET p1 = p1 + 1;
• -> IF p1 < 10 THEN ITERATE label1; END IF;
• -> LEAVE label1;
• -> END LOOP label1;
• -> set p2=p1;
• -> END;
• -> //
流程控制loop语句
- Loop语句是存储过程或函数中表达循环执行的一种方式
[begin_label:] loop
statement_list
end loop [end_label]
- 其中的statement_list可以包含一个或多个SQL语句
CREATE PROCEDURE doiterate(p1 INT)
BEGIN
label1: LOOP
SET p1 = p1 + 1;
IF p1 < 10 THEN
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
SET @x = p1;
END; 01
流程控制repeat语句
- repeat语句是存储过程或者函数中表达循环执行的一种方式
[begin_label] repeat
statement_list
until search_condition
end repeat [end_label]
Repeat语句中statement_list一直重复执行直到search_condition条件满足
Statement_list可以包含一个或多个SQL语句
• mysql> delimiter //
• mysql> CREATE PROCEDURE dorepeat(p1 INT)
• -> BEGIN
• -> SET @x = 0;
• -> REPEAT
• -> SET @x = @x + 1;
• -> UNTIL @x > p1 END REPEAT;
• -> END
• -> //
while
语句是存储过程或者函数中表达循环执行的一种方式
当search_condition返回为true时,则循环执行statement_list中的语句,直到search_condition的结果返回为false
Statement_list中可以包含一个或多个SQL语句
[begin_list] while search_condition do
statement_list
end while [end_label]
create procedure pro1()
begin
declare std_id int default 1;
while std_id > 10 do
insert into student values(std_id,'milk',1,1);
set std_id = std_id +1;
end while;
end ;
return
- 语句用在函数中,用来终结函数的执行过程并将指定值返回给调用者
return expr
- 在函数中必须要有至少一个return语句,当有多个return语句时则表名函数有多种退出方式
• delimiter //
• create function doreturn()
• returns int
• begin
• select sex into @a from students where sid=1;
• if @a=1 then return 1;
• elseif @a=0 then return 0;
• else return 999;
• end if;
• end;
• //
• delimiter ;
游标
cursor游标用来声明一个数据集
游标的声明必须在变量和条件声明之后,在handle声明之前
声明游标
- Cursor declare语句用来声明一个游标和指定游标对应的数据集合,通常数据集合是一个select语句
declare cursor_name cursor for select_statement
# select_statement代表一个select语句
打开游标
- Open cursor语句用来打开一个之前已经声明好的游标
open cursor_name
读取游标
- Cursor fetch语句用来获取游标指定数据集的下一行数据并将各个字段值赋予后面的变量
fetch [[next] from ] cursor_name into var_name [, var_name] ...
数据集中的字段需要和into语句中定义的变量一一对应
数据集中的数据都fetch完之后,则返回not found
关闭游标
CLOSE cursor_name ;
declare condition语句(异常处理)
- Declare condition语句命名特定的错误条件,而该特定错误可以在declare…handler中指定处理方法
declare condition_name condition for condition_value
condition_value:
mysql_error_code
| sqlstate [value] sqlstate_value
Condition_value指定特定的错误条件,可以有以下两种形式
- Mysql_err_code表示MySQL error code的整数
- SQLSTATE sqlstate_value表示MySQL中用5位字符串表达的语句状态
在MySQL中1051error code表示的是unknown table的错误,如果要对这个错误做特殊处理,可以用三种种方法:
• DECLARE CONTINUE HANDLER FOR 1051
• BEGIN
• -- body of handler
• END;
• DECLARE no_such_table CONDITION FOR 1051;
• DECLARE CONTINUE HANDLER FOR no_such_table
• BEGIN
• -- body of handler
• END;
• DECLARE no_such_table CONDITION FOR SQLSTATE '42S02';
• DECLARE CONTINUE HANDLER FOR no_such_table
• BEGIN
• -- body of handler
• END;
declare handler语句(异常处理)
Declare handler语句用来声明一个handler来处理一个或多个特殊条件,当其中的某个条件满足时则触发其中的statement语句执行
Statement可以是一个简单SQL语句,也可以是begin…end组成的多个语句
declare handle_action handler
for condition_value [,condition_value] ...
statement
handler_action:
continue
| exit
| undo
condition_value:
mysql_error_code
| sqlstate [value] sqlstate_value
| condition_name
| sqlwarning
| not found
| sqlexception
Handler_action子句声明当执行完statement语句之后应该怎么办
- Continue代表继续执行该存储过程或函数
- Exit代表退出声明此handler的begin…end语句块
- Undo参数已经不支持
condition_value的值有以下几种
- Mysql_err_code表示MySQL error code的整数
- SQLSTATE sqlstate_value表示MySQL中用5位字符串表达的语句状态
- Condition_name表示之前在declare…condition语句中声明的名字
- SQLWARNING表示所有的警告信息,即SQLSTATE中01打头的所有错误
- NOT FOUND表示查完或者查不到数据,即SQLSTATE中02打头的所有错误
- SQLEXCEPTION表示所有的错误信息
• DECLARE CONTINUE HANDLER FOR 1051
• BEGIN
• -- body of handler
• END;
•
• DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
• BEGIN
• -- body of handler
• END;
•
• DECLARE CONTINUE HANDLER FOR SQLWARNING
• BEGIN
• -- body of handler
• END;
•
• DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
• BEGIN
• -- body of handler
• END;
当condition发生但没有声明handler时,则存储过程和函数依照如下规则处理
- 发生SQLEXCEPTION错误,则执行exit退出
- 发生SQLWARNING警告,则执行contine继续执行
- 发生NOT FOUND情况,则执行continue继续执行
• 比如SQLSTATE ‘23000’表示主键冲突错误
• mysql> CREATE TABLE t (s1 INT, PRIMARY KEY (s1));
• Query OK, 0 rows affected (0.00 sec)
• mysql> delimiter //
• mysql> CREATE PROCEDURE handlerdemo ()
• -> BEGIN
• -> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
• -> SET @x = 1;
• -> INSERT INTO test.t VALUES (1);
• -> SET @x = 2;
• -> INSERT INTO test.t VALUES (1);
• -> SET @x = 3;
• -> END;
• -> //
CREATE PROCEDURE curdemo()
• BEGIN
• DECLARE done INT DEFAULT FALSE;
• DECLARE a CHAR(16);
• DECLARE b, c INT;
• DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
• DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
• DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
• OPEN cur1;
• OPEN cur2;
• read_loop: LOOP
• FETCH cur1 INTO a, b;
• FETCH cur2 INTO c;
• IF done THEN
• LEAVE read_loop; • END IF;
• IF b < c THEN
• INSERT INTO test.t3 VALUES (a,b);
• ELSE
• INSERT INTO test.t3 VALUES (a,c);
• END IF;
• END LOOP;
• CLOSE cur1;
• CLOSE cur2;
• END;
0
mysql中prepare语句的使用方法
SELECT *
FROM products
WHERE productCode = ?;
MySQL PREPARE 语句用法
为了使用MySQL预处理语句,您需要使用其他三个MySQL语句,如下所示:
PREPARE - 准备要执行的语句。
EXECUTE - 执行由PREPARE语句准备的预准备语句。
DEALLOCATE PREPARE - 发布准备好的声明。
下图说明了如何使用预准备语句:

PREPARE stmt1 FROM 'SELECT productCode, productName
FROM products
WHERE productCode = ?';
SET @pc = 'S10_1678';
EXECUTE stmt1 USING @pc;
DEALLOCATE PREPARE stmt1;
首先,我们使用PREPARE语句准备执行语句。我们使用 SELECT语句根据指定的产品代码查询products表中的产品数据 。我们使用问号(?)作为产品代码的占位符。
接下来,我们声明了一个产品代码变量 @pc并将其值设置为S10_1678。
然后,我们使用EXECUTE语句用产品代码变量执行预准备语句@pc。
最后,我们用它 DEALLOCATE PREPARE来发布准备好的声明。
类似于python中%的一个用法,对字符串进行占位,使用按照需求进行传值
mysql中如何查询存储过程相关语句
SHOW PROCEDURE STATUS LIKE 存储过程名;
# 或者通过select语句获取
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=存储过程名;
5.mysql中的触发器的更多相关文章
- Oracle使用触发器和mysql中使用触发器的比较——学习笔记
一.触发器 1.触发器在数据库里以独立的对象存储, 2.触发器不需要调用,它由一个事件来触发运行 3.触发器不能接收参数 --触发器的应用 举个例子:校内网.开心网.facebook,当你发一个日志, ...
- Oracle使用触发器和mysql中使用触发器的比较
一.触发器 1.触发器在数据库里以独立的对象存储, 2.触发器不需要调用,它由一个事件来触发运行 3.触发器不能接收参数 --触发器的应用 举个例子:校内网.开心网.facebook,当你发一个日志, ...
- mysql中的触发器和事务的操作
触发器 语法 创建触发器: CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigge ...
- Mysql中的触发器
什么是触发器 简单的说,就是一张表发生了某件事(插入.删除.更新操作),然后自动触发了预先编写好的若干条SQL语句的执行: 特点及作用 特点:触发事件的操作和触发器里的SQL语句是一个事务操作,具有原 ...
- MySQL中的触发器应用
直接上代码: /*数据库 - udi_ems_test*********************************************************************内容:在 ...
- MySQL中的触发器insert、update
以下为MySQL 触发器insert 的3个示例演示(update类似) delimiter // create trigger InsertUser before insert on user fo ...
- Mysql中的触发器【转】
转载:https://www.cnblogs.com/chenpi/p/5130993.html 阅读目录 什么是触发器 特点及作用 例子:创建触发器,记录表的增.删.改操作记录 弊端 什么是触发器 ...
- 【MySQL笔记】触发器,存储过程和函数
一.触发器 触发器(TRIGGER):是由事件来触发某个操作.当数据库系统执行这些事件时,就会激活触发器执行相应的操作.MySQL从5.0.2版本开始支持触发器. 触发事件:INSERT语句.UPDA ...
- Python3.7.1学习(七)mysql中pymysql模块详解(一)
pymysql是纯用Python操作MySQL的模块,其使用方法和MySQLdb几乎相同.此次介绍mysql以及在python中如何用pymysql操作数据库, 以及在mysql中存储过程, 触发器以 ...
- MySQL中的存储过程、函数与触发器
一.对待存储过程和函数的态度 优点: 1.存储过程只在创建时进行编译,sql语句则每次执行都需要编译.能提高数据库执行速度. 2.简单复杂操作结合事物一起封装. 3.复用性高. 4.安全性高,可指定存 ...
随机推荐
- 暑假集训CSP提高模拟7
这个 T1 的 \(n^{3}\) 的 SPJ 效率还是太慢了,膜拜 SPJ 大神学长,还会画画 A.Permutations & Primes 这题感觉挺水的但是感觉有不是那么水,主要还是因 ...
- C#爬取动态网页上的信息:B站主页
目录 简介 获取 HTML 文档 解析 HTML 文档 测试 参考文章 简介 动态内容网站使用 JavaScript 脚本动态检索和渲染数据,爬取信息时需要模拟浏览器行为,否则获取到的源码基本是空的. ...
- 基于全息感知的智慧高速IT设施监控运维方案
作为智能交通的重要细分领域,建设智慧高速是实施交通强国战略的重要基础.在信息化时代,交通行业已经依托信息化建设取得了显著的成果,其中以收费网络.办公网络.监控网络和通讯网络为基础的网络架构已经形成,并 ...
- Java如何将Object转换成指定Class对象
在Java中,将Object转换为指定类型的Class对象实际上是两个不同概念的操作: 将Object实例转换为特定类型的实例:这通常涉及到类型转换(如(MyType) myObject)或者通过反射 ...
- CentOS7 安装配置笔记 v2
1.通过镜像安装 CentOS72.安装 wget 下载工具3.修改镜像地址4.安装 nano 文本编辑工具5.安装 dotnet core6.安装vsftpd7.设置 firewalld8.为 do ...
- iOS中UIlabel多行文本展示使用小结
最近在项目开发中遇到了一个新的需求,就是菜单标题最多两行展示,一行展示的标签顶部和两行展示的标签顶部对齐.看到要求后,第一反应是这是什么奇葩的设计,但是没办法谁让别人是产品经理呢.细细思索后,代码如下 ...
- innerText 和 inner HTML 的区别
获取内容时: innerText会自动删除空格和换行:innerHTML会保留空格和换行: <body> <div>获 取内 容</div> <script& ...
- kotlin函数和Lambda表达式——>内联函数
1.内联函数 使用高阶函数会带来一些运行时的效率损失:每一个函数都是一个对象,并且会捕获一个闭包.即那些 在函数体内会访问到的变量.内存分配(对于函数对象和类)和虚拟调用会引入运行时间开销. 但是在许 ...
- KubeSphere 3.2.0 发布:带来面向 AI 场景的 GPU 调度与更灵活的网关
现如今最热门的服务器端技术是什么?答案大概就是云原生!KubeSphere 作为一个以 Kubernetes 为内核的云原生分布式操作系统,也是这如火如荼的云原生热潮中的一份子.KubeSphere ...
- mysql主从复制详细部署
1.异步复制:这是MySQL默认的复制模式.在这种模式下,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接收并处理.这种模式的优点是实现简单,但缺点是如果主库崩溃,已经提 ...