MySQL基础学习5
标签(空格分隔): MySQL
TCL(事务控制语言)
事务:
一个或一组SQL语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行
事务的ACID(acid)属性
1. 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位事务中的操作要么都发生,要么都不发生。
2. 一致性(Consistency)
事务必须使数据库从一个一致性状态变换到外一个一致性状态。
3. 隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4. 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
事务的创建
隐藏事务:事务没有明显的开始和结束的标记
比如:insert、update、delete语句
显示事务:事务具有明显的开启和结束标志
前提:必须先设置自动提交功能为禁用
自动提交功能禁用语句:
set autocommit = 0 ;
步骤1:开启事务
set autocommit = 0 ;
start transaction ;#可选
步骤2:编写事务中的SQL语句(select insert update delete)
语句1;
语句2;
...
步骤3:结束事务
commit ;提交事务
rollback ;回滚事务
savepoint 节点名; 设置保存点
演示事务的使用步骤
提交
1.开启事务SET autocommit = 0 ; START TRANSACTION ;
2.编写一组事务的语句
UPDATE account SET balance = 500 WHERE username = '张无忌' ; UPDATE account SET balance = 1500 WHERE username = '赵敏' ;
3.结束事务
COMMIT ;
回滚
1.开启事务SET autocommit = 0 ; START TRANSACTION ;
2.编写一组事务的语句
UPDATE account SET balance = 500 WHERE username = '张无忌' ; UPDATE account SET balance = 1500 WHERE username = '赵敏' ;
3.结束事务
ROLLBACK ;
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制,就会导致各种并发问题:
脏读: 对于两个事务 T1, T2,T1读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
不可重复读: 对于两个事务T1, T2, T1读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力,
使它们不会相互影响, 避免各种并发问题.
一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度,隔离级别越高, 数据一致性就越好, 但并发性越弱
事务的隔离级别
无 | 脏读 | 幻读 | 不可重复读 |
---|---|---|---|
read uncommitted ; | √ | √ | √ |
read committed ; | × | √ | √ |
repeatable read ; | × | × | √ |
serializable ; | × | × | × |
MySQL中默认 第三个隔离级别 repeatable read
order中默认 第二个隔离级别 read committed
查看隔离级别:select @@tx_isolation ;
设置隔离级别:set session transaction isolation level 隔离级别 ;
2.delect 和 truncate
DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。
TRUNCATE TABLE
则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。
在事务使用时的区别
演示delect
SET autocommit = 0 ;#开启事务
START TRANSACTION ;
DELETE FROM `account` ;
ROLLBACK ;
演示truncate
SET autocommit = 0 ;#开启事务
START TRANSACTION ;
TRUNCATE TABLE`account` ;
ROLLBACK ;
3.演示savepoint的使用
SET autocommit = 0 ;#开启事务
START TRANSACTION ;
DELETE FROM `account` WHERE id = 1;
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id = 28;
ROLLBAKE TO a;#回滚到保存点
视图
含义:虚拟表,和普通表一样使用
MySQL15.1版本出现的新特性,是通过表动态生成的数据
|无|创建语法的关键字|是否实际占用物理空间|使用
|---|---|---|
|视图|create view|只是保存了SQL逻辑|增删改查,只是一般不能增删改
|表|create table |保存了数据|增删改查
案例:查询姓张的学生名和专业名
一般写法:
SELECT stuname,majorname
FROM stuinfo AS s
INNER JOIN major AS m ON s.majorid = m.`id`
WHERE s.stuname LIKE '张' ;
视图写法:
封装视图
CREATE VIEW v1
AS
SELECT stuname,majorname
FROM stuinfo AS s
INNER JOIN major AS m ON s.majorid = m.`id` ;
每次实现相同目标,调用该视图即可
视图调用
SELECT * FROM v1 WHERE stuname LIKE '张' ;
一、创建视图
语法:
create view 视图名
as
查询语句 ;
案例1、查询邮箱中包含a字符的员工名,部门名,和工种信息
①创建视图
CREATE VIEW myv1
AS
SELECT last_name,`department_name`,`job_title`
FROM `departments` AS d
INNER JOIN `employees` AS e ON e.`department_id` = d.`department_id`
INNER JOIN `jobs` AS j ON j.`job_id` = e.`job_id` ;
②使用
SELECT * FROM myv1 WHERE last_name LIKE '%a%' ;
2.查询各部门的平均工资
创建视图查看各部门的平均工资
CREATE VIEW myv2
AS
SELECT AVG(`salary`) AS ag ,`department_id`
FROM `employees`
GROUP BY `department_id` ;
使用
SELECT myv2.ag ,jg.`grade_level`
FROM myv2
INNER JOIN `job_grades` AS jg
ON myv2.ag BETWEEN jg.`lowest_sal` AND jg.`highest_sal` ;
3.查询平均工资最低的部门信息(调用2.)
SELECT DISTINCT de.*
FROM `departments` AS de
INNER JOIN myv2
ON de.`department_id` = (
SELECT myv2.`department_id`
FROM myv2
ORDER BY myv2.`ag` LIMIT 1
) ;
4.查询平均工资最低的部门名和工资
CREATE VIEW myv3
AS
SELECT * FROM myv2
ORDER BY myv2.`ag` LIMIT 1 ;
SELECT d.*,m.ag
FROM `departments` AS d
INNER JOIN myv3 AS m
ON d.`department_id` = m.`department_id
视图的修改
方法一:
create or replace view 视图名
as
查询语句 ;
案例:更改myv3
CREATE OR REPLACE VIEW myv3
AS
SELECT AVG(`salary`),job_id
FROM `employees`
GROUP BY `job_id` ;
方法二:
alter view 视图名
as
查询语句 ;
案例:将myv3改回之前的,部门工资平均值的部门,平均工资和部门名
ALTER VIEW myv3
AS
SELECT AVG(`salary`),`department_id`
FROM `employees`
GROUP BY `department_id`
ORDER BY AVG(`salary`) LIMIT 1
视图的删除
语法:drop view 视图名,视图名.... ;
DROP VIEW myv1,myv2,myv3 ;
视图的查看(结构的查看)
语法:desc 视图名;
1、
DESC myv3 ;
2、
SHOW CREATE VIEW myv3 ;
视图的更新(原始表也一起更新,更改)简单的语句
1、插入
INSERT INTO myv1 VALUES('张飞','zf@qq.com',100000000) ;
2、修改语句
UPDATE myv1 SET last_name = '张无忌' WHERE last_name = '张飞' ;
3、删除
DELETE FROM myv1 WHERE last_name = '张无忌' ;
具备以下特点的试图不允许更新
• 包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all
• 常量视图
• Select中包含子查询
• join
• from一个不能更新的视图
• where子句的子查询引用了from子句中的表
可以通过以下两种方式来删除主表的记录
方式一:级联删除
方式二:级联置空
变量
系统变量:
全局变量
会话变量
自定义变量:
用户变量
局部变量
一、系统变量
说明:变量由系统提供,不是用户定义,属于服务器层面
使用语法:
1、查看所有的系统便变量
SHOW 关键词(global|【session】) variables ;
2、查看满足条件的部分系统变量
show 关键词(global|【session】) variables like '%char%' ;
3、查看指定的某个系统变量的值
select @@关键词(global|【session】).系统名 ;
4、为某个系统变量赋值
方式一:
set 关键词(global|【session】) 系统变量名 = 值 ;
方式二:
set @@关键词(global|【session】).系统变量名 = 值 ;
注意:
如果是全局级别,则需要加global,如果是会话级别,则需要加session,如果不写,则默认session
1》全局变量
作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启
①查看所有的全局变量
SHOW GLOBAL VARIABLES ;
②查看部分的全局变量
SHOW GLOBAL VARIABLES LIKE '%char%' ;
③查看指定的全局变量的值
SELECT @@global.autocommit ;#1-》true
SELECT @@tx_isolation ;
④为某个指定的全局变量赋值(跨连接有用)
SET @@global.autocommit = 0 ;#值改为0
SELECT @@global.autocommit ;可查看是否更改成功
2》会话变量
作用域:仅仅针对于当前会话(连接)有效
①查看所有的会话变量
SHOW SESSION VARIABLES ;
SHOW VARIABLES ;
②查看部分的会话变量
SHOW VARIABLES LIKE '%char%' ;
SHOW SESSION VARIABLES LIKE '%cgar%' ;
③查看指定的会话变量
SELECT @@tx_isolation ;
SELECT @@session.tx_isolation ;
④为某个指定的会话变量赋值(只针对当前会话框,不会跨框)
方式一:
SET @@session.tx_isolation = 'read-uncommitted' ;
SET @@tx_isolation = 'read-uncommitted' ;
SELECT @@session.tx_isolation
;#查看是否改变
方式二:
SET SESSION tx_isolation = 'read-uncommitted' ;
SELECT @@session.tx_isolation ;#查看是否改变
新版写法:
SELECT transaction_isolation = 'read-uncommitted' ;
二、自定义变量
说明:变量是用户自定义的,不是由系统的
使用步骤:
声明
赋值
使用(查看、比较、运算等)
1》用户变量
作用域:针对与当前会话(连接)有效,同于会话变量的作用域
应用在任何地方,也就是begin end里面或begin end外面
支持的赋值操作符: = 或 :=
①声明并初始化
SET @用户变量名 = 值;
SET @用户变化名:=值;
SELECT @用户变化名:=值;
②赋值(更新用户变量的值)
方式一:
SET @用户变量名 = 值;或
SET @用户变化名:=值;或
SELECT @用户变化名:=值;
方式二:通过SELECT INTO
SELECT 字段 INTO 变量
FROM 表;
案例:
声明并初始化
SET @name='john' ;
SET @name=100 ;#弱关系
SET @count =1 ;
赋值
SELECT COUNT(*) INTO @count
FROM employees ;
查看
SELECT @count ;
2》局部变量
作用域:仅仅在定义它的begin end中有效
应用在 begin end 中的第一句话!!!
①赋值
方式一:通过SET或SELECT
SET 局部变量名=值;或
SET 局部变量名:=值;或
SELECT @局部变量名:=值;
方式二:通过SELECT INTO
SELECT 字段 INTO 局部变量名
FROM 表;
3》使用
SELECT 局部变量 ;
无 | 作用域 | 定义和的位置 | 语法 |
---|---|---|---|
用户变量 | 当前会话 | 会话中的任何地方 | 必须加@符号,不用限定类型 |
局部变量 | BEGIN END中 | 只能在BEGIN END中,且为第一句话 | 一般不用加@符号,需要限定类型 |
案例:声明两个变量并赋初始值,求和,并打印
1、用户变量
SET @m =1;
SET @n = 2;
SET @sum = @m + @n;
SELECT @sum ;
2、局部变量
DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 2;
DECLARE SUM INT;
SET SUM = m + n;
SELECT SUM;#语法错误
存储过程和函数
存储过程和函数:类似于Java中的方法
好处:
1、提高代码的重用性
2、简化操作
存储过程
含义:一组预先编译好的SQL语句的合集,理解成批处理语句
1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的链接次数,提高了效率
一、创建语法
CREATE PROCEDURE 储存过程名(参数列表)
BEGIN
存储过程体(一组合法的SQL语句)
END
注意:
1、参数列表包含三部分
参数模式 参数名 参数类型
举例:
IN stuname VARCHAR(20)
参数模式:
IN#进 该参数可以作为输入,也就是该参数需要调用方传入值
OUT#出 该参数可以作为输出,也就是该参数可以作为返回值
INOUT#既进又出 该参数既可以作为输入又可以作为输出,也就是该参数既需要传入值,又可以返回值
2、如果存储过程体仅仅只有一句话,BEGIN END可以省略
存储过程体的每条SQL语句的结尾要求必须加分号 。
存储过程的结尾可以使用 DELIMITER 重新设置
语法:
DELIMITER 结束标记
例:DELIMITER &
二、调用语法(在命令窗户执行)
CALL 存储过程名(实参列表);
1、空参列表(在命令窗户执行)【插入功能的实现】
案例:插入到admin表中五条记录
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp1()
BEGIN
INSERT INTO admin(username
,password
)
VALUES('john','0000'),('lily','0000'),('timi','0000'),('rose','0000'),('tom','0000');
END $调用:CALL MySQL() $
查看: select * from admin$
2、创建带in模式参数的存储过程
案例1:创建存储过程实现 根据女神名,查询对应的男神信息
DELIMITER $ #设置结束标记
创建:
CREATE PROCEDURE myp2(IN beautyname VARCHAR(20))
BEGIN
SELECT bo.*
FROM boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
WHERE b.name = beautyname
END $
案例2:创建存储过程实现传入用户名和密码,插入到admin表中去
DELIMITER $ #设置结束标记
创建表:
CREATE PROCEDURE test_prol(IN username VARCHAR(20),IN loginpwd VARCHAR(20))
BEGIN
INSERT INTO admin(admin.`username`,PASSWORD)
VALUES(username,loginpwd);
END $
调用:
CALL test_prol('admin','0000')$
查看:
SELECT * FROM admin$
调用:
CALL myp2('小昭')$
案例2:创建存储过程实现,用户是否登陆成功
1、
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp3(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
DECLARE result VARCHAR(20) DEFAULT ' ';#声明并初始化
SELECT COUNT(*) INTO result#赋值
FROM admin
WHERE admin.`username` = username
AND admin.`password` = PASSWORD;
SELECT result;#使用
END $
调用:
CALL myp3('张飞','8888')$
2、
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp4(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
DECLARE result INT DEFAULT 0;#声明并初始化
SELECT COUNT(*) INTO result#赋值
FROM admin
WHERE admin.`username` = username
AND admin.`password` = PASSWORD;
SELECT IF(result>0,'成功','失败');#使用
END $
调用:
CALL myp4('张飞','8888')$
3、创建带out模式的存储过程
案例1:根据女神名,返回对应的男神名
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp5(IN beautyname VARCHAR(20),OUT boyname VARCHAR(20))
BEGIN
SELECT bo.boyname INTO boyname#赋值
FROM boys AS bo
INNER JOIN beauty AS b
ON bo.id = b.boyfriend_id
WHERE b.name = beautyname;
SET @bName$
CALL myp5('小昭',@bName)$ #调用
SELECT @bName$ #查看
案例2:根据女神名,返回对应的男神名和男神魅力值(多个out)
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp6(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP INT)
BEGIN
SELECT bo.boyName ,bo.userCP INTO boyName,userCP
FROM boys AS bo
INNER JOIN beauty AS b ON bo.id = b.boyfriend_id
WHERE b.name = beautyName;
END $
调用:
CALL myp6('小昭',@bName,@usercp)$
查看:
SELECT @bName,@usercp$
4、创建带inout模式参数的储存过程
案例1:传入a和b两个值,最终a和b都翻倍并返回
DELIMITER $ #设置结束标记
CREATE PROCEDURE myp7(INOUT a INT,INOUT b INT)
BEGIN
SET a = a*2;
SET b = b*2;
END $
调用:
SET @m = 10$
SET @n = 20$
CALL myp7(@m,@n)$
查看:
SELECT @m,@n$
例题3:创建储存过程或函数实现传入两个女神生日,返回大小
DELIMITER $ #设置结束标记
CREATE PROCEDURE test_pro3(IN birth1 DATETIME,IN birth2 DATETIME,OUT result INT)
BEGIN
SELECT DATEDIFF(birth1,birth2) INTO result;
END $
调用:
CALL test_pro3('2002-2-24',NOW(),@result)$
查看:
SELECT @result$
例题4:创建存储过程或函数实现传入女神名称,返回:女神 and 男神 格式的字符串
CREATE PROCEDURE test_pro5(IN beautyName VARCHAR(20),OUT str VARCHAR(50))
BEGIN
SELECT CONCAT(beautyName,' and ',IFNULL(boyName,'null')) INTO str
FROM boys AS bo
RIGHT JOIN beauty AS b ON b.boyfriend_id = bo.id
WHERE b.name = beautyName;
END $
CALL test_pro5('柳岩',@str)$
SELECT @str $
例题5:创建存储过程或函数,根据传入的条目和起始索引,查询beauty表的记录
CREATE PROCEDURE test_pro6(IN startindex INT ,IN size INT)
BEGIN
SELECT * FROM beauty LIMIT startindex,size;
END$
CALL test_pro6(3,5)$
三、删除存储过程
语法:drop procedure 存储过程名
一次只支持删除一个存储过程
DROP PROCEDURE p1;
四、查看存储过程的信息
DESC myp2;错误写法
SHOW CREATE PROCEDURE myp2;正确写法
函数
含义:一组预先编译好的SQL语句的合集,理解成批处理语句
1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的链接次数,提高了效率
区别:
存储过程:可以有0个返回值,也可以有多个返回,适合做批量插入,批量更新
函数:有且仅有1个返回,适合做处理数据后返回一个结果
一、创建语法
CERATE FUNCTION 函数名(参数列表) returns 返回类型
begin
函数体
end
注意:
1.参数列表 包含两部分
参数名 参数类型
2.函数体:肯定会有return语句,如果没有报错
如果return语句没有放在函数体的最后也不报错,但不建议
3.函数体中仅有一句话,则可以省略begin end
4.使用1delimiter语句设置结束标志
二、调用语法
SELECT 函数名(实参列表)
----------案例显示-----------
1.无参有返回
案例:返回公司的员工个数
DELIMITER $ #设置结束标记
CREATE FUNCTION myf1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;#定义局部变量
SELECT COUNT(*) INTO c#赋值
FROM `employees`;
RETURN c;
END $
SELECT mf1()$
2.有参有返回
案例1:根据员工名,返回他的员工名
DELIMITER $ #设置结束标记
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal = 0;#定义用户变量
SELECT salary INTO @sal #赋值
FROM employees
WHERE last_name = empName;
RETURN @sal;
END $
SELECT myf2('kochhar') $
案例2:根据部门名,返回该部门的平均工资
DELIMITER $ #设置结束标记
CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
DECLARE sal DOUBLE;
SELECT AVG(salary) INTO sal
FROM `employees` AS e
JOIN `departments` AS d
ON e.`department_id` = d.`department_id`
WHERE deptName = d.`department_name` ;
RETURN sal ;
END $
SELECT myf3('it') $
三、查看函数
SHOW CREATE FUNCTION myf3;
四、删除函数
DROP FUNCTION myf3;
案例
1、创建函数,实现传入两个float,返回两者之和
DELIMITER $ #设置结束标记
CREATE FUNCTION test_fun1(num1 FLOAT,num2 FLOAT) RETURNS FLOAT
BEGIN
DECLARE SUM FLOAT DEFAULT 0;
SET SUM = num1+num2;
RETURN SUM ;
END $
SELECT test_fun1(1,2)$
流程控制结构
循序结构:程序从上往下依次执行
分支结构:程序从两条或多条路径中选一条去执行
循环结构:程序在满足一定条件的基础上,重复执行一段代码
一、分支函数
1、if函数
功能:实现简单的双分支
语法:
if(表达式1,表达式2,表达式3)
执行循序:
如果表达式1成立,则if函数返回表达式2的值,否者返回表达式3的值
应用:任何地方
2、case结构
1.case函数的使用一:类似于Java中switch语句,一般用于实现等值判断
mysql中case语句的概念及其语法:
case 变量|表达式|字段
when 要判断的值1 then 要返回的值或语句1 ;
when要判断的值2 then 要返回的值或语句2 ;
....
else 要显示的值或语句n;
end case;
案例:查询员工的工资
要求:
部门号 = 30, 显示的工资为1.1倍
部门号 = 40, 显示的工资为1.2倍
部门号 = 50, 显示的工资为1.3倍
其他部门,显示原工资
SELECT `salary`,`department_id`,
CASE `department_id`
WHEN 30 THEN `salary` * 1.1
WHEN 40 THEN `salary` * 1.2
WHEN 50 THEN `salary` * 1.3
ELSE `salary`
END AS 新工资
FROM `employees` ;
2。case 函数的使用二:类似于Java中 多重if,一般用于实现区间判断
mysql中
case
when 常量1 then 要显示的值或语句1 ;
when常量2 then 要显示的值或语句2 ;
....
else 要显示的值或语句n;
end case;
案例:查询员工的工资
要求:
如果工资>20000,显示A级别
如果工资>20000,显示A级别
如果工资>20000,显示A级别
否则,显示D级别
SELECT `salary`,`department_id`,
CASE
WHEN `salary`>20000 THEN 'A'
WHEN `salary`>15000 THEN 'B'
WHEN `salary`>10000 THEN 'C'
ELSE 'D'
END AS 工资级别
特点:
①
可以作为表达式,嵌套在其它语句中使用,可以放在任何地方,BEHIN END中或BEGIN END的外面
可以作为独立的语句去使用,只能放在BEGIN END中
②
如果when中的值满足或条件满足,则执行对应的then后面的语句,并且结束case
如果不满足,则执行else中的语句或值
③
else可以省略,如果else省略了,并且所有when条件都不满足,则返回null
------------案例-------------
创建存储过程,根据传入的成绩,来显示等级,比如传入的成绩:90-100,显示A,80-90,显示B,60-80,显示C,否则显示D
DELIMITER $ #设置结束标记
CREATE PROCEDURE test_case(IN score INT)
BEGIN
CASE
WHEN score >= 90 AND score <= 100 THEN SELECT 'A';
WHEN score >= 80 THEN SELECT 'B';
WHEN score >= 60 THEN SELECT 'C';
ELSE SELECT 'D';
END CASE;
END $
CALL test_case(95) $
3、if函数
功能:实现多重分支
语法:
if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
【else 语句n;】
else if;
应用在begin end中
案例1:根据传入的成绩,来显示等级,比如传入的成绩:90-100,返回A,80-90,返回B,60-80,返回C,否则返回D
DELIMITER $ #设置结束标记
CREATE FUNCTION test_if(score INT) RETURNS CHAR
BEGIN
IF score >= 90 AND score <= 100 THEN RETURN 'A';
ELSEIF score >= 80 THEN RETURN 'B';
ELSEIF score >= 60 THEN RETURN 'C';
ELSE RETURN 'D';
END IF;
END $
SELECT test_if(86)$
二、循环结构
分类:
while、loop、repeat1
循环控制:
iterate类似于 continue, 继续,结束本次循环,继续下一次
leave 类似于 break,跳出,结束当前所在的循环
1、while
语法:
【标签:】while 循环条件 do
循环体;
end while【标签】;
2、loop
语法:
【标签】loop
循环体;
end loop【标签】;
可以用来模拟简单的死循环
3、repeat
语法:
【标签】repeat
循环体;
until 结束循环的条件
end repeat【标签】;
------案例--------
1、批量插入,根据次数插入到admin表中多条记录
CREATE PROCEDURE pro_while1(IN insertcount INT)
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<= insertcount DO
INSERT INTO admin (username,PASSWORD) VALUES(CONCAT('Rose',i),'666');
SET i = i +1;
END WHILE;
END $
CALL pro_while1(100)$
SELECT * FROM admin$
2、批量插入,根据次数插入到admin表中多条记录,如果次数大于20则停止
TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
CREATE PROCEDURE test_while1(IN insertcount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a : WHILE i <= insertcount DO
INSERT INTO admin (username,`PASSWORD`) VALUES(CONCAT('xiaohua',i),'0000');
IF i >=20 THEN LEAVE a;
END IF;
SET i = i+1;
END WHILE a;
END$
CALL test_while1(100)$
3、批量插入,根据次数插入到admin表中多条记录,只插入偶数次
TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
CREATE PROCEDURE test_while1(IN insertcount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a : WHILE i <= insertcount DO
SET i = i+1;
IF MOD(i,2)!=0 THEN ITERATE a;
END IF;
INSERT INTO admin (username,`PASSWORD`) VALUES(CONCAT('xiaohua',i),'0000');
END WHILE a;
END$
CALL test_while1(100)$
--------流程控制经典案例-----------
一、已知表stringcontent
其中字段:
id 自增长
content varchar(20)
向该表插入指定个数的随机的字符串
DROP TABLE IF EXISTS stringcontent ;
CREATE TABLE stringcontent(
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(20)
) ;
DELIMITER $
CREATE PROCEDURE test_randstr_insert(IN insertcount INT)
BEGIN
DECLARE i INT DEFAULT DEFAULT 1:#定义一个循环变量i,表示插入次数
DECLARE str VARCHAR(26) DEFAULT 'abcdefghigklmopqrstuvwxyz' ;
DECLARE startindex INT DEFAULT 1;#代表起始索引
DECLARE len INT DEFAULT 1;#代表截取的字符的长度
WHILE i <= insertcount DO
SET len = FLOOR(RAND()*(20-startindex+1)+1);#产生一个随机的整数,代表 截取长度,1-(26——startindex +1)
SET startindex = FLOOR(RAND()*26 +1) ;#产生一个随机的整数,代表起始索引1-26
INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startindex,len)) ;
SET i = i+1 ;
END WHILE ;
END $
CALL test_randstr_insert(10)$
SELECT * FROM stringcontent$