存储过程是一组为了完成某项特定功能的sql语句集,其实质上就是一段存储在数据库中的代码,他能够由声明式的sql语句(如CREATE,UPDATE,SELECT等语句)和过程式sql语句(如IF...THEN...ELSE控制结构语句)组成。存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。html
优势:mysql
缺点:
存储过程,每每定制化于特定的数据库上,由于支持的编程语言不一样。当切换到其余厂商的数据库系统时,须要重写原有的存储过程。sql
在sql中服务器处理sql语句默认是以分号做为语句的结束标志,然而在建立存储过程时,存储过程体中可能包含多条sql语句,这些sql语句若是仍以分号做为语句结束符,那么服务器在处理时会以第一条sql语句处的分号做为整个程序的结束符,而再也不去处理后面的sql。
为解决这个问题,一般使用DELIMITER命令,将sql语句的结束符临时修改成其余符号。
DELIMITER语法格式:数据库
DELIMITER $$
复制代码
$$
是用户定义的结束符,一般这个符号能够是一些特殊的符号。另外应避免使用反斜杠,由于他是转义字符。 若但愿换回默认的分号做为结束标记,只需再在命令行输入下面的sql语句便可。编程
DELIMITER ;
复制代码
在Mysql中,使用CREATE PROCEDURE
语句来建立存储过程。bash
CREATE PROCEDURE p_name([proc_parameter[,...]])
routine_body
复制代码
其中,语法项“proc_parameter”的语法格式是:服务器
[IN|OUT|INOUT]parame_name type
复制代码
IN
,输出参数OUT
,输入输出参数INOUT
。输入参数是使数据能够传递给一个存储过程;输出参数是用于存储过程须要返回的一个操做结果;输入输出参数既能够充当输入参数也能够充当输出结果。BEGIN
开始,以关键字END
结束。若只有一条sql能够忽略BEGIN....END
标志。在存储过程体中能够声明局部变量,用来存储过程体中的临时结果。在Mysql中使用DECLARE
语句来声明局部变量。编程语言
DECLARE var_name type [DEFAULT value]
复制代码
"var_name"用于指定局部变量的名称;"type"用来声明变量的类型;"DEFAULT"用来指定默认值,若是没有指定则为NULL。函数
注意:局部变量只能在存储过程体的BEGIN...END语句块中;局部变量必须在存储过程体的开头处声明;局部变量的做用范围仅限于声明它的BEGIN...END语句块,其余语句块中的语句不可使用它。oop
用户变量通常以@开头。
注意:滥用用户变量会致使程序难以理解及管理。
在Mysql中经过SET语句对局部变量赋值,其格式是:
SET var_name = expr[,var_name2 = expr]....
复制代码
在Mysql中,可使用SELECT...INTO语句把选定的列的值存储到局部变量中。格式是:
SELECT col_name[,..] INTO var_name[,....] table_expr
复制代码
其中"col_name"用于指定列名;"var_name"用于指定要赋值的变量名;"table_expr"表示SELECT语句中FROM后面的部分。
注意:SELECT...INTO语句返回的结果集只能有一行数据。
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc2(IN parameter int)
-> begin
-> declare var int;
-> set var=parameter+1;
-> if var=0 then
-> insert into t values(17);
-> end if;
-> if parameter=0 then
-> update t set s1=s1+1;
-> else
-> update t set s1=s1+2;
-> end if;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
case语句:
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc3 (in parameter int)
-> begin
-> declare var int;
-> set var=parameter+1;
-> case var
-> when 0 then
-> insert into t values(17);
-> when 1 then
-> insert into t values(18);
-> else
-> insert into t values(19);
-> end case;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc4()
-> begin
-> declare var int;
-> set var=0;
-> while var<6 do
-> insert into t values(var);
-> set var=var+1;
-> end while;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
repeat···· end repea:
它在执行操做后检查结果,而 while 则是执行前进行检查。
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc5 ()
-> begin
-> declare v int;
-> set v=0;
-> repeat
-> insert into t values(v);
-> set v=v+1;
-> until v>=5
-> end repeat;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
repeat
--循环体
until 循环条件
end repeat;
复制代码
loop ·····endloop:
loop 循环不须要初始条件,这点和 while 循环类似,同时和 repeat 循环同样不须要结束条件, leave 语句的意义是离开循环。
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc6 ()
-> begin
-> declare v int;
-> set v=0;
-> LOOP_LABLE:loop
-> insert into t values(v);
-> set v=v+1;
-> if v >=5 then
-> leave LOOP_LABLE;
-> end if;
-> end loop;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
ITERATE迭代:
mysql > DELIMITER &&
mysql > CREATE PROCEDURE proc10 ()
-> begin
-> declare v int;
-> set v=0;
-> LOOP_LABLE:loop
-> if v=3 then
-> set v=v+1;
-> ITERATE LOOP_LABLE;
-> end if;
-> insert into t values(v);
-> set v=v+1;
-> if v>=5 then
-> leave LOOP_LABLE;
-> end if;
-> end loop;
-> end;
-> &&
mysql > DELIMITER ;
复制代码
MySQL中的游标能够理解成一个可迭代对象(类比Python中的列表、字典等可迭代对象),它能够用来存储select 语句查询到的结果集,这个结果集能够包含多行数据,从而使咱们可使用迭代的方法从游标中依次取出每行数据。
MySQL游标的特色:
1.只读:没法经过光标更新基础表中的数据。
2.不可滚动:只能按照select语句肯定的顺序获取行。不能以相反的顺序获取行。 此外,不能跳过行或跳转到结果集中的特定行。
3.敏感:有两种游标:敏感游标和不敏感游标。敏感游标指向实际数据,不敏感游标使用数据的临时副本。敏感游标比一个不敏感的游标执行得更快,由于它不须要临时拷贝数据。MySQL游标是敏感的。
declare cursor_name cursor for select_statement;
复制代码
open cursor_name;
复制代码
fetch cursor_name into var_name;
复制代码
close cursor_name;
复制代码
当游标再也不使用时,应该关闭它。 当使用MySQL游标时,还必须声明一个notfound处理程序来处理当游标找不到任何行时的状况。 由于每次调用fetch语句时,游标会尝试依次读取结果集中的每一行数据。 当游标到达结果集的末尾时,它将没法得到数据,而且会产生一个条件。 处理程序用于处理这种状况。
declare continue handler for not found set type = 1;
复制代码
type是一个变量,示游标到达结果集的结尾。
delimiter $$
create PROCEDURE phoneDeal()
BEGIN
DECLARE id varchar(64); -- id
DECLARE phone1 varchar(16); -- phone
DECLARE password1 varchar(32); -- 密码
DECLARE name1 varchar(64); -- id
-- 遍历数据结束标志
DECLARE done INT DEFAULT FALSE;
-- 游标
DECLARE cur_account CURSOR FOR select phone,password,name from account_temp;
-- 将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 打开游标
OPEN cur_account;
-- 遍历
read_loop: LOOP
-- 取值 取多个字段
FETCH NEXT from cur_account INTO phone1,password1,name1;
IF done THEN
LEAVE read_loop;
END IF;
-- 你本身想作的操做
insert into account(id,phone,password,name) value(UUID(),phone1,password1,CONCAT(name1,'的家长'));
END LOOP;
-- 关闭游标
CLOSE cur_account;
END $$
复制代码
使用call语句调用存储过程
call sp_name[(传参)];
复制代码
使用drop语句删除存储过程
DROP PROCEDURE sp_name
复制代码
存储函数和存储过程同样,都是sql和语句组成的代码块。
存储函数不能有输入参数,而且能够直接调用,不须要call语句,且必须有一条包含RETURN语句。
在Mysql中使用CREATE FUNCTION语句建立:
CREATE FUNCTION fun_name (par_name type[,...])
RETURNS type
[characteristics]
fun_body
复制代码
其中,fun_name为函数名,而且名字惟一,不能与存储过程重名。par_name是指定的参数,type为参数类型;RETURNS字句用来声明返回值和返回值类型。fun_body是函数体,全部存储过程当中的sql在存储函数中一样可使用。可是存储函数体中必须包含一个RETURN 语句。
characteristics指定存储过程的特性,有如下取值:
delimiter $$
create function getAnimalName(animalId int) RETURNS VARCHAR(50)
DETERMINISTIC
begin
declare name VARCHAR(50);
set name=(select name from animal where id=animalId);
return (name);
end$$
delimiter;
-- 调用
select getAnimalName(4)
复制代码
其余参考:
www.cnblogs.com/zhanglei93/… www.cnblogs.com/lyhabc/p/37… blog.csdn.net/yuefeicall/…