mysql_17_存储过程和函数
1 -- 第十一章:存储过程和函数 2 -- 第一节:存储过程和函数的引入 3 -- 存储过程核函数是在数据库中定义一些sql语句的集合,然后直接调用这些存储过程核函数来执行已经定义好的 4 -- sql语句。存储过程核函数可以避免开发人员重复的编写相同的sql语句。而且,存储过程和函数是在Mysql服务 5 -- 器中存储和执行的,可以减少客户端和服务端的数据传输; 6 7 8 -- 第二节:创建存储过程和函数 9 -- 2.1创建存储过程 10 -- CREATE PROCEDURE sp_name([proc_parameter[,...]]) 11 -- [characteristic...] routine_body 12 -- sp_name 参数是存储过程的名称; 13 -- proc_parameter 表示存储过程的参数列表; 14 -- characteristic 参数指定存储过程的特性; 15 -- routine_body 参数是 SQL 代码的内容,可以用 BEGIN...END 来标志 SQL 代码的开始和结束。 16 -- proc_parameter 中的每个参数由 3 部分组成。这 3 部分分别是输入输出类型、参数名称和参数类型。 17 -- [ IN | OUT | INOUT ] param_name type 18 -- 其中,IN 表示输入参数;OUT 表示输出参数;INOUT 表示既可以是输入,也可以是输出;param_name 参数是 19 -- 存储过程的参数名称;type 参数指定存储过程的参数类型,该类型可以是 MySQL 数据库的任意数据类型; 20 -- Characteristic 参数有多个取值。其取值说明如下: 21 -- LANGUAGE SQL:说明 routine_body 部分是由 SQL 语言的语句组成,这也是数据库系统默认的语言。 22 -- [ NOT ] DETERMINISTIC :指明存储过程的执行结果是否是确定的。DETERMINISTIC 表示结果是确定的。每 23 -- 次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC 表示结果是非确定的,相同的输入 24 -- 可能得到不同的输出。默认情况下,结果是非确定的。 25 -- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } :指明子程序使用 SQL 语句的限制; 26 -- CONTAINS SQL 表示子程序包含 SQL 语句,但不包含读或写数据的语句;NO SQL 表示子程序中不包含 SQL 27 -- 语句;READS SQL DATA 表示子程序中包含读数据的语句;MODIFIES SQL DATA 表示子程序中包含写数据的 28 -- 语句。默认情况下,系统会指定为 CONTAINS SQL; 29 -- SQL SECURITY { DEFINER | INVOKER };指明谁有权限来执行。DEFINER 表示只有定义者自己才能够执行; 30 -- INVOKER 表示调用者可以执行。默认情况下,系统指定的权限是 DEFINER。 31 -- COMMENT ‘string’ :注释信息; 32 USE db_book; 33 34 CREATE PROCEDURE pro_book (IN bT INT,OUT count_num INT) 35 READS SQL DATA 36 BEGIN 37 SELECT COUNT(*) FROM t_book WHERE bookTypeId=bT; 38 END 39 40 -- 使用存储过程 41 CALL pro_book(1,@total); -- @total:会话变量,写上就是全局变量,不写就是局部变量 42 43 -- 2.2创建存储函数 44 -- CREATE FUNCTION sp_name ( [func_parameter[,...]] ) 45 -- RETURNS type 46 -- [ characteristic... ] routine_body 47 -- sp_name 参数是存储函数的名称;func_parameter 表示存储函数的参数列表;RETURNS type 指定返回值的 48 -- 类型;characteristic 参数指定存储过程的特性,该参数的取值与存储过程中的取值是一样的;routine_body 参数 49 -- 是 SQL 代码的内容,可以用 BEGIN...END 来标志 SQL 代码的开始和结束; 50 -- func_parameter 可以由多个参数组成,其中每个参数由参数名称和参数类型组成,其形式如下: 51 -- param_name type 其中,param_name 参数是存储函数的参数名称;type 参数指定存储函数的参数类型, 52 -- 该类型可以是 MySQL 数据库的任意数据类型; 53 CREATE FUNCTION func_book(bookId INT) 54 RETURNS VARCHAR(20) 55 BEGIN 56 RETURN(SELECT bookName FROM t_book WHERE id=bookId); 57 END 58 59 -- 使用存储函数 60 SELECT func_book(1); 61 62 63 -- 2.3变量的使用 64 CREATE TABLE t_user( 65 id int PRIMARY KEY NOT NULL auto_increment, 66 userName VARCHAR(20), 67 password VARCHAR(20) 68 ) 69 -- 1.定义变量 70 -- DECLARE var_name [,...] type [ DEFAULT value ] 71 CREATE PROCEDURE pro_user() 72 BEGIN 73 DECLARE a,b VARCHAR(20); 74 INSERT INTO t_user VALUES (NULL,a,b); 75 END 76 77 -- 调用pro_user存储过程 78 CALL pro_user(); 79 SELECT * FROM t_user;-- 可知变量默认为:NULL 80 81 -- 2.为变量赋值 82 -- SET var_name = expr [,var_name=expr] ... 83 CREATE PROCEDURE pro_user2() 84 BEGIN 85 DECLARE a,b VARCHAR(20); 86 SET a="haha",b="heihei";-- 为变量赋值 87 INSERT INTO t_user VALUES (NULL,a,b); 88 END 89 90 -- 调用pro_user2存储过程 91 CALL pro_user2(); 92 SELECT * FROM t_user; 93 94 -- SELECT col_name[,...] INTO var_name[,...] 95 -- FROM table_name WHERE condition 96 CREATE TABLE t_user2( 97 id2 int PRIMARY KEY NOT NULL auto_increment, 98 userName2 VARCHAR(20), 99 password2 VARCHAR(20) 100 ) 101 INSERT INTO t_user2 VALUES (NULL,"zhangsan","zhangsan123"); 102 103 CREATE PROCEDURE pro_user3() 104 BEGIN 105 DECLARE a,b VARCHAR(20); 106 SELECT userName2,password2 INTO a,b FROM t_user2 WHERE id2=1; 107 INSERT INTO t_user VALUES (NULL,a,b); 108 END 109 110 -- 调用pro_user2存储过程 111 CALL pro_user3(); 112 SELECT * FROM t_user2; 113 SELECT * FROM t_user; 114 115 -- 2.4游标的使用 116 INSERT INTO t_user2 VALUES (NULL,"lisi","Lisi_2580"); 117 -- 查询语句可能查询出多条记录,在存储过程和函数中使用游标来逐条读取查询结果集中的记录。 118 -- 游标的使用包括声明游标、打开游标、使用游标、和关闭游标。游标必须声明在处理程序之前, 119 -- 并且声明在变量和条件之后。 120 -- 1.游标声明 121 -- DECLARE cursor_name CURSOR FOR select_statement; 122 -- 2.打开游标 123 -- OPEN cursor_name; 124 -- 3.使用游标 125 -- FETCH cursor_name INTO var_name[,var_name...]; 126 -- 4.关闭游标 127 -- CLOSE cursor_name; 128 CREATE PROCEDURE pro_user4() 129 BEGIN 130 DECLARE a,b VARCHAR(20); 131 DECLARE cur_t_user2 CURSOR FOR SELECT userName2,password2 from t_user2 WHERE id2=2;-- 声明游标 132 OPEN cur_t_user2;-- 打开游标 133 FETCH cur_t_user2 INTO a,b;-- 使用游标 134 INSERT INTO t_user VALUES (NULL,a,b); 135 close cur_t_user2;-- 关闭游标 136 END 137 138 CALL pro_user4(); 139 SELECT * FROM t_user2; 140 SELECT * FROM t_user; 141 142 -- 2.5流程控制的使用 143 -- 存储过程和函数中可以使用流程控制来控制语句的执行。Mysql中可以使用IF语句、CASE语句、LOOP 144 -- 语句、LEAVE 语句、ITERATE 语句、REPEAT 语句和 WHILE 语句来进行流程控制。 145 -- 1.IF语句 146 -- IF search_condition THEN statement_list 147 -- [ ELSEIF search_condition THEN statement_list ]... 148 -- [ ELSE statement_list ] 149 -- END IF 150 CREATE PROCEDURE pro_user5(IN bookId INT) 151 BEGIN 152 SELECT COUNT(*) INTO @num FROM t_user WHERE id= bookId; 153 IF @num>0 THEN UPDATE t_user SET userName="已更新" WHERE id=bookId; 154 ELSE 155 INSERT INTO t_user VALUES (NULL,"已插入","已设密码"); 156 END IF; 157 END 158 159 SELECT * FROM t_user; 160 161 CALL pro_user5(2); 162 SELECT * FROM t_user; 163 164 CALL pro_user5(5); 165 SELECT * FROM t_user; 166 167 -- 2.CASE语句 168 -- CASE case_value 169 -- WHEN when_value THEN statement_list 170 -- [WHEN when_value THEN statement_list]... 171 -- [ELSE statement_list ] 172 -- END CASE 173 CREATE PROCEDURE pro_user6(IN bookId INT) 174 BEGIN 175 SELECT COUNT(*) INTO @num FROM t_user WHERE id= bookId; 176 CASE @num 177 WHEN 1 THEN UPDATE t_user SET userName="CASE已更新" WHERE id=bookId; 178 WHEN 6 THEN INSERT INTO t_user VALUES (NULL,"CASE已插入","CASE已设密码"); 179 ELSE INSERT INTO t_user VALUES (NULL,"CASE_ELSE已插入","CASE_ELSE已设密码"); 180 END CASE; 181 END 182 183 SELECT * FROM t_user; 184 185 CALL pro_user6(1); 186 SELECT * FROM t_user; 187 188 CALL pro_user6(6); 189 SELECT * FROM t_user; 190 191 CALL pro_user6(7); 192 SELECT * FROM t_user; 193 -- 3.LOOP,LEAVE语句 194 -- LOOP 语句可以使某些特定的语句重复执行,实现一个简单的循环。但是 LOOP 语句本身没有停止循环 195 -- 的语句,必须是遇到 LEAVE 语句等才能停止循环。LOOP 语句的语法的基本形式如下: 196 -- [begin_label:]LOOP 197 -- Statement_list 198 -- END LOOP [ end_label ] 199 -- LEAVE 语句主要用于跳出循环控制。语法形式如下: 200 -- LEAVE label 201 DELETE FROM t_user; 202 203 CREATE PROCEDURE pro_user7(IN totalNum INT) 204 BEGIN 205 abc:LOOP 206 IF totalNum=0 THEN LEAVE abc; 207 ELSE INSERT INTO t_user VALUES (totalNum,"LOOP已插入","LOOP已设密码"); 208 END if; 209 SET totalNum=totalNum-1; 210 END LOOP abc; 211 END 212 213 SELECT * FROM t_user; 214 CALL pro_user7(10); 215 SELECT * FROM t_user; 216 217 DELETE FROM t_user; 218 DROP PROCEDURE pro_user7; 219 220 -- 4.ITERATE语句 221 -- ITERATE 语句也是用来跳出循环的语句。但是,ITERATE 语句是跳出本次循环,然后直接进入下一次 222 -- 循环。基本语法: 223 -- ITERATE label ; 224 DELETE FROM t_user; 225 226 CREATE PROCEDURE pro_user8(IN totalNum INT) 227 BEGIN 228 abc:LOOP 229 SET totalNum=totalNum-1; 230 IF totalNum=0 THEN LEAVE abc; 231 ELSEIF totalNum=5 THEN ITERATE abc; 232 END if; 233 INSERT INTO t_user VALUES (totalNum,"LOOP已插入","LOOP已设密码"); 234 END LOOP abc; 235 END 236 237 SELECT * FROM t_user; 238 CALL pro_user8(10); 239 SELECT * FROM t_user; 240 241 DELETE FROM t_user; 242 243 -- 5.REPEAT语句 244 -- REPEAT 语句是有条件控制的循环语句。当满足特定条件时,就会跳出循环语句。REPEAT 语句的基本 245 -- 语法形式如下: 246 -- [ begin_label : ] REPEAT 247 -- Statement_list 248 -- UNTIL search_condition 249 -- END REPEAT [ end_label ] 250 DELETE FROM t_user; 251 252 CREATE PROCEDURE pro_user9(IN totalNum INT) 253 BEGIN 254 REPEAT 255 SET totalNum=totalNum-1; 256 INSERT INTO t_user VALUES (totalNum,"已插入","已设密码"); 257 UNTIL totalNum=3 -- 此处不能加分号 258 END REPEAT; 259 END 260 261 SELECT * FROM t_user; 262 CALL pro_user9(10); 263 SELECT * FROM t_user; 264 265 DELETE FROM t_user; 266 267 -- 6.WHILE语句 268 -- [ begin_label : ] WHILE search_condition DO 269 -- Statement_list 270 -- END WHILE [ end_label ] 271 DELETE FROM t_user; 272 273 CREATE PROCEDURE pro_user10(IN totalNum INT) 274 BEGIN 275 WHILE totalNum>0 DO 276 INSERT INTO t_user VALUES (totalNum,"WHILE已插入","WHILE已设密码"); 277 SET totalNum=totalNum-1; 278 END WHILE; 279 END 280 281 SELECT * FROM t_user; 282 CALL pro_user10(10); 283 SELECT * FROM t_user; 284 285 DELETE FROM t_user; 286 287 288 -- 第三节:调用存储过程和函数 289 -- 3.1调用存储过程 290 -- CALL sp_name( [parameter[,...]] ) 291 -- 3.2调用存储函数 292 -- fun_name( [parameter[,...]] ) 293 294 295 -- 第四节:查看存储过程和函数 296 -- 4.1 SHOW STATUS 语句查看存储过程和函数的状态 297 -- SHOW { PROCEDURE | FUNCTION } STATUS [ LIKE ‘pattern’ ] ; 298 SHOW PROCEDURE STATUS LIKE "pro_%"; 299 SHOW FUNCTION STATUS LIKE "func_book"; 300 301 -- 4.2 SHOW CREATE 语句查看存储过程和函数的定义 302 -- SHOW CREATE { PROCEDURE | FUNCTION } sp_name; 303 SHOW CREATE PROCEDURE pro_book; 304 SHOW CREATE FUNCTION func_book; 305 306 -- 4.3 从information_schema.Routines表中查看存储过程和函数的信息 307 308 309 -- 第五节:修改存储过程和函数 310 -- ALTER { PROCEDURE | FUNCTION } sp_name [ characteristic ... ] 311 -- characteristic : 312 -- { CONTAINS SQL } NO SQL | READS SQL DATA | MODIFIES SQL DATA } 313 -- | SQL SECURITY { DEFINER | INVOKER } 314 -- | COMMENT ‘string’ 315 -- 其中: 316 -- sp_name 参数表示存储过程或函数的名称; 317 -- characteristic 参数指定函数的特性。 318 -- CONTAINS SQL 表示子程序包含 SQL 语句,但不包含读或写数据的语句; 319 -- NO SQL 表示子程序中不包含 SQL 语句; 320 -- READS SQL DATA表示子程序中包含数据的语句; 321 -- MODIFIES SQL DATA 表示子程序中包含写数据的语句。 322 -- SQL SECURITY{ DEFINER | INVODER } 指明谁有权限来执行。 323 -- DEFINER 表示只有定义者自己才能够执行; 324 -- INVODER 表示调用者可以执行。 325 -- COMMENT ‘string’ 是注释信息。 326 SHOW PROCEDURE STATUS LIKE "pro_book"; 327 ALTER PROCEDURE pro_book COMMENT "测试一个comment"; 328 SHOW PROCEDURE STATUS LIKE "pro_book"; 329 330 ALTER PROCEDURE pro_book COMMENT ""; 331 SHOW PROCEDURE STATUS LIKE "pro_book"; 332 333 334 -- 第六节:删除存储过程和函数 335 -- DROP {PROCEDURE | FUNCTION } sp_name ; 336 DROP PROCEDURE pro_user10; 337 DROP FUNCTION func_book;