发布时间:2023-05-24 19:30
存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合。
1. 存储过程和函数的好处
2. 存储过程和函数的区别
-- 修改结束分隔符为$ DELIMITER $ -- 创建存储过程 CREATE PROCEDURE 存储过程名称(参数列表) BEGIN SQL 语句列表; END$ -- 修改结束分隔符 DELIMITER ;
调用存储函数
CALL 存储过程名称(实际参数);
/*
创建存储过程
-- 修改分隔符为$
DELIMITER $
-- 标准语法
CREATE PROCEDURE 存储过程名称(参数列表)
BEGIN
SQL 语句列表;
END$
-- 修改分隔符为分号
DELIMITER ;
*/
-- 创建stu_group()存储过程,封装 分组查询总成绩,并按照总成绩升序排序的功能
DELIMITER $
CREATE PROCEDURE stu_group()
BEGIN
SELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC;
END$
DELIMITER ;
/*
调用存储过程
CALL 存储过程名称(实际参数);
*/
-- 调用stu_group()存储过程
CALL stu_group();
查看数据库中所有的存储过程
SELECT * FROM mysql.proc WHERE db='数据库名称';
删除存储过程
DROP PROCEDURE [IF EXISTS] 存储过程名称;
定义变量
DECLARE 变量名 数据类型 [DEFAULT 默认值];
变量赋值方式一
SET 变量名 = 变量值;
变量赋值方式二
SELECT 列名 INTO 变量名 FROM 表名 [WHERE 条件];
标准语法:
IF 判断条件1 THEN 执行的sql语句1; [ELSEIF 判断条件2 THEN 执行的sql语句2;] ... [ELSE 执行的sql语句n;] END IF;
存储过程的参数与返回值
CREATE PROCEDURE 存储过程名称([IN|OUT|INOUT] 参数名 数据类型) BEGIN SQL 语句列表; END$
IN:代表输入参数,需要由调用者传递实际数据(默认)
OUT:代表输出参数,该参数可以作为返回值
IOUT:代表既可以作为输入参数,也可以作为输出参数
/*
参数传递
CREATE PROCEDURE 存储过程名称([IN|OUT|INOUT] 参数名 数据类型)
BEGIN
SQL 语句列表;
END$
*/
/*
输入总成绩变量,代表学生总成绩
输出分数描述变量,代表学生总成绩的描述信息
根据总成绩判断:
380分及以上 学习优秀
320 ~ 380 学习不错
320以下 学习一般
*/
DELIMITER $
CREATE PROCEDURE pro_test5(IN total INT,OUT info VARCHAR(10))
BEGIN
-- 对总成绩判断
IF total > 380 THEN
SET info = '学习优秀';
ELSEIF total >= 320 AND total <= 380 THEN
SET info = '学习不错';
ELSE
SET info = '学习一般';
END IF;
END$
DELIMITER ;
-- 调用pro_test5存储过程
CALL pro_test5(350,@info);
CALL pro_test5((SELECT SUM(score) FROM student),@info);
SELECT @info;
循环语法
初始化语句; WHILE 条件判断语句 DO 循环体语句; 条件控制语句; END WHILE;
/*
while循环
初始化语句;
WHILE 条件判断语句 DO
循环体语句;
条件控制语句;
END WHILE;
*/
-- 计算1~100之间的偶数和
DELIMITER $
CREATE PROCEDURE pro_test6()
BEGIN
-- 定义求和变量
DECLARE result INT DEFAULT 0;
-- 定义初始化变量
DECLARE num INT DEFAULT 1;
-- while循环
WHILE num <= 100 DO
IF num % 2 = 0 THEN
SET result = result + num;
END IF;
SET num = num + 1;
END WHILE;
-- 查询求和结果
SELECT result;
END$
DELIMITER ;
-- 调用pro_test6存储过程
CALL pro_test6();
3. 存储函数
存储函数和存储过程非常相似,区别在于存储函数必须有返回值
创建存储函数
CREATE FUNCTION 函数名称([参数 数据类型]) RETURNS 返回值类型 BEGIN 执行的sql语句; RETURN 结果; END$
调用存储函数
SELECT 函数名称(实际参数);
删除存储函数
DROP FUNCTION 函数名称;
/*
创建存储函数
CREATE FUNCTION 函数名称([参数 数据类型])
RETURNS 返回值类型
BEGIN
执行的sql语句;
RETURN 结果;
END$
*/
-- 定义存储函数,获取学生表中成绩大于95分的学生数量
DELIMITER $
CREATE FUNCTION fun_test1()
RETURNS INT
BEGIN
-- 定义变量
DECLARE s_count INT;
-- 查询成绩大于95分的数量,为s_count赋值
SELECT COUNT(*) INTO s_count FROM student WHERE score > 95;
-- 返回统计结果
RETURN s_count;
END$
DELIMITER ;
/*
调用函数
SELECT 函数名称(实际参数);
*/
-- 调用函数
SELECT fun_test1();
/*
删除函数
DROP FUNCTION 函数名称;
*/
-- 删除函数
DROP FUNCTION fun_test1;
触发器分类
创建触发器
CREATE TRIGGER 触发器名称 BEFORE|AFTER INSERT|UPDATE|DELETE ON 表名 FOR EACH ROW BEGIN 触发器要执行的功能; END$
/*
创建触发器
DELIMITER $
CREATE TRIGGER 触发器名称
BEFORE|AFTER INSERT|UPDATE|DELETE
ON 表名
FOR EACH ROW
BEGIN
触发器要执行的功能;
END$
DELIMITER ;
*/
-- 创建INSERT型触发器。用于对account表新增数据进行日志的记录
DELIMITER $
CREATE TRIGGER account_insert
AFTER INSERT
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'INSERT',NOW(),new.id,CONCAT('插入后{id=',new.id,',name=',new.name,',money=',new.money,'}'));
END$
DELIMITER ;
-- 向account表添加一条记录
INSERT INTO account VALUES (NULL,'王五',2000);
-- 查询account表
SELECT * FROM account;
-- 查询account_log表
SELECT * FROM account_log;
-- 创建UPDATE型触发器。用于对account表修改数据进行日志的记录
DELIMITER $
CREATE TRIGGER account_update
AFTER UPDATE
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'UPDATE',NOW(),new.id,CONCAT('更新前{id=',old.id,',name=',old.name,',money=',old.money,'}','更新后{id=',new.id,',name=',new.name,',money=',new.money,'}'));
END$
DELIMITER ;
-- 修改account表中李四的金额为2000
UPDATE account SET money=2000 WHERE id=2;
-- 查询account表
SELECT * FROM account;
-- 查询account_log表
SELECT * FROM account_log;
-- 创建DELETE型触发器。用于对account表删除数据进行日志的记录
DELIMITER $
CREATE TRIGGER account_delete
AFTER DELETE
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'DELETE',NOW(),old.id,CONCAT('删除前{id=',old.id,',name=',old.name,',money=',old.money,'}'));
END$
DELIMITER ;
-- 删除account表中王五
DELETE FROM account WHERE id=3;
-- 查询account表
SELECT * FROM account;
-- 查询account_log表
SELECT * FROM account_log;
1. 查看触发器
SHOW TRIGGERS;
2. 删除触发器
DROP TRIGGER 触发器名称;
开启事务
START TRANSACTION;
回滚事务
ROLLBACK;
提交事务
COMMIT;
-- 张三给李四转账500元
-- 开启事务
START TRANSACTION;
-- 1.张三账户-500
UPDATE account SET money=money-500 WHERE NAME='张三';
出错了...
-- 2.李四账户+500
UPDATE account SET money=money+500 WHERE NAME='李四';
-- 回滚事务
ROLLBACK;
-- 提交事务
COMMIT;
这里“出错了”导致两个update都不能执行成功,这就是事务的特点,这个单元要么同时成功要么同时失败。
事务提交方式的分类
自动提交(MySQL默认)--1代表自动提交,0代表手动提交
手动提交。
查看事务提交方式
SELECT@@AUTOCOMMIT;
修改事务提交方式
SET @@AUTOCOMMIT=数字;
原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态。
也就是说一个事务执行之前和执行之后都必须处于一致性状态。
隔离性(isolcation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务。
不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
持久性(durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的。
即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
多个客户端操作时,各个客户端的事务之间应该是隔离的,相互独立的,不受影响的。
而如果多个事务操作同一批数据时,就会产生不同的问题,我们需要设置不同的隔离级别来解决这些问题。
查询数据库隔离级别
SELECT@@TRANSACTION_ISOLATION;
修改数据库隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;
注意:隔离级别从小到大安全性越来越高,但是效率越来越低,所以不建议修改数据库默认的隔离级别。