存储过程
其实就是mysql语句组成的脚本,也就是数据库中保存的一系列SQL命令的集合。
可以使用变量,条件判断,流程控制等
提高性能 | 减轻网络负担 | 可以防止对表的直接访问 | 避免重复编写SQL操作 |
创建过程
语法格式:
delimiter // //delimiter 关键字用来指定存储过程的分隔符,默认为'';"
create procedure 名称() 若不指定,编译器会把存储过程当成SQL语句进行处理,从而执行报错
begin
.... 功能代码
end
// //结束存储过程
mysql> delimiter // //指定分隔符//
mysql> create procedure db9.p1()
-> begin
-> select count(*) from db9.user;
-> end
-> //
Query OK, 0 rows affected (0.02 sec)
查看存储过程
1. mysql> show procedure status;
2. mysql> select db,name,type from mysql.proc where name="存储过程名";
mysql> select db,name,type from mysql.proc where name="p1";
+-----+------+-----------+
| db | name | type |
+-----+------+-----------+
| db9 | p1 | PROCEDURE |
+-----+------+-----------+
1 row in set (0.00 sec)
调用/删除存储过程
call 存储过程名(); //存储过程无参数,()可以省略;存储过程有参数,调用时必须传给参数
mysql> call db9.p1() // //调用存储过程
+----------+
| count(*) |
+----------+
| 42 |
+----------+
1 row in set (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
mysql> delimiter ;
mysql> call db9.p1();
+----------+
| count(*) |
+----------+
| 42 |
+----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
drop procedure 存储过程名;
mysql> drop procedure db9.p1;
Query OK, 0 rows affected (0.00 sec)
mysql> select db,name,type from mysql.proc where name="p1";
Empty set (0.00 sec)
进阶知识
变量类型
名称 | 描述 | 格式 | |
---|---|---|---|
系统变量 | 会话变量 | 使用set命令定义全局变量的修改会影响到整个服务器,但是对会话变量的修改,只会影响到当前的会话。select @@hostname | mysql> set session 变量名=值; |
全局变量 | mysql>set global 变量名=值; | ||
用户变量 | 在客户端链接到数据库服务的整个过程中都是有效的。当目前链接断开后所有用户变量失效 |
定义 set @变量名=值; 输出select @变量名; |
|
局部变量 | 存储过程中的begin/end。其有效范围仅限于该语句块中,语句块执行完毕后,变量失效。用declare定义 | declare | |
注意:局部变量 和 参数变量 调用时,变量名前不需要加@ |
mysql> show session variables like "sort%";
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| sort_buffer_size | 262144 |
+------------------+--------+
1 row in set (0.00 sec)
mysql> set session sort_buffer_size=40000;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like "%semi%";
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.00 sec)
mysql> create procedure db9.p2() begin declare x int default 9; declare y char(10); set y = "jack"; select x;select y; end//
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p2();
+------+
| x |
+------+
| 9 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| jack |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
算数运算
+(加) -(减) * (乘) /(除) DIV(整除运算) %(取模 也就是余数)
mysql> set @z=1+2;select @z;
Query OK, 0 rows affected (0.00 sec)
+------+
| @z |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql> set @x=1;set @y=3;set @z=@x*@y;select @z;
+------+
| @z |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql> set @x=3;set @y=10;set @z=@y/@x;select @z;
+-------------+
| @z |
+-------------+
| 3.333333333 |
+-------------+
1 row in set (0.00 sec)
mysql> set @x=10 div 3;
Query OK, 0 rows affected (0.00 sec)
mysql> select @x;
+------+
| @x |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql> delimiter //
mysql> create procedure db9.p3()
-> begin
-> declare x int;declare y int;declare z int;
-> select count(shell) into x from db9.user where shell="/bin/bash"; //使用sql命令查询结果赋值(into 变量名)
-> select count(shell) into y from db9.user where shell="/sbin/nologin";
-> set z = x + y;
-> select x , y , z;
-> end
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p3();
+------+------+------+
| x | y | z |
+------+------+------+
| 2 | 35 | 37 |
+------+------+------+
1 row in set (0.00 sec)
参数类型
关键字 | 名称 | 描述 |
---|---|---|
in | 输入参数 | 作用是给存储过程传值,必须在调用存储过程时赋值,在存储过程中该参数的值不允许修改;默认类型是in |
out | 输出参数 | 该值可在存储过程内部被改变,可返回 |
inout | 输入/输出 | 调用时指定,可被改变和返回 |
mysql> create procedure db9.p4( in x char(20) ) begin select name from db9.user where name=x;
-> end
-> //
mysql> delimiter ;
Query OK, 0 rows affected (0.00 sec)
mysql> call db9.p4("root");
+------+
| name |
+------+
| root |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> create procedure db9.p5( in shellname char(20) ,out num int) begin select count(name) into num from db9.user where shell=shellname;select num;
-> end //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p5("/bin/bash",4); //out和inout 参数不可以赋值
ERROR 1414 (42000): OUT or INOUT argument 2 for routine db9.p5 is not a variable or NEW pseudo-variable in BEFORE trigger
mysql> call db9.p5("/bin/bash"); //也不可以不写或者空”null“
ERROR 1318 (42000): Incorrect number of arguments for PROCEDURE db9.p5; expected 2, got 1
mysql> select @w;
+------+
| @w |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> call db9.p5("/bin/bash",@w); //必须用变量占位
+------+
| num |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
mysql> delimiter //
mysql> create procedure db9.p6( inout x char(30))
-> begin
-> select name,shell from db9.user where shell=x;
-> select count(*) into x from db9.user;
-> select x;
-> end
-> //
Query OK, 0 rows affected (0.01 sec)
mysql> set @i="/bin/bash";
Query OK, 0 rows affected (0.00 sec)
mysql> call db9.p6(@i);
+------+-----------+
| name | shell |
+------+-----------+
| root | /bin/bash |
| lisi | /bin/bash |
+------+-----------+
2 rows in set (0.00 sec)
+------+
| num |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
流程控制
类型(数值) | 用途 | 类型(字符类) | 用途 |
---|---|---|---|
= | 等于 | or and ! | 逻辑或,与,非 |
> >= | 大于,大于等于 | in... not in.. | 在..范围之内,不在..范围之内 |
< <= | 小于,小于等于 | is null is not null | 字段的值为空, 不为空 |
!= | 不等于 | like | 模糊匹配 |
between..and.. | 在..与..之间 | regexp | 正则匹配 |
if结构
if单分支 | if双分支 |
---|---|
if 条件测试 then 代码.. .. .. end if; |
if 条件测试 then 代码1.. else 代码2.. end if; |
mysql> create procedure db9.p22() begin if 1<=2 then select user(); end if; select * from db9.user where id=1; end//
//if条件不成立则只输出最后一个
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p22();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
+----+------+----------+------+------+---------+---------+-----------+
| id | name | password | uid | gid | comment | homedir | shell |
+----+------+----------+------+------+---------+---------+-----------+
| 1 | root | x | 0 | 0 | root | /root | /bin/bash |
+----+------+----------+------+------+---------+---------+-----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter //
mysql> create procedure db9.p23(in line int )
-> begin
-> if line < 10 then
-> select name,uid from db9.user where id <= line;
-> else
-> select name,uid,shell from db9.user where id >= line;
-> end if;
-> end
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p23(7);
+----------+------+
| name | uid |
+----------+------+
| root | 0 |
| bin | 1 |
| daemon | 2 |
| adm | 3 |
| lp | 4 |
| sync | 5 |
| shutdown | 6 |
+----------+------+
7 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> call db9.p23(15);
+---------------------+-------+---------------+
| name | uid | shell |
+---------------------+-------+---------------+
| dbus | 81 | /sbin/nologin |
| polkitd | 999 | /sbin/nologin |
...
| lisi | 1000 | /bin/bash |
| mysql | 27 | /bin/false |
| NULL | 1500 | NULL |
+---------------------+-------+---------------+
28 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
循环结构
while条件式循环 | loop死循环 | repeat条件式循环 |
---|---|---|
while 条件判断 do 循环体 .. .. end while; 反复测试,只要成立就执行序列 |
loop 循环体 .. .. end loop; 无条件,反复执行某一段代码 |
repeat 循环体 .. .. until 条件判断 end repeat; 当条件成立时结束结束循环 |
mysql> delimiter //
mysql> create procedure db9.p24()
-> begin
-> declare x int default 1;
-> declare y int default 1;
-> while x <= 3 do
-> select y;
-> set x=x+1;
-> end while;
-> end
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p24();
+------+
| y |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> create procedure db9.p25() begin declare y int default 1; loop select y; end loop; end//
mysql> delimiter ;
mysql> call db9.p25(); //会无限循环下去,
1 row in set (1.66 sec)
+------+
| y |
+------+
| 1 |
+------+
1 row in set (1.66 sec)
+------+
| y |
+------+
| 1 |
+------+
...
mysql> ^C //可以ctrl+c 终止
mysql> create procedure db9.p26()
-> begin
-> declare y int default 1;
-> repeat
-> select y;
-> set y=y+1;
-> until y=7
-> end repeat;
-> end
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> call db9.p26();
+------+
| y |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 4 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 5 |
+------+
1 row in set (0.00 sec)
+------+
| y |
+------+
| 6 |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter //
mysql> create procedure db9.p27(in line int )
-> begin
-> if line is not null then
-> select * from db9.user where id=line;
-> else select * from db9.user where id=1;
-> end if;
-> end
-> //
//定义一个过程,当用户输入行数时,显示对应行的数据,否则,直接输出第一行
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p27(3);
+----+--------+----------+------+------+---------+---------+---------------+
| id | name | password | uid | gid | comment | homedir | shell |
+----+--------+----------+------+------+---------+---------+---------------+
| 3 | daemon | x | 2 | 2 | daemon | /sbin | /sbin/nologin |
+----+--------+----------+------+------+---------+---------+---------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> select @u;
+------+
| @u |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> call db9.p27(@u); //输入空
+----+------+----------+------+------+---------+---------+-----------+
| id | name | password | uid | gid | comment | homedir | shell |
+----+------+----------+------+------+---------+---------+-----------+
| 1 | root | x | 0 | 0 | root | /root | /bin/bash |
+----+------+----------+------+------+---------+---------+-----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
例:输出user表中,uid字段值为偶数的用户名和对应uid号,并且统计有多少个用户?
mysql> delimiter //
mysql> create procedure db9.p28()
-> begin
-> declare count int default 0;
-> declare juid int;
-> declare y int default 1;
-> declare x int;
-> select count(*) into x from db9.user;
-> while y <= x do select uid into juid from db9.user where id = y;
-> if juid % 2 = 0 then
-> select name,uid from db9.user where id = y;
-> set count = count + 1;
-> end if;
-> set y = y+1;
-> end while;
-> select count;
-> end
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call db9.p28();
+------+------+
| name | uid |
+------+------+
| root | 0 |
+------+------+
1 row in set (0.01 sec)
+--------+------+
| name | uid |
+--------+------+
| daemon | 2 |
+--------+------+
1 row in set (0.01 sec)
...
...
+------+------+
| name | uid |
+------+------+
| NULL | 1500 |
+------+------+
1 row in set (0.01 sec)
+-------+
| count |
+-------+
| 22 |
+-------+
1 row in set (0.01 sec)
Query OK, 0 rows affected (0.01 sec)