MySQL存储过程简析

创建存储过程:

#创建查看fruits表的存储过程:
#DELIMITER(定界符)设置结束符为// 防止与存储过程的;冲突。
 DELIMITER //
 CREATE PROCEDURE Proc()
     BEGIN
     SELECT * FROM fruits;
     END //
 #恢复结束符
 DELIMITER ;

 #调用
 CALL Proc ( );

#设置输出类型
#创建获取fruits表记录条数的存储过程:CountProc,COUNT(*)把结果放入参数param1
DELIMITER //
CREATE PROCEDURE CountProc ( OUT param1 INT ) BEGIN
	SELECT
		COUNT( * ) INTO param1 
	FROM
		fruits;
	
END // 
DELIMITER;

存储函数

#创建存储函数:NameByZip,返回SELECT语句的查询结果,为字符串型:
 DELIMITER //
 CREATE FUNCTION NameByZip()
 RETURNS CHAR(50)
 RETURN   (SELECT s_name FROM suppliers WHERE s_call= '48075');
 //
 DELIMITER ;

变量

#直接定义:
DECLARE  myparam  INT  DEFAULT 100;
DECLARE var1, var2, var3 INT;
SET var1 = 10, var2 = 20;
SET var3 = var1 + var2;

#通过SELECT ... INTO为一个或多个变量赋值:
DECLARE fruitname CHAR(50);
DECLARE fruitprice DECIMAL(8,2);

SELECT f_name,f_price INTO fruitname, fruitprice
FROM fruits WHERE f_id ='a1';

定义条件和处理程序

  • 作用:预判错误,对应处理
#定义"ERROR 1148(42000)"错误,名称为command_not_allowed:
//方法一:使用sqlstate_value 
DECLARE  command_not_allowed CONDITION FOR SQLSTATE '42000';
//方法二:使用mysql_error_code 
DECLARE  command_not_allowed CONDITION  FOR  1148
#定义处理程序:
//方法一:捕获sqlstate_value 
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='NO_SUCH_TABLE';

//方法二:捕获mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info=' NO_SUCH_TABLE ';

//方法三:先定义条件,然后调用
DECLARE  no_such_table  CONDITION  FOR  1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info=' NO_SUCH_TABLE ';

//方法四:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';

//方法五:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info=' NO_SUCH_TABLE ';

//方法六:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR'; 

#定义条件和处理程序,具体执行的过程如下:
 CREATE TABLE test.t (s1 int,primary key (s1));
Query OK, 0 rows affected (0.00 sec)

 DELIMITER //
 
 CREATE PROCEDURE handlerdemo ()
      BEGIN
       DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
       SET @x = 1;
       INSERT INTO test.t VALUES (1);
       SET @x = 2;
       INSERT INTO test.t VALUES (1);
       SET @x = 3;
     END;
     // 
 DELIMITER ;

/*调用存储过程*/
 CALL handlerdemo();
Query OK, 0 rows affected (0.00 sec)
/*查看调用过程结果*/
 SELECT @x;
    +------+
    | @x   |
    +------+
    | 3    |
    +------+
    1 row in set (0.00 sec)

光标

  • 仅在存储过程,存储函数中使用
#声明光标的名称为cur_fruit,SELECT语句部分从fruits表中查询出f_name和f_price字段的值。
DECLARE cursor_fruit CURSOR FOR SELECT f_name, f_price FROM fruits ;

#使用名称为cursor_fruit的光标。将查询出来的数据存入fruit_name和fruit_price这两个变量中:
FETCH  cursor_fruit INTO fruit_name, fruit_price ;
上面的示例中,将光标cursor_fruit中SELECT语句查询出来的信息存入fruit_name和fruit_price中。fruit_name和fruit_price必须在前面已经定义。

#关闭名称为cursor_fruit的光标:
CLOSE  cursor_fruit; 

流程控制

#IF语句:
IF val IS NULL THEN
	SELECT
		'val is NULL';
	ELSE SELECT
		'val is not NULL';

END IF;

#CASE流程控制语句的第1种格式,判断val值等于1、等于2,或者两者都不等,语句如下:
#当val值为1时,输出字符串“val is 1”;当val值为2时,输出字符串“val is 2”;否则输出字符串“val is not 1 or 2”。

CASE val 
	WHEN 1 THEN
	SELECT
		'val is 1';
	
	WHEN 2 THEN
	SELECT
		'val is 2';
	ELSE SELECT
		'val is not 1 or 2';

END CASE;

#使用CASE流程控制语句的第2种格式,判断val是否为空、小于0、大于0或者等于0,语句如下:
#当val值为空,输出字符串“val is NULL”;当val值小于0时,输出字符串“val is less than 0”;当val值大于0时,输出字符串“val is greater than 0”;否则输出字符串“val is 0”。
CASE
  WHEN val IS NULL THEN SELECT 'val is NULL';
  WHEN val < 0 THEN SELECT 'val is less than 0';
  WHEN val > 0 THEN SELECT 'val is greater than 0';
  ELSE SELECT 'val is 0';
END CASE;


#LOOP语句进行循环操作,id值小于等于10之前,将重复执行循环过程:
DECLARE id INT DEFAULT 0;
add_loop: LOOP  
SET id = id + 1;
  IF id >= 10 THEN  LEAVE add_loop;
  END IF;
END LOOP add_ loop; 

#使用LEAVE语句退出循环:
add_num: LOOP  
SET @count=@count+1;
IF @count=50 THEN LEAVE add_num ;
END LOOP add_num ; 
该示例循环执行count加1的操作。当count的值等于50时,使用LEAVE语句跳出循环。

#ITERATE语句示例:
CREATE PROCEDURE doiterate()
BEGIN
DECLARE p1 INT DEFAULT 0;
my_loop: LOOP
  SET p1= p1 + 1;
  IF p1 < 10 THEN ITERATE my_loop;
  ELSEIF p1 > 20 THEN LEAVE my_loop;
  END IF;
  SELECT 'p1 is between 10 and 20';
END LOOP my_loop;
END

#REPEAT语句示例,id值小于等于10之前,将重复执行循环过程:
DECLARE id INT DEFAULT 0;
REPEAT
SET id = id + 1;
UNTIL  id >= 10
END REPEAT; 
该示例循环执行id加1的操作。当id值小于10时,循环重复执行;当id值大于或者等于10时,使用LEAVE语句退出循环。REPEAT循环都以END REPEAT结束。

#WHILE语句示例,id值小于等于10之前,将重复执行循环过程:
DECLARE i INT DEFAULT 0;
WHILE i < 10 DO
SET i = i + 1;
END WHILE;

调用

#定义名为CountProc1的存储过程:
#该存储过程返回了指定s_id=101的水果商提供的水果种类,返回值存储在num变量中,使用SELECT查看,返回结果为3。

DELIMITER //
 CREATE PROCEDURE CountProc1 (IN sid INT, OUT num INT)
     BEGIN
       SELECT COUNT(*) INTO num FROM fruits WHERE s_id = sid;
     END //
DELIMITER ;

#调用存储过程:
 CALL CountProc1 (101, @num);
Query OK, 1 row affected (0.00 sec)
查看返回结果:
 select @num;
+------+
| @num |
+------+
|    3 |
+------+
1 row in set (0.02 sec)


#定义存储函数CountProc2,然后调用这个函数:
 DELIMITER //
 CREATE FUNCTION  CountProc2 (sid INT)
     RETURNS INT
     BEGIN
     RETURN (SELECT COUNT(*) FROM fruits WHERE s_id = sid);
     END //
Query OK, 0 rows affected (0.00 sec)
  DELIMITER ;
调用存储函数:
 SELECT CountProc2(101);
+--------------------+
| Countproc(101) |
+--------------------+
|             3 |
+-------------------+

【例10.24SHOW STATUS语句示例:
SHOW PROCEDURE STATUS LIKE 'C%'\G

【例10.25SHOW CREATE语句示例:
SHOW CREATE FUNCTION test.CountProc \G

【例10.26】从Routines表中查询名称为CountProc的存储函数的信息:
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='CountProc'  AND  ROUTINE_TYPE = 'FUNCTION' \G

【例10.27】修改存储过程CountProc的定义。将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行:
ALTER  PROCEDURE  CountProc  
MODIFIES SQL DATA
SQL SECURITY INVOKER ; 
执行代码,并查看修改后的信息。结果显示如下:
//执行ALTER PROCEDURE语句
 ALTER  PROCEDURE  CountProc
     MODIFIES SQL DATA  
     SQL SECURITY INVOKER ;
Query OK, 0 rows affected (0.00 sec)  
//查询修改后的CountProc表信息  
 SELECT SPECIFIC_NAME,SQL_DATA_ACCESS,SECURITY_TYPE
      FROM information_schema.Routines
     WHERE ROUTINE_NAME='CountProc' AND ROUTINE_TYPE='PROCEDURE';

【例10.28】修改存储函数CountProc的定义。将读写权限改为READS SQL DATA,并加上注释信息“FIND NAME”:
ALTER  FUNCTION  CountProc
READS SQL DATA  
COMMENT 'FIND NAME' ; 
执行代码,并查看修改后的信息。结果显示如下:
//执行ALTER FUNCTION语句
 ALTER  FUNCTION  CountProc  
     READS SQL DATA  
     COMMENT 'FIND NAME' ;  
Query OK, 0 rows affected (0.00 sec)  
//查询修改后f表的信息
 SELECT SPECIFIC_NAME,SQL_DATA_ACCESS,ROUTINE_COMMENT 
FROM information_schema.Routines 
WHERE ROUTINE_NAME='CountProc'  AND  ROUTINE_TYPE = 'FUNCTION'  ;

【例10.29】删除存储过程和存储函数:
DROP PROCEDURE CountProc;
DROP FUNCTION CountProc;
语句的执行结果如下:
 DROP PROCEDURE CountProc;
Query OK, 0 rows affected (0.00 sec)
 DROP FUNCTION CountProc;
Query OK, 0 rows affected (0.00 sec)
上面语句的作用就是删除存储过程CountProc和存储函数CountProc。


错误

权限问题

1418 - 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), Time: 0.000000s

  • 二进制日志启用后,这个变量就会启用,默认0不让创建存储过程
show variables like 'log_bin_trust_function_creators';
set global log_bin_trust_function_creators=1 
发布了64 篇原创文章 · 获赞 45 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yuhezheg/article/details/104111133