一、存储过程的简介:mysql
咱们经常使用的操做数据库语言SQL语句在执行的时候须要要先编译,而后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户经过指定存储过程的名字并给定参数(若是该存储过程带有参数)来调用执行它。linux
一个存储过程是一个可编程的函数,它在数据库中建立并保存。它能够有SQL语句和一些特殊的控制结构组成。当但愿在不一样的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是很是有用的。数据库中的存储过程能够看作是对编程中面向对象方法的模拟。它容许控制数据的访问方式。sql
二、存储过程的有点:数据库
(1).存储过程加强了SQL语言的功能和灵活性。存储过程能够用流控制语句编写,有很强的灵活性,能够完成复杂的判断和较复杂的运算。编程
(2).存储过程容许标准组件是编程。存储过程被建立后,能够在程序中被屡次调用,而没必要从新编写该存储过程的SQL语句。并且数据库专业人员能够随时对存储过程进行修改,对应用程序源代码毫无影响。安全
(3).存储过程能实现较快的执行速度。若是某一操做包含大量的Transaction-SQL代码或分别被屡次执行,那么存储过程要比批处理的执行速度快不少。由于存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,而且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。服务器
(4).存储过程能过减小网络流量。针对同一个数据库对象的操做(如查询、修改),若是这一操做所涉及的Transaction-SQL语句被组织程存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大增长了网络流量并下降了网络负载。网络
(5).存储过程可被做为一种安全机制来充分利用。系统管理员经过执行某一存储过程的权限进行限制,可以实现对相应的数据的访问权限的限制,避免了非受权用户对数据的访问,保证了数据的安全。函数
三、关于mysql的存储过程:学习
存储过程是数据库存储的一个重要的功能,可是MySQL在5.0之前并不支持存储过程,这使得MySQL在应用上大打折扣。好在MySQL 5.0终于开始已经支持存储过程,这样便可以大大提升数据库的处理速度,同时也能够提升数据库编程的灵活性。
同时,要在mysql5.1以上版本建立子程序,必须具备CREATE ROUTINE权限,而且ALTER ROUTINE和EXECUTE权限被自动授予它的建立者;
四、存储过程的建立:
(1)语法:
CREATE PROCEDURE sp_name ([ proc_parameter ]) [ characteristics..] routine_body
proc_parameter指定存储过程的参数列表,列表形式以下:[IN|OUT|INOUT] param_name type
其中in表示输入参数,out表示输出参数,inout表示既能够输入也能够输出;param_name表示参数名称;type表示参数的类型该类型能够是MYSQL数据库中的任意类型有如下取值:
characteristic:
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
routine_body:
Valid SQL procedure statement or statements
LANGUAGE SQL :说明routine_body部分是由SQL语句组成的,当前系统支持的语言为SQL,SQL是LANGUAGE特性的惟一值
[NOT] DETERMINISTIC :指明存储过程执行的结果是否正确。DETERMINISTIC 表示结果是肯定的。每次执行存储过程时,相同的输入会获得相同的输出。[NOT] DETERMINISTIC 表示结果是不肯定的,相同的输入可能获得不一样的输出。若是没有指定任意一个值,默认为[NOT] DETERMINISTIC
CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA:指明子程序使用SQL语句的限制。
CONTAINS SQL代表子程序包含SQL语句,可是不包含读写数据的语句;
NO SQL代表子程序不包含SQL语句;
READS SQL DATA:说明子程序包含读数据的语句;
MODIFIES SQL DATA代表子程序包含写数据的语句。
默认状况下,系统会指定为CONTAINS SQL
SQL SECURITY { DEFINER | INVOKER } :指明谁有权限来执行。DEFINER 表示只有定义者才能执行
INVOKER 表示拥有权限的调用者能够执行。默认状况下,系统指定为DEFINER
COMMENT 'string' :注释信息,能够用来描述存储过程或函数
routine_body是SQL代码的内容,能够用BEGIN...END来表示SQL代码的开始和结束
(2) 格式
MySQL存储过程建立的格式:CREATE PROCEDURE 过程名 ([过程参数[,...]])
[特性 ...] 过程体
EG:
DELIMITER //
DROP PROCEDURE IF EXISTS simpleproc;
CREATE PROCEDURE simpleproc (OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM t_user;
END //
DELIMITER ;
我这是在使用Navicat for MySQL 上敲的,就不打算进入mysql客户端去敲了,我的以为这个更方便快捷一点;若是熟悉linux的童鞋估计就不这么认为啦;
好了,废话很少说,先解释一下:(1)DELIMITER这个东西的做用就是告诉mysql,个人存储过程的结束符号是//,因此在你的存储过程当中使用;不会被认为是结束符号;注:当使用delimiter命令时,你应该避免使用反斜杠(‘\’)字符,由于那是MySQL的 转义字符(2)drop procedure if exists的意思跟咱们建表时的语句是同样的,若是存在这个存储过程则删除;(3)create procedure simpleproc (out param1 int) 的意思也很明确,就是建立这个过程,并且带有一个输出参数,注:在function中能够有return 语句,可是procedure是没有的,可是也能够作到将结果传回去,如上;(4) begin .... end 这中间包裹着的就是procedure的主程序,也就是主体部分;简而言之,把你要放在一块儿工做的sql都丢在这里就好;(5)DELIMITER;这个语句做为结束语句。目的是告诉mysql我如今不要使用//做为结束字符了,要换回;了;注:这个不止但是//,还能够是其余符号;
五、变量
DECLARE语句被用来把不一样项目局域到一个 子程序:局部变量,条件和 处理程序 及光标;DECLARE仅被用在BEGIN ... END复合语句里,而且必须在复合语句的开头,在任何其它语句以前。光标必须在声明处理程序以前被声明,而且变量和条件必须在声明光标或处理程序以前被声明。
declare 声明局部变量:DECLARE var_name[,...] type [DEFAULT value];这个语句被用来声明局部变量。要给变量提供一个默认值,请包含一个DEFAULT子句。值能够被指定为一个表达式,不须要为一个常数。若是没有DEFAULT子句,初始值为NULL。
set 变量:SET var_name = expr [, var_name = expr] ...; 在存储程序中的SET语句是通常SET语句的扩展版本。被参考变量多是子程序内声明的变量,或者是全局服务器变量。在存储程序中的SET语句做为预先存在的SET语法的一部分来实现。这容许SET a=x, b=y, ...这样的扩展语法。其中不一样的变量类型(局域 声明变量及全局和集体变量)能够被混合起来。这也容许把局部变量和一些只对系统变量有意义的选项合并起来。在那种状况下,此选项被识别,可是被忽略了。
六、定义处理程序
有时候程序是会出错的,可是你但愿你的程序在出错的状况下继续执行,declare就能够帮助咱们解决这样的问题;具体定义以下:特定条件须要特定处理。这些条件能够联系到错误,以及子程序中的通常流程控制。定义条件是事先定义程序执行过程当中遇到的问题,处理程序定义了在遇到这些问题时候应当采起的处理方式,而且保证存储过程或函数在遇到警告或错误时能继续执行。这样能够加强存储程序处理问题的能力,避免程序异常中止运行
一、定义条件
DECLARE condition_name CONDITION FOR[condition_type]
[condition_type]:
SQLSTATE[VALUE] sqlstate_value |mysql_error_code
condition_name:表示条件名称
condition_type:表示条件的类型
sqlstate_value和mysql_error_code均可以表示mysql错误
sqlstate_value为长度5的字符串错误代码
mysql_error_code为数值类型错误代码,例如:ERROR1142(42000)中,sqlstate_value的值是42000,
mysql_error_code的值是1142
//方法一:使用sqlstate_value DECLARE command_not_allowed CONDITION FOR SQLSTATE '42000' //方法二:使用mysql_error_code DECLARE command_not_allowed CONDITION FOR SQLSTATE 1148
这个语句指定须要特殊处理条件。他将一个名字和指定的错误条件关联起来。
这个名字随后被用在定义处理程序的DECLARE HANDLER语句中
二、定义处理程序
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type:
|CONTINUE:对一个CONTINUE处理程序,当前子程序的执行在执行 处理程序语句以后继续。
| EXIT :对于EXIT处理程序,当 前BEGIN...END复合语句的执行被终止。
| UNDO :UNDO 处理程序类型语句还不被支持。 ·
condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING:SQLWARNING是对全部以01开头的SQLSTATE代码的速记
| NOT FOUND:NOT FOUND是对全部以02开头的SQLSTATE代码的速记
| SQLEXCEPTION:SQLEXCEPTION是对全部没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的速记
| mysql_error_code
这个语句指定每一个能够处理一个或多个条件的处理程序。若是产生一个或多个条件,指定的语句被执行。
//方法一:捕获sqlstate_value DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @info='CAN NOT FIND'; //方法二:捕获mysql_error_code DECLARE CONTINUE HANDLER FOR 1148SET @info='CAN NOT FIND'; //方法三:先定义条件,而后调用 DECLARE can_not_find CONDITION FOR 1146 ; DECLARE CONTINUE HANDLER FOR can_not_find SET set @info='CAN NOT FIND'; //方法四:使用SQLWARNING DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR'; //方法五:使用NOT FOUND DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND'; //方法六:使用SQLEXCEPTION DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR'; eg: delimiter // DROP PROCEDURE IF EXISTS sp2; CREATE PROCEDURE sp2() BEGIN DECLARE CONTINUE HANDLER for SQLSTATE '23000' set @info = 23000; SET @info = 1; INSERT INTO test.t_user VALUES (1,'test','test','test'); SET @info = 2; INSERT INTO test.t_user VALUES (1,'test','test','test'); SET @info = 3; END // delimiter ; -- 执行如下sp2 call sp2(); -- 查询如下@info SELECT @info; --结果分析:若是程序没有出错,按照执行目的,结果@info = 3; 若是被捕获了 '23000' 则结果是@23000; 使用continue做为执行handler_type的话,捕获异常就继续执行;因此结果为3; 使用exit做为执行handler_type的话,捕获异常后直接结束,因此结果为23000;
七、光标
简单光标在存储程序和函数内被支持。语法如同在嵌入的SQL中。光标当前是不敏感的,只读的及不滚动的。 不敏感意为服务器能够活不能够复制它的结果表。 光标必须在声明处理程序以前被声明,而且变量和条件必须在声明光标或处理程序以前被声明。
一、声明光标
DECLARE cursor_name CURSOR FOR select_statement
这个语句声明一个光标。也能够在子程序中定义多个光标,可是一个块中的每个光标必须有惟一的名字。 SELECT语句不能有INTO子句。
二、打开光标
OPEN cursor_name 这个语句打开先前声明的光标。
三、使用光标 FETCH
FETCH cursor_name INTO var_name [, var_name] ... 这个语句用指定的打开光标读取下一行(若是有下一行的话),而且前进光标指针
四、关闭光标
CLOSE cursor_name 这个语句关闭先前打开的光标。 若是未被明确地关闭,光标在它被声明的复合语句的末尾被关闭。
二、流程控制构造
1.IF语句
IF语句用来进行条件判断。根据是否知足条件,将执行不一样的语句。其语法的基本形式以下:
IF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list] ... [ELSE statement_list] END IF
其中,search_condition参数表示条件判断语句;statement_list参数表示不一样条件的执行语句。
注意:MYSQL还有一个IF()函数,他不一样于这里描述的IF语句
下面是一个IF语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp3; CREATE PROCEDURE sp3() BEGIN DECLARE age int DEFAULT 19; set @age1 = 0; SET @age2 = 0; set @age3 = 0; IF age>20 THEN SET @age1=age; ELSEIF age=20 THEN SET @age2=age; ELSE SET @age3=-1; END IF; END // delimiter ; call sp3();
该示例根据age与20的大小关系来执行不一样的SET语句。
若是age值大于20,那么将count1的值加1;若是age值等于20,那么将count2的值加1;
其余状况将count3的值加1。IF语句都须要使用END IF来结束。
2.CASE语句
CASE语句也用来进行条件判断,其能够实现比IF语句更复杂的条件判断。CASE语句的基本形式以下:
CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE
其中,case_value参数表示条件判断的变量;
when_value参数表示变量的取值;
statement_list参数表示不一样when_value值的执行语句。
CASE语句还有另外一种形式。该形式的语法以下:
CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list] ... [ELSE statement_list] END CASE
其中,search_condition参数表示条件判断语句;
statement_list参数表示不一样条件的执行语句。
下面是一个CASE语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp4; CREATE PROCEDURE sp4() BEGIN DECLARE age int DEFAULT 19; set @age1 = 0; CASE age WHEN age > 20 THEN SET @age1 = age; WHEN age = 20 THEN SET @age1 = age-1; ELSE SET @age1 = -1; END CASE; END // delimiter ; call sp4(); select @age1;
注意:这里的CASE语句和“控制流程函数”里描述的SQL CASE表达式的CASE语句有轻微不一样。这里的CASE语句不能有ELSE NULL子句
而且用END CASE替代END来终止!!
3.LOOP语句
LOOP语句可使某些特定的语句重复执行,实现一个简单的循环。
可是LOOP语句自己没有中止循环的语句,必须是遇到LEAVE语句等才能中止循环。
LOOP语句的语法的基本形式以下:
[begin_label:] LOOP statement_list END LOOP [end_label]
其中,begin_label参数和end_label参数分别表示循环开始和结束的标志,这两个标志必须相同,并且均可以省略;(例子与leave结合一块儿写)
4.LEAVE语句
LEAVE语句主要用于跳出循环控制。其语法形式以下:
LEAVE label
其中,label参数表示循环的标志。
下面是一个LEAVE语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp5; CREATE PROCEDURE sp5() BEGIN set @age = 0; add_age:LOOP SET @age = @age + 1; if @age>1000 THEN LEAVE add_age; end IF; END LOOP add_age; END // delimiter ; -- 调用 call sp5(); -- 查看结果 select @age;
该示例循环执行count加1的操做。当count的值等于100时,则LEAVE语句跳出循环。
5.ITERATE语句
ITERATE语句也是用来跳出循环的语句。可是,ITERATE语句是跳出本次循环,而后直接进入下一次循环。
ITERATE语句只能够出如今LOOP、REPEAT、WHILE语句内。
ITERATE语句的基本语法形式以下:
ITERATE label
其中,label参数表示循环的标志。
下面是一个ITERATE语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp6; CREATE PROCEDURE sp6() BEGIN DECLARE age int DEFAULT 0; DECLARE EXIT HANDLER FOR SQLSTATE '23000' SET age = 23000; add_fun:LOOP SET age = age + 1; IF age > 10 THEN INSERT into t_user value(1, 'lennon', 'lennon', 'lennon'); ELSEIF age > 5 && age < 10 THEN ITERATE add_fun; ELSE select age; END IF; END LOOP add_fun; END // delimiter ; call sp6();
说明:LEAVE语句和ITERATE语句都用来跳出循环语句,但二者的功能是不同的。
LEAVE语句是跳出整个循环,而后执行循环后面的程序。而ITERATE语句是跳出本次循环,而后进入下一次循环。
使用这两个语句时必定要区分清楚。
6.REPEAT语句
REPEAT语句是有条件控制的循环语句。当知足特定条件时,就会跳出循环语句。REPEAT语句的基本语法形式以下:
[begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label]
其中,statement_list参数表示循环的执行语句;search_condition参数表示结束循环的条件,知足该条件时循环结束。
下面是一个REPEAT语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp7; CREATE PROCEDURE sp7() BEGIN set @age = 0; add_count:REPEAT set @age = @age + 1 ; UNTIL @age>100 END REPEAT add_count; END // delimiter ; call sp7(); select @age;
该示例循环执行count加1的操做,count值为100时结束循环。
REPEAT循环都用END REPEAT结束。
7.WHILE语句
WHILE语句也是有条件控制的循环语句。但WHILE语句和REPEAT语句是不同的。
WHILE语句是当知足条件时,执行循环内的语句。
WHILE语句的基本语法形式以下:
[begin_label:] WHILE search_condition DO statement_list END WHILE [end_label]
其中,search_condition参数表示循环执行的条件,知足该条件时循环执行;
statement_list参数表示循环的执行语句。
下面是一个ITERATE语句的示例。代码以下:
delimiter // DROP PROCEDURE IF EXISTS sp8; CREATE PROCEDURE sp8() BEGIN set @age = 0; WHILE @age < 100 DO set @age = @age + 1 ; END WHILE; END // delimiter ; call sp8(); select @age;
该示例循环执行count加1的操做,count值小于100时执行循环。
若是count值等于100了,则跳出循环。WHILE循环须要使用END WHILE来结束。
八、查看存储过程
SHOW { PROCEDURE | FUNCTION } STATUS [ LIKE ' pattern ' ] ;
SHOW CREATE { PROCEDURE | FUNCTION } sp_name ;
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=' sp_name ' ;
eg:
show PROCEDURE STATUS like 'sp6'; show CREATE PROCEDURE sp6; SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp6' ;
总结:
终因而整理完一部分了,比较粗糙,可是我相信看完以后会有不小的收获;有一部分是摘抄网络的,有些是摘抄官方手册的,主要目的在于整理本身工做之余的笔记;鄙人菜鸟一枚,若是写的很差,请指出就好,别咬我;这些都是比较基础的整理,但也须要作一个系统的整理学习才能将sql掌握的更好,才能对mysql掌握的更好吧;
流程大体为: 建立->定义变量(光标)->处理程序(有点相似try--catch)->流程控制;