场景
存储过程
存储过程是一组为了完成特定功能的SQL语句集合。使用存储过程的目的是将常用或复杂的工作预先用SQL语句写好并用一个指定名称存储起来,
这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。
当以后需要数据库提供与己定义好的存储过程的功能相同的服务时,只需调用"CALL 存储过程名字"即可自动完成。
创建存储过程
创建存储过程需要使用 CREATE PROCEDU 语句 基本语法格式如下:
CREATE PROCEDURE sp_name ( [proc_parameter] ) [characteristic .. ·] routine body
CREATE PROCEDURE 为用来创建存储函数的关键字;
sp_name为存储过程的名称;
proc_parameter指定存储过程的参数列表 列表形式如下:
[ IN I OUT I INOUT ) param name type
IN 表示输入参数, OUT 表示输出参数, INOUT 表示既可以输入也可以输出 param_name 表示参数名称 type 表示参数的类型,
该类型可以是 MySQL 数据库中的任意类型。
characteristic 指定存储过程的特性,有以下取值
(1)LANGUAGE SQL:说明 routine_body部分是由 SQL 语句组成的,SQL是LANGUAGE特性的唯一值。
(2)[NOT] DETERMINISTIC: 指明存储过程执行的结果是否正确。 DETERMINISTIC表示结果是确定的,
当每次执行存储过程时相同的的输入会得到相同的输出;
NOT DETERMINISTIC 表示结果是不确定的,相同的输入可能得到不同的输出。
如果没有指定任意一个值,默认为NOT DETERMINISTIC。
(3){ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:指明子程序使用 SQL语句的限制。
CONTAINS SQL 表明子程序包含SQL语句,但是不包含读或写数据的语句。
NOSQL 表明子程序不包含SQL语句。
READS SQL DATA 说明子程序包含读数据的语句。
MODIFIES SQL DATA 表明子程序包含写数据的语句。在默认情况下,系统会指定为 CONTAINS SQL。
(4)SQL SECURITY { DEFINER |INVOKER }: 指明谁有权限来执行。 DEFINER表示只有定义者才能执行。
INVOKER 表示拥有权限的调用者可以执行。在默认情况下 系统指定为 DEFINER。
(5)COMMENT 'string': 注释信息,可以用来描述存储过程或函数。
routine_ body是SQL代码的内容,可以用 BEGIN··· END 来表示 SQL 代码的开始和结束。
创建测试表test_student
CREATE TABLE test_student
(
sid int PRIMARY KEY,
sname
VARCHAR(20),
ssex CHAR(2),
sage
int,
did int
);
插入测试数据
INSERT INTO test_student(sid,sname,sage,did)
VALUES (1,'张三',13,101),
(2,'李四',14,101),
(3,'王五',15,102),
(4,'赵六',16,101);
创建查看student表的存储过程
CREATE PROCEDURE Proc_student () BEGIN
SELECT
*
FROM
test_student;
END;
调用存储过程
CALL 语句用来调用一个使用 PROCEDURE 创建好的存储过程,基本语法格式如下:
CALL sp name ([parameter [, ···]]}
CALL 调用语句中的 sp_name 为存储过程的名称, parameter 为存储过程的参数。
创建存储过程,查询某个班级的平均年龄,然后调用该存储过程
CREATE PROCEDURE avg_student (
IN
dep INT,
OUT avg FLOAT ) BEGIN
SELECT
avg( sage ) INTO avg
FROM
test_student
WHERE
did = dep;
END;
CALL avg_student(101,@aa);
--
查询返回的结果
SELECT @aa;
查看存储过程
在存储过程创建好以后,用户可以通过如下三种方式进行查看
方式1:使用SHOW PROCEDURE STATUS 语句查看存储过程的状态
SHOW PROCEDURE STATUS LIKE 'avg_%';
获取数据库中所有名称以字母avg_开头的存储过程的信息。
只能查看存储过程操作哪一个数据库,存储过程的名称、类型,谁定义的, 创建和修改时间、字符编码等信息,
不能查看存储过程的具体定义。 -- 如果需要查看详细定 ,需要使用 SHOW CREATE PROCEDURE 语句。
方式2:使用 SHOW CREATE PROCEDURE 语句
SHOW CREATE PROCEDURE avg_student;
它返回一个可用来重新创建已命名存储过程的确切字符串
方式3:通过information_schema.Routines 查看存储过程的信息。
SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_NAME = 'avg_student';
修改存储过程
在存储过程创建完成后,如果需要修改,可以使用ALTER语句进行修改
修改存储过程的定义,将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行。
ALTER PROCEDURE avg_student
MODIFIES SQL DATA
SQL SECURITY
INVOKER;
删除存储过程
使用DROP PROCEDURE 语句
DROP PROCEDURE avg_student;
存储函数
创建存储函数
创建存储函数需要使用 CREATE FUNCTION 语旬
基本语法格式如下
CREATE FUNCTION func_name ( [func_parameter] ) RETURNS type [characteristic···] routine_ body
CREATE FUNCTION 为用来创建存储函数的关键字: func_name 表示存储函数的名称;func_parameter 为存储过程的参数列表,
参数列表形式如下
{IN | OUT | INOUT } param_name type
其中,IN 表示输入参数,OUT 表示输出参数,INOUT 表示既可以输入也可以输出, param_name 表示参数名称,
type 表示参数的类型,该类型可以是 MySQL 数据库中的任意类型。
CREATE FUNCTION name_student ( aa INT ) RETURNS CHAR (
50 ) BEGIN
RETURN ( SELECT sname FROM test_student
WHERE did = aa );
END
参数定义 aa 返回一个CHAR类型结果。 SELECT语句从student 表申查询 did 等于aa并将该记录中的sname字段返回。
如果提示:This function has none of DETERMINISTIC, NO SQL, or
READS SQL DATA in its declaration and binary logging is enabled
(you *might* want to use the less safe
log_bin_trust_function_creators variable)
执行如下临时生效,重启后失效:
set global log_bin_trust_function_creators= TRUE;
调用存储函数
MySQL中,存储函数的使用方法和MySQL内部函数的使用方法是一样的。
用户自己定义的存储函数与MySQL内部函数的性质相同,区别在于存储函数是用户自己定义的,
而内部函数是MySQL开发者定义的。
SELECT name_student(102);
查看存储函数
可以使用 SHOW FUNCTION STATUS 语句或 SHOW CREATE FUNCTION 语句来查看
也可以直接从系统的 information_chema 数据库中查询。
SHOW FUNCTION STATUS LIKE 'name_student';
SHOW CREATE FUNCTION name_student;
SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_NAME
= 'name_student';
删除存储函数
删除存储函数可以使用 DROP FUNCTION 语句
DROP FUNCTION name_student;
自定义函数
定义变量
MySQL 中使用 DECLARE 关键字来定义变量,定义变量的基本语法格式如下
DECLARE var_name[,···] type [DEFAULT value]
DECLARE 关键字用来声明变量。
var name 数是变量的名称,可以同时定义多个变量。
type参数用来指定变量的类型。
DEFAULT value 子句为变量提供一个默认值。默认值可以是一个常数,也可以是一个表达式。
如果没有给变量指定默认值,初始值为NULL
DECLARE studentid char(10) DEFAULT '一年级';
变量赋值
变量赋值使用SET语句
DECLARE v1;
SET v1=66;
-- MySQL中还可以使用SELECT···
INTO 语旬为变量赋值
DECLARE student_name char(50);
SELECT sname into student_name
FROM
test_student
WHERE sid= 2;
流程控制语句
IF语句
IF price>=30 then
SELECT
'价格太高';
ELSE SELECT '价格适中';
END
IF;
--
判断price的值,如果price大于等于30,输出字符串'价格太高',否则输出字符串'价格适中'。IF语句都需要END IF来结束
CASE语句用来进行条件判断,
CASE did
WHEN 101 THEN SELECT '一年级';
WHEN 102
THEN SELECT '二年级';
END CASE;
LOOP语句
--
LOOP语句可以重复执行特定的语句,实现简单的循环,但是 LOOP 语句本身并不进行条件判断,
--
没有停止循环的语旬,必须使用LEAVE语句才能停止循环,跳出循环过程。
-- 基本格式
-- [begin_label:] LOOP
-- statement
list
-- END LOOP [end_label]
--
语法中的 begin_label 参数和 end_label 参数分别表示循环开始和结束的标志,这两个标志必须相同 ,
-- 而且都可以省略 statement_list参数表示需要循环执行的语句
DECLARE aa int default 0;
Add_sum:loop
Set aa=aa+1;
END loop Add_sum;
--
该例执行的是aa加1的操作,循环中没有跳出循环的语旬,所以该循环为死循环
LEAVE语句
-- LEAVE
语句主要用来跳出任何被标注的流程控制语句
DECLARE aa int default 0;
Add_sum:loop
Set aa=aa+1;
IF aa>50 then leave Add_sum;
END
IF;
END loop Add_sum;
ITERATE语句
--
ITERATE语句也是用来跳出循环的语句,但ITERATE只可以出现在LOOP 、REPEAT和WHILE语句内。
-- ITERATE语句是跳出本次循环,然后直接进入下次循环,ITERATE的意思是再次循环
CREATE PROCEDURE pp(a INT)
BEGIN
La: LOOP
SET a=a+1;
IF a<10 THEN ITERATE la;
END
IF;
LEAVE la;
END LOOP la;
SET @x=a;
END;
-- 该例中的a变量为输入参数,在LOOP循环中a的值加1,在 IF 条件语句中进行判断,如果a的值小
-- 于10,则使用ITERATE la 跳出本次循环,又一次从头开始 LOOP
循环,a的值再次加1;若a大于等于
-- 10,则ITERATE la 语句不执行 执行下面的 LEAVE la
语句跳出整个循环。
REPEAT 语句
-- REPEAT
语句创建的是带条件判断的循环过程。循环语句每次执行完都会对表达式进行判断,若表达
--
式为真,则结束循环,否则再次重复执行循环中的语句。当条件判断为真时就会跳出循环语句。 REPEAT
--
语句的基本语法格式
-- [begin_label:] REPEAT
-- statement_list
-- UNTIL
search_condition
-- END REPEAT [end_label]
-- 语法中的begin_label end_label为开始标记和结束标记 均可以省略。 statement_list
参数表示循
-- 环的执行语旬, search_condition参数表示结束循环的条件,该条件为真时结束跳出循环
该参数为假时再
-- 次执行循环语句
DECLARE ss int DEFAULT 0;
REPEAT
SET ss=ss+1;
UNTIL ss>=10;
END REPEAT;
WHILE 语句
-- WHILE 语句也是有条件控制的循环语句
WHILE 语句和REPEAT 语句是不同的。 WHILE语句在
-- 执行时先对条件表达式进行判断
若该条件表达式为真 则执行循环内的语句,否则退出循环过程
DECLARE ss int DEFAULT 0;
WHILE ss<=10 DO
SET ss=ss+1;
END WHILE;
光标/游标的使用
在存储过程或自定义函数中的查询可能会返回多条记录。可以使用光标来逐条读取查询结果集中的记录。
光标在很多其他书 被称为游标。光标的使用包括光标的声明、打开光标、使用光标和关闭光标。
需要注意的是,光标必须在处理程序之前声明 在变量和条件之后声明。
声明光标
-- 声明一个名为cursor_student的光标
DECLARE cursor_student CURSOR FOR SELECT sid,sname FROM
test_student;
打开光标
OPEN cursor_student;
使用光标
--
使用名称为cursor_student的光标,将查询得到的数据存储在变量e_no e_name
FETCH
cursor_student INTO e_no,e_name;
关闭光标
CLOSE cursor_student;
定义条件和处理程序
在程序的运行过程中可能会遇到问题,此时可以通过定义条件和处理程序来事先定义这些问题,
并且可以在处理程序中定义在遇到这些问题时应该采用什么样的处理方式,提出解决方法 保证存储过程或自
定义函数在遇到警告或错误时能够继续执行,从而增强程序处理问题的能力,避免程序出现异常,被停止执行
定义条件的语法格式
-- DECLARE
condition_name CONDITION FOR condition_value
--
condition_value:
-- SQLSTATE [VALUE] sqlstate_value |
mysql_error_code
-- 语法中的 condition_name 参数为条件的名称, condition_value
参数为条件的类型。
-- sqlstate_value和mysql_error_code 都可以表示 MySQL
的错误。其中 sqlstate_value 为长度为5的字符
--
串类型的错误代码,mysql_error_code 为数值类型错误代码。
-- 示例:定 RROR 1110(44000)的错误,名称为 command not find
DECLARE command_not_find CONDITION FOR sqlstate '44000';
DECIMAL command_not_find CONDITION FOR 1110;
定义处理程序
--
其语法格式如下:
-- DECLARE handler_type HANDLER FOR
condition_value [,...] sp_statement
-- 参数说明
-- handler_type : CONTINUE | EXIT | UNDO
-- handler_type 为错误处理方式,取上述3个值中的一个。 CONTINUE 表示遇到错误不处理,继续执行
-- EXIT 表示遇到错误马上退出;UNDO 表示遇到错误后撤销之前的操作。
-- condition_value 表示错误的类型,该参数可以取以下值。
-- SQLSTATE[VALUE] sqlstate_value 字符串错误值。
-- condition_name :使用DECLARE CONDITION 定义的错误条件名称。
-- SQLWARNING: NOT FOUND 匹配所有以 02 开头的 SQLSTATE 错误代码
SQLEXCEPTION 匹配所
-- 有没有被SQLWARNING或NOT FOUND 捕获的 SQLSTATE
错误代码。
-- 示例 定义捕获 sqlstate_value 值。如果遇到 sqlstate_value 值为23SOO
执行 CONTINUE 操作,并且给变量x赋值20
DECLARE CONTINUE HANDLER FOR
SQLSTATE '23S00'
SET @x= 20;
-- 示例 该方法捕获 mysql_error_code
值。如果mysql_error_code值为1146,执行CONTINUE操作,并且给变量x赋值20
DECLARE CONTINUE HANDLER FOR 1146
SET
@x= 20;
-- 示例 该方法先定义NO TABLE 条件,遇到1150错误时执行CONTINUE操作,并输出"NO
TABLE"信息。
DECLARE NO_TABLE CONDITION FOR 1150;
DECLARE CONTINUE HANDLER FOR NO_TABLE
SET @info= 'NO_TABLE';
-- 示例
SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT操作,并且输出 "ERROR"信息。
DECLARE EXIT HANDLER FOR SQLWARNING SET @info= 'ERROR';