a! 昨天晚上睡前突然就想到了存储过程,发现好久没用都忘得差不多了......来复习一下子....
一、存储过程是什么?
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升。简单来说就是数据库 SQL 语言层面的代码封装与重用。
二、为什么要用存储过程?
1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
3.存储过程可以重复使用,可减少数据库开发人员的工作量。
4.安全性高,可设定只有某些用户才具有对指定存储过程的使用权。
PS:一些网上盛传的所谓的存储过程要比sql语句执行更快的说法,实际上是个误解,并没有根据,包括微软内部的人也不认可这一点,所以不能作为正式的优点,希望大家能够认识到这一点。
5.虽然调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。
三、怎么用?
先来写一把mysql的,oracle的后面再编辑补充。
MySQL 5.0 版本开始支持存储过程。
以下简单案例来自菜鸟教程,自己敲了一遍加上自己的理解稍微整理了一下,嘻嘻嘻,先把基础捡起来。
表结构:
matches:
1.定义一个存储过程
//作用:根据给定的playerno删除指定信息
mysql> delimiter $$ #将语句的结束符号从分号;临时改为两个$$(可以是自定义) mysql> create procedure delete_mathes(IN p_playno INTEGER)// -> begin -> delete from matches where playerno=p_playno; -> end$$ Query OK, 0 rows affected (0.10 sec) mysql> delimiter ; #将语句的结束符号恢复为分号
2.执行存储过程:
首先来看一下执行之前的数据: mysql> select * from matches; +---------+--------+----------+------+------+ | MATCHNO | TEAMNO | PLAYERNO | WON | LOST | +---------+--------+----------+------+------+ | 1 | 1 | 6 | 3 | 1 | | 7 | 1 | 57 | 3 | 0 | | 8 | 1 | 8 | 0 | 3 | | 9 | 2 | 27 | 3 | 2 | | 11 | 2 | 112 | 2 | 3 | +---------+--------+----------+------+------+ 5 rows in set (0.00 sec)
执行存储过程:
mysql> call delete_mathes(112);
Query OK, 1 row affected (0.07 sec)
在存储过程中设置了需要传参的变量p_playerno,调用存储过程的时候,将112作为参数赋值给p_playerno,然后进行存储过程里的SQL操作。
执行之后的数据:palyerno为112的数据被删除 mysql> select * from matches; +---------+--------+----------+------+------+ | MATCHNO | TEAMNO | PLAYERNO | WON | LOST | +---------+--------+----------+------+------+ | 1 | 1 | 6 | 3 | 1 | | 7 | 1 | 57 | 3 | 0 | | 8 | 1 | 8 | 0 | 3 | | 9 | 2 | 27 | 3 | 2 | +---------+--------+----------+------+------+ 4 rows in set (0.00 sec)
3.存储过程的参数
MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT,形式如:
create procedure 存储过程名([[IN |OUT |INOUT ] 参数名 数据类形...])
IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
(1)IN参数的一个简单实例:
mysql> delimiter $$ mysql> create procedure in_param(in p_in int) -> begin -> select p_in; -> set p_in=2; -> select p_in; -> end$$ Query OK, 0 rows affected (0.07 sec) Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; 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.02 sec) Query OK, 0 rows affected (0.04 sec) mysql> select @p_in; +-------+ | @p_in | +-------+ | 1 | +-------+ 1 row in set (0.00 sec)
p_in 在存储过程中被修改,但并不影响 @p_id 的值,因为前者为局部变量、后者为全局变量。
(2)OUT参数的一个实例:
mysql> delimiter # 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.08 sec) mysql> delimiter ; mysql> call out_param(@p_out); +-------+ | p_out | +-------+ | NULL | +-------+ 1 row in set (0.00 sec) #因为传入的参数是out类型的,只输出,所以全局变量p_out并不起作用,第一次select p_out时对象为NULL +-------+ | p_out | +-------+ | 2 | +-------+ 1 row in set (0.02 sec) Query OK, 0 rows affected (0.03 sec) mysql> select @p_out; +--------+ | @p_out | +--------+ | 2 | +--------+ 1 row in set (0.00 sec)
#调用了out_param存储过程,输出参数,改变了p_out变量的值
(3)INOUT参数的一个小实例
mysql> delimiter % 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.01 sec) mysql> delimiter ; 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.02 sec) Query OK, 0 rows affected (0.03 sec) mysql> select @p_inout; +----------+ | @p_inout | +----------+ | 2 | +----------+ 1 row in set (0.00 sec) #调用了inout_param函数,改变了p_inout的值
PS:
1、如果过程没有参数,也必须在过程名后面写上小括号例。
2、确保参数的名字不等于列的名字,否则在过程体中,参数名被当做列名来处理。
3、输入值使用in参数,返回值用out当参数,尽量不使用inout。
4、变量的定义和赋值
(1)局部变量声明一定要放在存储过程体的开始:
mysql> create procedure cri_param() -> begin -> declare l_int int unsigned default 100; -> declare l_num numeric(8,2) default 9.99; -> declare l_date date default '2020-02-17'; -> declare l_datetime datetime default '2020-02-17 22:22:22'; -> declare l_varchar varchar(15) default 'hello'; -> select l_int,l_num,l_date,l_datetime,l_varchar; -> end! Query OK, 0 rows affected (0.03 sec) mysql> delimiter ; mysql> call cri_param; +-------+-------+------------+---------------------+-----------+ | l_int | l_num | l_date | l_datetime | l_varchar | +-------+-------+------------+---------------------+-----------+ | 100 | 9.99 | 2020-02-17 | 2020-02-17 22:22:22 | hello | +-------+-------+------------+---------------------+-----------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.02 sec)
(2)变量赋值
SET 变量名 = 表达式值 [var_name=value]
(3)用户变量
定义用户变量的几种方式:
mysql> select @x; +-------+ | @x | +-------+ | hello | +-------+ 1 row in set (0.00 sec) mysql> set @y='bye'; Query OK, 0 rows affected (0.00 sec) mysql> select @y; +------+ | @y | +------+ | bye | +------+ 1 row in set (0.00 sec) mysql> set @z=5+5; Query OK, 0 rows affected (0.00 sec) mysql> select @z; +------+ | @z | +------+ | 10 | +------+ 1 row in set (0.00 sec)
(4)在存储过程中使用用户变量
mysql> delimiter & mysql> create procedure greet() -> select concat(@gt,'world'); -> set @gt='hello '; -> & Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql> call greet(); -> & +---------------------+ | concat(@gt,'world') | +---------------------+ | hello world | +---------------------+ 1 row in set (0.00 sec)
(5)存储过程间传递全局变量的值
mysql> create procedure p1() -> set @last_p='p1'; -> $ Query OK, 0 rows affected (0.05 sec) mysql> create procedure p2() -> select concat('last prodecure was ',@last_p); -> $ Query OK, 0 rows affected (0.06 sec) mysql> delimiter ; mysql> call p1(); Query OK, 0 rows affected (0.00 sec) mysql> call p2(); +---------------------------------------+ | concat('last prodecure was ',@last_p) | +---------------------------------------+ | last prodecure was p1 | +---------------------------------------+ 1 row in set (0.00 sec)
PS:
1、用户变量名一般以@开头。
2、滥用用户变量会导致程序难以理解及管理。
啊喂,大半夜的,明天再继续复习,嘻嘻嘻狗命要紧,洗漱一下做个拉伸准备睡觉 ^-^
a!秃头芊再次上线!写算法题突然思路阻塞.......换个脑子把昨天这个写完吧.....
5.mysql的注释
两个横杆--:该风格一般用于单行注释。
6.mysql查询,修改,删除存储过程
mysql> show procedure status where db='db1';--db1是数据库名 +------+---------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +------+---------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | db1 | cri_param | PROCEDURE | root@localhost | 2020-02-17 22:29:00 | 2020-02-17 22:29:00 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | delete_mathes | PROCEDURE | root@localhost | 2020-02-17 21:29:55 | 2020-02-17 21:29:55 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | greet | PROCEDURE | root@localhost | 2020-02-17 22:44:34 | 2020-02-17 22:44:34 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | inout_param | PROCEDURE | root@localhost | 2020-02-17 22:07:39 | 2020-02-17 22:07:39 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | in_param | PROCEDURE | root@localhost | 2020-02-17 21:48:07 | 2020-02-17 21:48:07 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | out_param | PROCEDURE | root@localhost | 2020-02-17 21:59:18 | 2020-02-17 21:59:18 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | p1 | PROCEDURE | root@localhost | 2020-02-17 22:49:02 | 2020-02-17 22:49:02 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | | db1 | p2 | PROCEDURE | root@localhost | 2020-02-17 22:50:00 | 2020-02-17 22:50:00 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci | +------+---------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 8 rows in set (0.01 sec)
查看具体的存储过程的内容:
mysql> show create procedure db1.cri_param; +-----------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation | +-----------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | cri_param | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `cri_param`() begin declare l_int int unsigned default 100; declare l_num numeric(8,2) default 9.99; declare l_date date default '2020-02-17'; declare l_datetime datetime default '2020-02-17 22:22:22'; declare l_varchar varchar(15) default 'hello'; select l_int,l_num,l_date,l_datetime,l_varchar; end | utf8 | utf8_general_ci | utf8_general_ci | +-----------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set (0.01 sec)
修改:使用ALTER语句可以修改存储过程或函数的特性,只能修改特性,如果想修改过程体只能删除存储过程再重新创建。
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
characteristic:
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
参数说明:
sp_name参数表示存储过程或函数的名称;
characteristic参数指定存储函数的特性。
CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;
NO SQL表示子程序中不包含SQL语句;
READS SQL DATA表示子程序中包含读数据的语句;
MODIFIES SQL DATA表示子程序中包含写数据的语句。
SQL SECURITY { DEFINER | INVOKER }指明谁有权限来执行,DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。
COMMENT 'string'是注释信息。
删除:
DROP {PROCEDURE|FUNCTION} [IF EXISTS] sp_name