SQL存储过程、存储函数

概念:

存储过程和函数:

存储过程和函数是事先经过编译并存储在数据库中的一SQL语句的集合

存储过程和函数的好处:

  1. 存储过程和函数可以重复使用,减轻开发人员的工作量。类似于java中方法可以多次调用
  2. 减少网络流量,存储过程和函数位于服务器上,调用的时候只需要传递名称和参数即可
  3. 减少数据在数据库和应用服务器之间的传输,可以提高数据处理的效率
  4. 将一些业务逻辑在数据库层面来实现,可以减少代码层面的业务处理

存储过程和函数的区别:

  1. 函数必须有返回值
  2. 存储过程没有返回值

存储过程:

语法:
/*DELIMITER该关键字用来声明sql语句的分隔符,告诉MySQL该段命令已经结束!sql语句默认的分隔符是分号,但是有的时候我们需要一条功能sql语句中包含分号,但是并不作为结束标识。这个时候就可以使用DELIMITER来指定分隔符了!
*/
-- 修改分隔符为$
DELIMITER $  -- 标准语法
CREATE PROCEDURE 存储过程名称(参数...)
BEGINsql语句;
END$-- 修改分隔符为分号
DELIMITER ;-- 存储过程从这里结束-- 调用存储过程
CALL 存储过程名称(实际参数);

数据准备:

-- 创建学生表
CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,	-- 学生idNAME VARCHAR(20),					-- 学生姓名age INT,							-- 学生年龄gender VARCHAR(5),					-- 学生性别score INT                           -- 学生成绩
);
-- 添加数据
INSERT INTO student VALUES (NULL,'张三',23,'男',95),(NULL,'李四',24,'男',98),
(NULL,'王五',25,'女',100),(NULL,'赵六',26,'女',90);-- 按照性别进行分组,查询每组学生的总成绩。按照总成绩的升序排序
SELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC;
创建存储过程:
-- 创建存储过程
DELIMITER $
CREATE PROCEDURE stu_group()
BEGINSELECT gender,SUM(score) getSum FROM student GROUP BY gender  ORDER BY getSum ASC;
END$
DELIMITER ;-- 调用存储过程
CALL stu_group();
存储过程的查看和删除:
-- 查询数据库中所有的存储过程 标准语法
show procedure status;-- 查看创建时SQL语句
SHOW CREATE PROCEDURE stu_group;-- 删除存储过程标准语法
DROP PROCEDURE [IF EXISTS] 存储过程名称;
DROP PROCEDURE IF EXISTS stu_group;
变量的使用:

定义变量:

-- 标准语法
DECLARE 变量名 数据类型 [DEFAULT 默认值];
-- 注意: DECLARE定义的是局部变量,只能用在BEGIN END范围之内DELIMITER $
CREATE PROCEDURE pro_test1 ()
BEGINDECLARE num INT DEFAULT 10;-- 定义变量SELECT num;-- 使用变量
END$
DELIMITER;CALL pro_test1 ();-- 调用

变量赋值方式1:

-- 标准语法
SET 变量名 = 变量值;-- 定义字符串类型变量,并赋值
DELIMITER $CREATE PROCEDURE pro_test2()
BEGINDECLARE NAME VARCHAR(10);   -- 定义变量SET NAME = '存储过程';       -- 为变量赋值SELECT NAME;                -- 查询变量
END$DELIMITER ;-- 调用pro_test2存储过程
CALL pro_test2();

变量赋值方式2:

-- 标准语法
SELECT 列名 INTO 变量名 FROM 表名 [WHERE 条件];-- 定义两个int变量,用于存储男女同学的总分数
DELIMITER $CREATE PROCEDURE pro_test3()
BEGINDECLARE men,women INT;  -- 定义变量SELECT SUM(score) INTO men FROM student WHERE gender='男';    -- 计算男同学总分数赋值给menSELECT SUM(score) INTO women FROM student WHERE gender='女';  -- 计算女同学总分数赋值给womenSELECT men,women;           -- 查询变量
END$DELIMITER ;-- 调用pro_test3存储过程
CALL pro_test3();
if语句的使用:
-- 标准语法
IF 判断条件1 THEN 执行的sql语句1;
[ELSEIF 判断条件2 THEN 执行的sql语句2;]
...
[ELSE 执行的sql语句n;]
END IF;/*定义一个int变量,用于存储班级总成绩定义一个varchar变量,用于存储分数描述根据总成绩判断:380分及以上    学习优秀320 ~ 380     学习不错320以下       学习一般
*/
DELIMITER $CREATE PROCEDURE pro_test4()
BEGIN-- 定义总分数变量DECLARE total INT;-- 定义分数描述变量DECLARE description VARCHAR(10);-- 为总分数变量赋值SELECT SUM(score) INTO total FROM student;-- 判断总分数IF total >= 380 THEN SET description = '学习优秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '学习不错';ELSE SET description = '学习一般';END IF;-- 查询总成绩和描述信息SELECT total,description;
END$DELIMITER ;-- 调用pro_test4存储过程
CALL pro_test4();
参数的传递:

@变量名: 这种变量要在变量名称前面加上“@”符号,叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。
@@变量名: 这种在变量前加上 “@@” 符号, 叫做系统变量

语法:

DELIMITER $-- 标准语法
CREATE PROCEDURE 存储过程名称([IN|OUT|INOUT] 参数名 数据类型)
BEGIN执行的sql语句;
END$
/*IN:代表输入参数,需要由调用者传递实际数据。默认的OUT:代表输出参数,该参数可以作为返回值INOUT:代表既可以作为输入参数,也可以作为输出参数
*/
DELIMITER ;

输入参数IN:

/*输入总成绩变量,代表学生总成绩输出分数描述变量,代表学生总成绩的描述根据总成绩判断:380分及以上  学习优秀320 ~ 380    学习不错320以下      学习一般
*/
DELIMITER $CREATE PROCEDURE pro_test6(IN total INT,OUT description VARCHAR(10))
BEGIN-- 判断总分数IF total >= 380 THEN SET description = '学习优秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '学习不错';ELSE SET description = '学习一般';END IF;
END$DELIMITER ;-- 调用pro_test6存储过程
CALL pro_test6(310,@description);-- 查询总成绩描述
SELECT @description;

输出参数:

/*输入总成绩变量,代表学生总成绩输出分数描述变量,代表学生总成绩的描述根据总成绩判断:380分及以上  学习优秀320 ~ 380    学习不错320以下      学习一般
*/
DELIMITER $CREATE PROCEDURE pro_test6(IN total INT,OUT description VARCHAR(10))
BEGIN-- 判断总分数IF total >= 380 THEN SET description = '学习优秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '学习不错';ELSE SET description = '学习一般';END IF;
END$DELIMITER ;-- 调用pro_test6存储过程
CALL pro_test6(310,@description);-- 查询总成绩描述
SELECT @description;
case语句:

语法1:

-- 标准语法
CASE 表达式
WHEN1 THEN 执行sql语句1;
[WHEN2 THEN 执行sql语句2;]
...
[ELSE 执行sql语句n;]
END CASE;

语法2:

-- 标准语法
CASE
WHEN 判断条件1 THEN 执行sql语句1;
[WHEN 判断条件2 THEN 执行sql语句2;]
...
[ELSE 执行sql语句n;]
END CASE;

演示:

/*输入总成绩变量,代表学生总成绩定义一个varchar变量,用于存储分数描述根据总成绩判断:380分及以上  学习优秀320 ~ 380    学习不错320以下      学习一般
*/
DELIMITER $CREATE PROCEDURE pro_test7(IN total INT)
BEGIN-- 定义变量DECLARE description VARCHAR(10);-- 使用case判断CASEWHEN total >= 380 THENSET description = '学习优秀';WHEN total >= 320 AND total < 380 THENSET description = '学习不错';ELSE SET description = '学习一般';END CASE;-- 查询分数描述信息SELECT description;
END$DELIMITER ;-- 调用pro_test7存储过程
CALL pro_test7(390);
CALL pro_test7((SELECT SUM(score) FROM student));
while循环:

语法:

-- 标准语法
初始化语句;
WHILE 条件判断语句 DO循环体语句;条件控制语句;
END WHILE;

演示:

/*计算1~100之间的偶数和
*/
DELIMITER $CREATE PROCEDURE pro_test8()
BEGIN-- 定义求和变量DECLARE result INT DEFAULT 0;-- 定义初始化变量DECLARE num INT DEFAULT 1;-- while循环WHILE num <= 100 DO-- 偶数判断IF num%2=0 THENSET result = result + num; -- 累加END IF;-- 让num+1SET num = num + 1;         END WHILE;-- 查询求和结果SELECT result;
END$DELIMITER ;-- 调用pro_test8存储过程
CALL pro_test8();
repeat循环:

repeat循环是条件满足则停止。while循环是条件满足则执行

语法:

-- 标准语法
初始化语句;
REPEAT循环体语句;条件控制语句;UNTIL 条件判断语句
END REPEAT;-- 注意:repeat循环是条件满足则停止。while循环是条件满足则执行
-- UNTIL只能写在最下面

演示:

/*计算1~10之间的和
*/
DELIMITER $CREATE PROCEDURE pro_test9()
BEGIN-- 定义求和变量DECLARE result INT DEFAULT 0;-- 定义初始化变量DECLARE num INT DEFAULT 1;-- repeat循环REPEAT-- 累加SET result = result + num;-- 让num+1SET num = num + 1;-- 停止循环UNTIL num>10END REPEAT;-- 查询求和结果SELECT result;
END$DELIMITER ;-- 调用pro_test9存储过程
CALL pro_test9();
loop循环:

loop可以实现简单的循环,但是退出循环需要使用其他的语句来定义。可以使用leave语句完成!
如果不加退出循环的语句,那么就变成了死循环

语法:

-- 标准语法
初始化语句;
[循环名称:] LOOP条件判断语句[LEAVE 循环名称;]循环体语句;条件控制语句;
END LOOP 循环名称;-- 注意:loop可以实现简单的循环,但是退出循环需要使用其他的语句来定义。我们可以使用leave语句完成!
--      [循环名称:] LOOP循环名称要加 如果不加退出循环的语句,那么就变成了死循环。
/*计算1~10之间的和
*/
DELIMITER $CREATE PROCEDURE pro_test10()
BEGIN-- 定义求和变量DECLARE result INT DEFAULT 0;-- 定义初始化变量DECLARE num INT DEFAULT 1;-- loop循环l:LOOP-- 条件成立,停止循环IF num > 10 THENLEAVE l;END IF;-- 累加SET result = result + num;-- 让num+1SET num = num + 1;END LOOP l;-- 查询求和结果SELECT result;
END$DELIMITER ;-- 调用pro_test10存储过程
CALL pro_test10();
游标:
  • 游标可以遍历返回的多行结果,每次拿到一整行数据
  • 在存储过程和函数中可以使用游标对结果集进行循环的处理
  • 简单来说游标就类似于集合的迭代器遍历
  • MySQL中的游标只能用在存储过程和函数中
含义语法
创建游标DECLARE 游标名称 CURSOR FOR 查询sql语句;
打开游标OPEN 游标名称;
使用游标获取数据FETCH 游标名称 INTO 变量名1,变量名2,…;
关闭游标CLOSE 游标名称;

演示:

-- 创建stu_score表
CREATE TABLE stu_score(id INT PRIMARY KEY AUTO_INCREMENT,score INT
);/*将student表中所有的成绩保存到stu_score表中
*/
DELIMITER $CREATE PROCEDURE pro_test11()
BEGIN-- 定义成绩变量DECLARE s_score INT;-- 创建游标,查询所有学生成绩数据DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 开启游标OPEN stu_result;-- 使用游标,遍历结果,拿到第1行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第2行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第3行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第4行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 关闭游标CLOSE stu_result;
END$DELIMITER ;-- 调用pro_test11存储过程
CALL pro_test11();-- 查询stu_score表
SELECT * FROM stu_score;-- ===========================================================
/*出现的问题:student表中一共有4条数据,我们在游标遍历了4次,没有问题!但是在游标中多遍历几次呢?就会出现问题
*/
DELIMITER $CREATE PROCEDURE pro_test11()
BEGIN-- 定义成绩变量DECLARE s_score INT;-- 创建游标,查询所有学生成绩数据DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 开启游标OPEN stu_result;-- 使用游标,遍历结果,拿到第1行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第2行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第3行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第4行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游标,遍历结果,拿到第5行数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 关闭游标CLOSE stu_result;
END$DELIMITER ;-- 调用pro_test11存储过程
CALL pro_test11();-- 查询stu_score表,虽然数据正确,但是在执行存储过程时会报错
SELECT * FROM stu_score;

游标的优化使用(配合循环使用)

/*当游标结束后,会触发游标结束事件。我们可以通过这一特性来完成循环操作加标记思想:1.定义一个变量,默认值为0(意味着有数据)2.当游标结束后,将变量值改为1(意味着没有数据了)
*/
-- 1.定义一个变量,默认值为0(意味着有数据)
DECLARE flag INT DEFAULT 0;
-- 2.当游标结束后,将变量值改为1(意味着没有数据了)
DECLARE EXIT HANDLER FOR NOT FOUND SET flag = 1;/*将student表中所有的成绩保存到stu_score表中
*/
DELIMITER $CREATE PROCEDURE pro_test12()
BEGIN-- 定义成绩变量DECLARE s_score INT;-- 定义标记变量DECLARE flag INT DEFAULT 0;-- 创建游标,查询所有学生成绩数据DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 游标结束后,将标记变量改为1,判断,如果没有数据就把flag改为1DECLARE EXIT HANDLER FOR NOT FOUND SET flag = 1;-- 开启游标OPEN stu_result;-- 循环使用游标REPEAT-- 使用游标,遍历结果,拿到数据FETCH stu_result INTO s_score;-- 将数据保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);UNTIL flag=1END REPEAT;-- 关闭游标CLOSE stu_result;
END$DELIMITER ;-- 调用pro_test12存储过程
CALL pro_test12();-- 查询stu_score表
SELECT * FROM stu_score;

存储函数:

存储函数和存储过程是非常相似的。存储函数可以做的事情,存储过程也可以做到!
存储函数有返回值,存储过程没有返回值(参数的out其实也相当于是返回数据了)

创建存储函数

DELIMITER $-- 标准语法
CREATE FUNCTION 函数名称([参数 数据类型])
RETURNS 返回值类型
BEGIN执行的sql语句;RETURN 结果;
END$DELIMITER ;

调用存储函数

-- 标准语法
SELECT 函数名称(实际参数);

删除存储函数

-- 标准语法
DROP FUNCTION 函数名称;

演示:

/*定义存储函数,获取学生表中成绩大于95分的学生数量
*/
DELIMITER $CREATE FUNCTION fun_test1()
RETURNS INT
BEGIN-- 定义统计变量DECLARE result INT;-- 查询成绩大于95分的学生数量,给统计变量赋值SELECT COUNT(*) INTO result FROM student WHERE score > 95;-- 返回统计结果RETURN result;
END$DELIMITER ;-- 调用fun_test1存储函数
SELECT fun_test1();-- 删除存储函数
DROP FUNCTION fun_test1;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

meta http-equiv=X-UA-Compatible content=IE=edge,chrome=1 /

X-UA-Compatible是针对IE8新加的一个设置&#xff0c;对于IE8之外的浏览器是不识别的&#xff0c;这个区别与content"IE7"在无论页面是否包含<!DOCTYPE>指令&#xff0c;都像是使用了 Windows Internet Explorer 7的标准模式。而content"IEEmulateIE7&quo…

错误页跳转

错误页跳转的语法 <%page errorPage"出现错误跳转页面"%> <%page isErrorPage"true/false%>跳转到此页面进行处理错误 代码如下&#xff1a; <%page language"java" contentType"text/html" pageEncoding"GBK"%&g…

yum 安装mysql数据库

1、先查看是否有安装mysql&#xff0c;有的话通过yum remove mysql先卸载掉&#xff0c;卸载完成后执行 yum install -y mysql-server mysql mysql-deve 2、启动mysql服务 service mysqld start  //也可以通过/etc/init.d/mysqld start启动 3、设置为开机自启动 chkconfig m…

修改项目名称之后,访问不到项目的问题

转载于:https://www.cnblogs.com/Joke-Jay/p/7190187.html

Mysql锁机制详解

Mysql锁&#xff1a; 在多线程当中如果想保证数据的准确性是如何实现的呢&#xff1f;没错&#xff0c;通过同步实现。同步就相当于是加锁。加了锁以后有什么好处呢&#xff1f;当一个线程真正在操作数据的时候&#xff0c;其他线程只能等待。当一个线程执行完毕后&#xff0c;…

stanford-parser for C#

在项目里用到C#对英文句子进行词性标注。比較成熟的英文词性标注软件是stanford-parser。它个C#版本号&#xff0c;也是借助于IKVM完毕JAVA-C#的转换。详细配置过程例如以下&#xff1a; 1、下载stanford-parser的jar包 http://nlp.stanford.edu/software/lex-parser.shtml 2…

保姆级Mycat操作详解

Mycat环境搭建&#xff1a; 下载&#xff1a;http://dl.mycat.org.cn/2.0/ 上传到虚拟机并解压 tar -zxvf mycat.tar.gz cd mycat ll授权&#xff1a;设置mycat权限 chmod -R 777 mycat环境变量&#xff1a;配置环境变量 # 编辑文件 vi /etc/profile # 添加内容&#xff…

百度陆奇最新内部演讲:如何成为一个优秀的工程师?

作者&#xff5c;陆奇 来源&#xff5c;百度 Family 一位工程师&#xff0c;如何才能称得上优秀&#xff1f;除了写得一手好 Code&#xff0c;什么样的工作态度和方法才是一个优秀工程师的必备&#xff1f;7 月 11 日&#xff0c;陆奇出席百度内部 Engineering Leadership Talk…

最常见的水平拆分规则

1.枚举法&#xff1a; <tableRule name"sharding-by-intfile"><rule><columns>user_id</columns><algorithm>hash-int</algorithm></rule></tableRule> <function name"hash-int" class"io.myca…

TestNG-详解preserve-order的作用与测试case的执行顺序

在TestNG xml配置文件中&#xff0c;关于<test>的配置里面&#xff0c;有一个属性叫preserve-order&#xff0c;一开始以为这个属性可以用来控制测试case(那些被Test注解标注的方法)的执行顺序&#xff0c;后来测试了一把&#xff0c;发现没有这种效果&#xff0c;最后上…

数据库连接JDBC

JDBC&#xff1a; JDBC&#xff08;Java DataBase Connectivity,java数据库连接&#xff09;是一种用于执行SQL语句的Java API&#xff0c;可以为多种关系型数据库提供统一访问&#xff0c;它是由一组用Java语言编写的类和接口组成的。其实就是java官方提供的一套规范(接口)。用…

【bzoj】 1412: [ZJOI2009]狼和羊的故事

Description “狼爱上羊啊爱的疯狂&#xff0c;谁让他们真爱了一场&#xff1b;狼爱上羊啊并不荒唐&#xff0c;他们说有爱就有方向&#xff0e;&#xff0e;&#xff0e;&#xff0e;&#xff0e;&#xff0e;” Orez听到这首歌&#xff0c;心想&#xff1a;狼和羊如此和谐&am…

计算机基础--网络

互联网协议 互联网协议的功能&#xff1a;定义计算机如何接入internet&#xff0c;以及接入internet的计算机通信的标准。 互联网协议按照功能不同分为osi七层或者tcp/ip五层或tcp/ip四层 每层常见物理设备 因为学习python编程只需要了解tcp/ip五层模型&#xff0c;所以我们只需…

万字详解数据库连接池

数据库连接池的概念 数据库连接是一种关键的、有限的、昂贵的资源&#xff0c;这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性&#xff0c;影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。数据库连…

Win Linux 双系统安装指南

双系统安装指南 环境说明 硬件&#xff1a;一块240G NVMe&#xff0c;一块240G SSD&#xff0c;一块2T的HDD。 系统&#xff1a;Linux Mint 18.2&#xff0c;Windows 10 Enterprise Version 1703 Update June 2017 分配&#xff1a;由于工作原因&#xff0c;我的主系统为Linux …

JDBC自定义框架

自定义JDBC框架&#xff1a; 定义必要的信息、获取数据库的连接、释放资源都是重复的代码&#xff0c;在操作JDBC时通常都是执行SQL语句就可以了&#xff0c;所以需要抽取出来一个模板类来封装一些方法&#xff08;Update、Query&#xff09;&#xff0c;专门执行增删改查的SQL…

SpingMVC 执行的流程

一&#xff1a;SpringMVC的开发步骤 ①&#xff1a;在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求。 由于Web应用是基于请求/响应结构的应用&#xff0c;所以不管哪个MVC Web框架&#xff0c;都需要在web.xml中配置该框架的核心Servlet或Filter&#xff0c;这…

UI 07 _ 导航视图控制器 与 属性传值

首先, 先创建三个VC. 完毕点击按钮, 进入下一页, 并可以返回. 要先把导航视图控制器创建出来. 在AppDelegate.m 文件里代码例如以下: #import "AppDelegate.h" #import "MainViewController.h" interface AppDelegate () endimplementation AppDelegate …

el表达式具体解释

引用内容百度百科(http://baike.baidu.com/view/1488964.htm) 參考百度百科&#xff0c;然后自己又加入了一部分自己感觉实用的东西&#xff0c;整理一下希望对大家有所帮助&#xff01;E L&#xff08;Expression Language&#xff09; 目的&#xff1a;为了使JSP写起来更加简…

MyBatis接口代理

MyBatis接口代理&#xff1a; 采用 Mybatis 的代理开发方式实现 DAO 层的开发&#xff0c;这种方式是目前的主流方式。Mapper 接口开发方法只需要程序员编写Mapper 接口&#xff08;相当于Dao 接口&#xff09;&#xff0c;由Mybatis 框架根据接口定义创建接口的动态代理对象&a…