MySQL——存储过程
核心知识点:
1.什么存储过程?它都有哪些优点?
2.存储过程的语法和参数?
3.存储过程有哪些操作?
4.存储过程常用的控制语句?
一、存储过程概论
SQL语句需要先编译然后执行,而存储过程是一组为了完成特定功能的SQL语句集,
经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
存储过程是可编程的函数在数据库中创建并保存,可以由SQL语句和控制结构组成。
当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。
数据库中的存储过程可以看作是函数,就是对命令的封装,你可以多次调用它,并传递不同的参数。
存储过程是数据库的一个重要的功能,MySQL5.0以前并不支持存储过程,这使得MySQL在应用上大打折扣,
好在MySQL5.0开始支持存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。
虽然存储过程有时候很好用,但是千万不要滥用,因为这会给以后的程序开发带来意向不到的问题。
二、存储过程的优点
(1)增强SQL语言的功能和灵活性
存储过程可以用控制语句来编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
(2)标准组件式编程
存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。
而且数据库专业人士可以随时对存储过程进行修改,对应用程序源码毫无影响。
(3)较快的执行速度
存储过程要比批处理(同一个代码重复执行多次)的执行速度快很多,因为存储过程是预编译的。
在首次运行一个存储过程时,优化器对其进行分析优化,并且给出最终在系统表中的执行计划。
而批处理的SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。
(4)较少网络流量
针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的SQL语句被组织进存储进程,那么当在客户端计算机上调用该存储过程时,网络中传送的只是该调用该语句,从而大大减少网络流量并降低了网络负载。
(5)作为一种安全机制来充分利用
通过对执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
三、认识存储过程
现在我有一张表,其中有三个字段完全是空,需要填值。如果我一条一条的输入,每个字段值都需要一条SQL语句,感觉很麻烦,此时我们就可以使用存储过程,一次创建,多次使用。
#有三个字段需要填值,全部使用SQL语句很繁琐
mysql> select * from student_score;
-> //
+----+--------+-------+-------+--------+
| id | name | linux | mysql | python |
+----+--------+-------+-------+--------+
| 1 | 科比 | NULL | NULL | NULL |
| 2 | 毛线 | NULL | NULL | NULL |
| 3 | 黄鱼 | NULL | NULL | NULL |
| 4 | 子豪 | NULL | NULL | NULL |
| 5 | 星爷 | NULL | NULL | NULL |
| 6 | 代鹏 | NULL | NULL | NULL |
| 7 | 子栋 | NULL | NULL | NULL |
| 8 | 周攀 | NULL | NULL | NULL |
| 9 | 大爷 | NULL | NULL | NULL |
| 10 | 小鸟 | NULL | NULL | NULL |
+----+--------+-------+-------+--------+
10 rows in set (0.00 sec)
有三个字段需要填写
#存储过程
mysql> delimiter //
mysql> create procedure auto_add(in a int,in b int,in c int,in d int)
-> begin
-> update student_score set linux = a where id = d;
-> update student_score set mysql = b where id = d;
-> update student_score set python = c where id = d;
-> end;
-> //
Query OK, 0 rows affected (0.07 sec)
创建一个存储过程
mysql> call auto_add(45,67,56,2)//
Query OK, 1 row affected (0.09 sec) mysql> call auto_add(89,34,67,3)//
Query OK, 1 row affected (0.01 sec) mysql> call auto_add(45,78,90,4)//
Query OK, 1 row affected (0.07 sec) mysql> call auto_add(56,78,56,4)//
Query OK, 1 row affected (0.18 sec) mysql> call auto_add(56,90,78,5)//
Query OK, 1 row affected (0.06 sec) mysql> call auto_add(89,96,87,6)//
Query OK, 1 row affected (0.07 sec) mysql> call auto_add(67,76,45,7)//
Query OK, 1 row affected (0.01 sec) mysql> call auto_add(34,56,45,8)//
Query OK, 1 row affected (0.07 sec) mysql> call auto_add(56,54,60,9)//
Query OK, 1 row affected (0.06 sec) mysql> call auto_add(78,75,67,10)//
Query OK, 1 row affected (0.01 sec)
调用函数,填制
mysql> select * from student_score;
-> //
+----+--------+-------+-------+--------+
| id | name | linux | mysql | python |
+----+--------+-------+-------+--------+
| 1 | 科比 | 63 | 33 | 76 |
| 2 | 毛线 | 45 | 67 | 56 |
| 3 | 黄鱼 | 89 | 34 | 67 |
| 4 | 子豪 | 56 | 78 | 56 |
| 5 | 星爷 | 56 | 90 | 78 |
| 6 | 代鹏 | 89 | 96 | 87 |
| 7 | 子栋 | 67 | 76 | 45 |
| 8 | 周攀 | 34 | 56 | 45 |
| 9 | 大爷 | 56 | 54 | 60 |
| 10 | 小鸟 | 78 | 75 | 67 |
+----+--------+-------+-------+--------+
10 rows in set (0.00 sec)
查看最终的结果
由上面的例子可以看出,使用存储过程可以简化操作的过程。
补充:分隔符
为什么我使用双反斜杠?
MySQL默认以’“;”作为分隔符,如果没有声明分隔符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以事先要用“DELIMITER //”声明当前段分隔符,让编译器把两个’//‘之间的内容当作存储过程的代码。
四、存储过程的创建
语法:
CREATE PROCEDURE 过程名([IN|OUT|INOUT] 参数名 参数类型,[IN|OUT|INOUT] 参数名 参数类型....) BEGIN 操作 END
参数:
存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用’,‘分隔开。
MySQL存储过程的参数用在存储过程的定义,共有三种参数类型:IN、OUT、INOUT
(1)IN:参数的值必须在调用存储过程时指定,在存储过程或修改该参数的不能返回,为默认值
mysql> delimiter // #声明分隔符
mysql> create PROCEDURE in_param(IN p_in int) #创建存储过程
-> BEGIN #开始
-> SELECT p_in; #打印变量,类似于print
-> SET p_in = 2; #设置变量大小
-> SELECT p_in; #打印
-> END;
-> //
Query OK, 0 rows affected (0.00 sec) mysql> set @p_in = 1// #赋值参数
Query OK, 0 rows affected (0.00 sec) mysql> call in_param(@p_in); #执行存储过程
-> //
+------+
| p_in |
+------+
| 1 |
+------+
1 row in set (0.00 sec) +------+
| p_in |
+------+
| 2 |
+------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> select @p_in// #由于存储过程的中的值不能返回,所以没有改变变量的值
+-------+
| @p_in |
+-------+
| 1 |
+-------+
1 row in set (0.00 sec)
使用IN参数的过程讲解
(2)OUT:该值可在存储过程内部被改变,并可返回
mysql> CREATE PROCEDURE out_param(OUT p_out int)
-> BEGIN
-> SELECT p_out;
-> SET p_out = 2;
-> SELECT p_out;
-> END;
-> //
Query OK, 0 rows affected (0.00 sec) mysql> set @p_out = 1
-> //
Query OK, 0 rows affected (0.00 sec) mysql> CALL out_param(@p_out) //
+-------+
| p_out |
+-------+
| NULL |
+-------+
1 row in set (0.00 sec) #还没有值,而外面的值又没有传进来 +-------+
| p_out |
+-------+
| 2 |
+-------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> SELECT @p_out // #内部的值可以返回
+--------+
| @p_out |
+--------+
| 2 |
+--------+
1 row in set (0.00 sec)
使用OUT参数的过程讲解
(3)INOUT:调用时指定,并且可被改变和返回
mysql> CREATE PROCEDURE inout_param(INOUT p_inout int)
-> BEGIN
-> SELECT p_inout;
-> SET p_inout = 2;
-> SELECT p_inout;
-> END;
-> //
Query OK, 0 rows affected (0.00 sec) mysql> SET @p_inout = 1;
-> //
Query OK, 0 rows affected (0.00 sec) mysql> CALL inout_param(@p_inout) // #外面的值既可以传进来
+---------+
| p_inout |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec) +---------+
| p_inout |
+---------+
| 2 |
+---------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> SELECT @p_inout // #里面的值也能够返回
+----------+
| @p_inout |
+----------+
| 2 |
+----------+
1 row in set (0.00 sec)
使用INOUT参数的过程详解
五、存储过程的操作
1.存储过程的调用
用CALL和你过程名以及一个括号,括号里面根据需要,加入参数。
mysql> CALL out_param(@p_out) // #相当于程序中代码的执行
+-------+
| p_out |
+-------+
| NULL |
+-------+
1 row in set (0.00 sec) +-------+
| p_out |
+-------+
| 2 |
+-------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)
存储过程的调用
2.存储过程的查询
查询某一个库中有那些存储过程有多种方法
(1)SELECT name FROM mysql.proc WHERE db = '数据库名';
mysql> select name from mysql.proc where db = 'class_7' //
+-------------+
| name |
+-------------+
| auto_add |
| inout_param |
| in_param |
| out_param |
+-------------+
4 rows in set (0.00 sec)
只查询存储过程名
(2)SELECT routine_name FROM infomation_schema.routines WHERE routine_schema='数据库名';
mysql> select routine_name from information_schema.routines
-> where routine_schema = 'class_7' //
+--------------+
| routine_name |
+--------------+
| auto_add |
| inout_param |
| in_param |
| out_param |
+--------------+
4 rows in set (0.00 sec)
只查询存储过程的名字
(3)SHOW PROCEDURE STATUS WHERE db ='数据库名';
mysql> show procedure status where db = 'class_7' //
+---------+-------------+-----------+----------------+---------------------+---------------------+--------------------+
| Db | Name | Type | Definer | Modified |collation_connection | Database Collation |
+---------+-------------+-----------+----------------+---------------------+---------------------+--------------------+
| class_7 | auto_add | PROCEDURE | root@localhost | 2017-12-12 16:21:34 |utf8_general_ci | utf8_general_ci |
| class_7 | inout_param | PROCEDURE | root@localhost | 2017-12-12 18:59:33 |utf8_general_ci | utf8_general_ci |
| class_7 | in_param | PROCEDURE | root@localhost | 2017-12-12 18:48:34 |utf8_general_ci | utf8_general_ci |
| class_7 | out_param | PROCEDURE | root@localhost | 2017-12-12 18:53:44 |utf8_general_ci | utf8_general_ci |
+---------+-------------+-----------+----------------+---------------------+---------------------+--------------------+
4 rows in set (0.00 sec)
查询存储过程的详细信息
(4)SHOW CREATE PROCEDURE 数据库.存储过程名
mysql> show create procedure class_7.auto_add //
+-----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation |
+-----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| auto_add | | CREATE DEFINER=`root`@`localhost` PROCEDURE `auto_add`(in a int,in b int,in c int,in d int)
begin
update student_score set linux = a where id = d;
update student_score set mysql = b where id = d;
update student_score set python = c where id = d;
end | utf8 | utf8_general_ci | utf8_general_ci |
+-----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)
查询某一个具体的存储过程的详细信息
3.存储过程的删除
DROP PROCEDURE 存储过程名;
从MySQL上的表格中删除一个或多个存储过程。
还可以对存储过程进行修改,由于不常用,这里不做介绍。
六、存储过程的控制语句
1.变量作用域
内部变量在其作用域范围内享有更高的优先权,当执行到end时,内部变量消失。
在存储过程外部再也找不到这个内部变量,但是可以通过out参数或者将其值指派给会话变量来保存其值。
mysql> delimiter //
mysql> create procedure proc()
-> begin
-> declare x1 varchar(5) default 'outer';
-> begin
-> declare x1 varchar(5) default 'inner';
-> select x1;
-> end; #end结束的时候,x1 = inner不能再使用
-> select x1;
-> end;
-> //
Query OK, 0 rows affected (0.00 sec) mysql> CALL proc()
-> //
+-------+
| x1 |
+-------+
| inner |
+-------+
1 row in set (0.00 sec) +-------+
| x1 |
+-------+
| outer |
+-------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)
变量作用域过程讲解
2.if-then-else语句
mysql> delimiter //
mysql> create procedure proc3(IN par int)
-> begin
-> declare var int;
-> set var = par + 1;
-> if var = 0 THEN
-> insert into judge(state) values('空值');
-> end if; #结束这个判断
-> if par = 0 THEN
-> insert into judge(state) values('');
-> else
-> insert into judge(state) values('真值');
-> end if;
-> end; #与begin对照
-> //
Query OK, 0 rows affected (0.00 sec)
if-then-else过程解析
3.while循环
mysql> create proceduce proc6(inout n int)
-> begin
-> declare sum int default 0;
-> declare i int default 0;
-> while i <= n DO #do开始循环
-> set sum = sum + i;
-> set i = i + 1;
-> end while; #endwhile结束循环
-> select sum; #打印和
-> set n = sum; #传参,让外界可以接收这个值
-> end; #与begin一起表示过程体
-> //
mysql> set @n = 100; #外界用户变量必须以@开头
-> //
Query OK, 0 rows affected (0.00 sec) mysql> call proc10(@n)// #执行函数
+------+
| sum |
+------+
| 5050 |
+------+
1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> select @n // #打印变量值
+------+
| @n |
+------+
| 5050 |
+------+
1 row in set (0.00 sec)
while循环
其实,控制语句还有loop...end loop、repeat...end repeat、case-when-then-else等语句
MySQL——存储过程的更多相关文章
- MySQL存储过程(转)
一.MySQL 创建存储过程 "pr_add" 是个简单的 MySQL 存储过程,这个存储过程有两个 int 类型的输入参数 "a"."b" ...
- MySql存储过程
MySQL 存储过程 ```sql CREATE PROCEDURE myprocedure (IN para01 INTEGER) BEGIN DECLARE var01 CHAR(10); IF ...
- mysql存储过程和存储函数
mysql存储过程和存储函数 存数函数代码示例: DROP PROCEDURE IF EXISTS calc_ci_day_suc_rate; delimiter // CREATE FUNCTION ...
- mysql存储过程编写-入门案例-遁地龙卷风
(-1)写在前面 这篇文章只是简要的叙述了mysql存储过程编写的基本概念. 我使用的mysql版本是5.7.9-log. 参照<<深入浅出MySQL>>. (0) delim ...
- MySQL存储过程动态SQL语句的生成
用Mysql存储过程来完成动态SQL语句,使用存储过程有很好的执行效率: 现在有要求如下:根据输入的年份.国家.节假日类型查询一个节假日,我们可以使用一般的SQL语句嵌入到Java代码中,但是执行效率 ...
- MySQL 存储过程
MySQL 存储过程 存储过程是通过给定的语法格式编写自定义的数据库API,类似于给数据库编写可执行函数. 简介 存储过程是一组为了完成特定功能的SQL语句集合,是经过编译后存储在数据库中. 存储过程 ...
- mysql存储过程详解
mysql存储过程详解 1. 存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...
- PHP调用MYSQL存储过程实例
PHP调用MYSQL存储过程实例 标签: mysql存储phpsqlquerycmd 2010-09-26 11:10 11552人阅读 评论(3) 收藏 举报 实例一:无参的存储过程$conn = ...
- mysql存储过程语法及实例
存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. --------------------基本语法-------------------- 一.创建存储过程cr ...
- java, mybatis, 调用mysql存储过程
Map<String, Object> bindinfo = new HashMap<String, Object>(); bindinfo.put(&q ...
随机推荐
- redmine安装笔记
切换到redmine安装目录 对所有ip开放启动命令,并且注册为后台运行 nohup ruby bin/rails server webrick -e production -b 0.0.0.0 -p ...
- C++ 模板详解(二)(转)
四.类模板的默认模板类型形参 1.可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值.函数模板和类模板都可以为模板的非类型形参提供默认值. 2.类模板的类型形参默认值形式为:tem ...
- Oracle 修改表名
.ALTER TABLE T_PLAT_KEYWORD_STATISTIC RENAME TO T_PLAT_KEYWORD; .create new_table as select * from o ...
- 工作总结 用, 隔开数据 后台不可以用 List<string> 接收 get请求直接通过浏览器发请求传数组或者list到后台
旁边的 css js 为项目的 加载 css js 地址 只加载引用的样式 js http://localhost:8736/LinInFoKPI/ExcelPrint?line=&start ...
- Iocomp控件教程之LinearGauge--线性刻度尺控件
线性刻度尺-线性刻度尺控件(LinearGauge)是一个具有线性表达式刻度的图像控件.支持多达5种颜色断面和4种指示器样式,相同功能,查看线性对数刻度尺(Linear Log Gauge)控件内容 ...
- Cookie-Parser是怎样解析签名后的cookie的(同一时候对cookie和cookie-signature进行说明)
第一步:我们来学习一下cookie-signature: var cookie=require('./index'); var val = cookie.sign('hello', 'tobiisco ...
- Andrew Ng机器学习笔记+Weka相关算法实现(五)SVM最优间隔和核方法
这一章主要解说Ng的机器学习中SVM的兴许内容.主要包括最优间隔分类器求解.核方法. 最优间隔分类器的求解 利用以一篇讲过的的原始对偶问题求解的思路,我们能够将相似思路运用到SVM的求解上来. 详细的 ...
- linux权限的深入讨论
1. 怎样查看文件的权限 1) 掌握使用ls –l命令查看文件上所设定的权限. drwxr-xr-x. 2 root root 6 May 26 2017 binfmt.d 权限信 ...
- Django--基础补充
render 函数 在Django的使用中,render函数大多与浏览器发来的GET请求一并出现,它的使用方法非常简单 例如:render(request,"xxx.html",{ ...
- 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢? 输出需要删除的字符个数。
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> ...