创建存储过程:
#创建查看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.24】SHOW STATUS语句示例:
SHOW PROCEDURE STATUS LIKE 'C%'\G
【例10.25】SHOW 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