1、sql
DROP TABLE IF EXISTS `demo`; CREATE TABLE `demo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of demo -- ---------------------------- INSERT INTO `demo` VALUES (1, \'测试\'); INSERT INTO `demo` VALUES (2, \'测试2\'); INSERT INTO `demo` VALUES (3, \'测试3\'); INSERT INTO `demo` VALUES (32, \'测试2\'); INSERT INTO `demo` VALUES (33, \'测试2\'); INSERT INTO `demo` VALUES (34, NULL); INSERT INTO `demo` VALUES (35, \'测试3\'); INSERT INTO `demo` VALUES (36, \'测试3\'); INSERT INTO `demo` VALUES (37, \'测试3\'); INSERT INTO `demo` VALUES (38, \'xxx\'); SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT \'用户名称\', `birthday` date NULL DEFAULT NULL COMMENT \'生日\', `sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT \'性别\', `address` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT \'地址\', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES (1, \'王五\', NULL, \'2\', NULL); INSERT INTO `t_user` VALUES (2, \'张三\', \'2014-07-10\', \'1\', \'北京市\'); INSERT INTO `t_user` VALUES (3, \'张小明\', NULL, \'1\', \'河南郑州\'); INSERT INTO `t_user` VALUES (4, \'陈小明\', NULL, \'1\', \'河南郑州\'); INSERT INTO `t_user` VALUES (5, \'张三丰\', NULL, \'1\', \'河南郑州\'); INSERT INTO `t_user` VALUES (6, \'陈小明\', NULL, \'1\', \'河南郑州\'); INSERT INTO `t_user` VALUES (7, \'王五\', NULL, NULL, NULL); INSERT INTO `t_user` VALUES (8, \'小A\', \'2015-06-27\', \'2\', \'北京\'); INSERT INTO `t_user` VALUES (9, \'小B\', \'2015-06-27\', \'2\', \'北京\'); INSERT INTO `t_user` VALUES (10, \'小C\', \'2015-06-27\', \'1\', \'北京\'); INSERT INTO `t_user` VALUES (11, \'小D\', \'2015-06-27\', \'2\', \'北京\'); SET FOREIGN_KEY_CHECKS = 1;
2、无参数存储过程
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO() BEGIN SELECT * FROM DEMO; END$$ DELIMITER; 调用存储过程 CALL PRO()
3、输入参数的存储过程
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT) BEGIN SELECT * FROM DEMO WHERE ID = x; END$$ DELIMITER; 调用存储过程 CALL PRO(2)
4、输入输出参数的存储过程
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res VARCHAR(64)) BEGIN SELECT NAME INTO res FROM DEMO WHERE ID = x; END$$ DELIMITER; 调用存储过程 CALL PRO(2, @res); SELECT @res;
5、if-then-else 语句
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res VARCHAR(64)) BEGIN IF x = 1 THEN UPDATE DEMO SET NAME = \'AAA\' WHERE ID = x; ELSEIF x = 2 THEN UPDATE DEMO SET NAME = \'BBB\' WHERE ID = x; ELSE UPDATE DEMO SET NAME = \'CCC\' WHERE ID = x; END IF; SELECT NAME INTO res FROM DEMO WHERE ID = x; END$$ DELIMITER; 调用存储过程 CALL PRO(2, @res); SELECT @res;
6、case语句:
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res VARCHAR(64)) BEGIN CASE x WHEN 1 THEN UPDATE DEMO SET NAME = \'AAA\' WHERE ID = x; WHEN 2 THEN UPDATE DEMO SET NAME = \'BBB\' WHERE ID = x; ELSE UPDATE DEMO SET NAME = \'CCC\' WHERE ID = x; END CASE; SELECT NAME INTO res FROM DEMO WHERE ID = x; END$$ DELIMITER; 调用存储过程 CALL PRO(2, @res); SELECT @res;
7、while ···· end while:
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res INT) BEGIN DECLARE var INT; SET var = 0; WHILE var < x DO INSERT INTO DEMO (NAME) VALUES (\'NAME\' + var); SET var = var + 1; END WHILE; SELECT COUNT(1) INTO res FROM DEMO; END$$ DELIMITER; 调用存储过程 CALL PRO(3, @res); SELECT @res;
8、repeat···· end repea:
它在执行操作后检查结果,而 while 则是执行前进行检查。
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res INT) BEGIN DECLARE var INT; SET var = 0; REPEAT INSERT INTO DEMO (NAME) VALUES (\'NAME\' + var); SET var = var + 1; UNTIL var >= x END REPEAT; SELECT COUNT(1) INTO res FROM DEMO; END$$ DELIMITER; 调用存储过程 CALL PRO(3, @res); SELECT @res;
9、loop ·····end loop:
loop 循环不需要初始条件,这点和 while 循环相似,同时和 repeat 循环一样不需要结束条件, leave 语句的意义是离开循环。
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res INT) BEGIN DECLARE var INT; SET var = 0; LOOP_LABLE: LOOP INSERT INTO DEMO (NAME) VALUES (\'NAME\' + var); SET var = var + 1; IF var >=x THEN LEAVE LOOP_LABLE; END IF; END LOOP; SELECT COUNT(1) INTO res FROM DEMO; END$$ DELIMITER; 调用存储过程 CALL PRO(3, @res); SELECT @res;
10、ITERATE迭代:
LOOP 及 LEAVE、ITERATE
这里LOOP用来标记循环;
而LEAVE表示离开循环,好比编程里面的break一样;
ITERATE则继续循环,好比编程里面的continue一样。
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO(IN x INT, OUT res INT) BEGIN DECLARE var INT; SET var = 0; LOOP_LABLE: LOOP IF var = 2 THEN SET var = var + 1; ITERATE LOOP_LABLE; END IF; INSERT INTO DEMO (NAME) VALUES (\'NAME\' + var); SET var = var + 1; IF var >= x THEN LEAVE LOOP_LABLE; END IF; END LOOP; SELECT COUNT(1) INTO res FROM DEMO; END$$ DELIMITER; 调用存储过程 CALL PRO(4, @res); SELECT @res;
11、游标
MySQL中的游标可以理解成一个可迭代对象(类比Python中的列表、字典等可迭代对象),它可以用来存储select 语句查询到的结果集,这个结果集可以包含多行数据,从而使我们可以使用迭代的方法从游标中依次取出每行数据。
MySQL游标的特点:
1.只读:无法通过光标更新基础表中的数据。
2.不可滚动:只能按照select语句确定的顺序获取行。不能以相反的顺序获取行。 此外,不能跳过行或跳转到结果集中的特定行。
3.敏感:有两种游标:敏感游标和不敏感游标。敏感游标指向实际数据,不敏感游标使用数据的临时副本。敏感游标比一个不敏感的游标执行得更快,因为它不需要临时拷贝数据。MySQL游标是敏感的。
声明游标
游标声明必须在变量声明之后。如果在变量声明之前声明游标,MySQL将会发出一个错误。游标必须始终与select语句相关联。
declare cursor_name cursor for select_statement;
打开游标
使用open语句打开游标,只有先打开游标才能读取数据。
open cursor_name;
读取游标
使用fetch语句来检索游标指向的一行数据,并将游标移动到结果集中的下一行。
fetch cursor_name into var_name;
关闭游标
使用close语句关闭游标。
close cursor_name;
当游标不再使用时,应该关闭它。 当使用MySQL游标时,还必须声明一个notfound处理程序来处理当游标找不到任何行时的情况。 因为每次调用fetch语句时,游标会尝试依次读取结果集中的每一行数据。 当游标到达结果集的末尾时,它将无法获得数据,并且会产生一个条件。 处理程序用于处理这种情况。
declare continue handler for not found set type = 1;
type是一个变量,示游标到达结果集的结尾。
DROP PROCEDURE IF EXISTS PRO; DELIMITER $$ CREATE PROCEDURE PRO() BEGIN DECLARE id_tmp INT; DECLARE name_tmp VARCHAR(64); -- 遍历数据结束标志 DECLARE done INT DEFAULT FALSE; -- 游标 DECLARE cur_account CURSOR FOR select id,username from t_user; -- 将结束标志绑定到游标 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 打开游标 OPEN cur_account; -- 遍历 read_loop: LOOP FETCH NEXT from cur_account INTO id_tmp,name_tmp; IF done THEN LEAVE read_loop; END IF; INSERT INTO DEMO(ID,NAME) VALUES(id_tmp, name_tmp); END LOOP; CLOSE cur_account; END$$ DELIMITER; 调用存储过程 CALL PRO();