mysql 事务 游标_mysql的存储过程、事务、游标知识点总结

mysql的存储过程、事务、游标详解

mysql的存储过程、游标 、事务实例详解

下面是自己曾经编写过的mysql数据库存储过程,留作存档,以后用到的时候拿来参考。

其中,涉及到了存储过程、游标(双层循环)、事务。

【说明】:代码中的注释只针对当时业务而言,无须理会。

代码如下:

DELIMITER $$

DROP PROCEDURE IF EXISTS `transferEmailTempData`$$

CREATE PROCEDURE transferEmailTempData(IN jobId VARCHAR(24))

BEGIN

DECLARE idval VARCHAR(24) DEFAULT '';

DECLARE taskIdval VARCHAR(24) DEFAULT '';

DECLARE groupIdval VARCHAR(24) DEFAULT '';

DECLARE emailval VARCHAR(50) DEFAULT '';

/*标识正式表是否存在一条相同数据,即:groupId、email相同*/

DECLARE infoId VARCHAR(24) DEFAULT '';

/*标识事务错误*/

DECLARE err INT DEFAULT 0;

/*达到一定数量就进行提交,计数器*/

DECLARE counts INT DEFAULT 0;

/*标识是否回滚过*/

DECLARE isrollback INT DEFAULT 0;

/*游标遍历时,作为判断是否遍历完全部记录的标记*/

DECLARE done INTEGER DEFAULT 0;

/*获取临时表该任务的数据*/

DECLARE cur CURSOR FOR SELECT id,taskId,groupId,email FROM `t_email_data_temp` WHERE taskId=jobId;

/*根据群组id、email查询是否存在相同记录*/

DECLARE cur2 CURSOR FOR SELECT id FROM `t_email_info` e WHERE e.`group_id` = groupIdval AND e.`email_address` = emailval;

/* 出现错误,设置为1,只要发生异常就回滚*/

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET err=1;

/*声明当游标遍历完全部记录后将标志变量置成某个值*/

DECLARE CONTINUE HANDLER FOR NOT FOUND

SET done=1;

/*开启事务*/

START TRANSACTION;

/*打开游标*/

OPEN cur;

/*使用LOOP循环遍历*/

out_loop:LOOP

/*将每一条结果对应的字段值赋值给变量*/

FETCH cur INTO idval,taskIdval,groupIdval,emailval;

IF done = 1 THEN

LEAVE out_loop;

END IF;

/*打开第二个游标*/

OPEN cur2;

SET done = 0;

FETCH cur2 INTO infoId;

/*如果正式表不存在相同groupId and email记录,添加到正式表*/

IF done = 1 THEN

/*插入正式表*/

INSERT INTO `t_email_info` VALUES(idval,emailval,groupIdval,0,'',NOW(),'admin',NOW(),'admin');

/*删除临时数据*/

DELETE FROM `t_email_data_temp` WHERE id = idval;

/*计数器,每1000条才提交*/

SET counts = counts + 1;

/*发生异常,回滚*/

IF err=1 THEN

SET isrollback=1;

ROLLBACK;

ELSE

IF counts = 1000 THEN

COMMIT;

/*达到1000条提交后,重置计数器*/

SET counts=0;

END IF;

END IF;

ELSE

/*已经存在相同记录,则删除该记录*/

IF done=0 THEN

DELETE FROM `t_email_data_temp` WHERE id = idval;

END IF;

END IF;

FETCH cur2 INTO infoId;

CLOSE cur2;

/*控制外部的循环,该步骤不能缺少,否则只循环一次就结束了*/

SET done=0;

END LOOP out_loop;

CLOSE cur;

/*如果没有发生过回滚事件,则更新task状态*/

/*如果回滚过,不更新task状态,下次执行任务的时候,会再次将剩余没有提交的数据进行添加到正式表*/

IF isrollback=0 THEN

UPDATE `t_email_task` t SET t.`if_finish` = 1 WHERE t.`id`=jobId;

END IF;

END$$

DELIMITER ;

窥探mysql存储过程细节

存储过程,可以这样认为,将我们需要特殊处理的sql语句封装成函数,当需要的时候我们只需调用这个函数就可以实现我们想要的操作,这个过程我们可以称之为存储过程。当然了,真正存储过程的定义不是这样的。但是我们可以这样简单的去理解存储过程。

下面我们看一个简单的使用存储过程的例子。

首先我们新建一张表 proced:

create table proced(

id int(5) primary key auto_increment,

name varchar(50),

type varchar(50)

);

然后我们需要向这个表中插入10万条数据,这个时候我们需要借助存储过程来实现这一功能。

mysql> delimiter //

mysql> create procedure adddata()

-->begin

-->declare n int default 0;

-->while n<100000

-->do

-->insert into proced(name,type) values(‘迹忆博客','onmpw');

-->set n = n+1;

-->end while;

-->end

-->//

mysql> delimiter ;

mysql> call adddata();

使用上述存储过程,我们就可以向proced表中插入10万条数据了。

借助上述小例子,我们来讲一下如何创建一个存储过程。

创建存储过程

首先我们来看一下创建存储过程的语法:

CREATE PROCEDURE procedure_name(IN/OUT/INOUT parameter TYPE)

BEGIN

procedure_body

END

这个过程比较简单。

在上面的小例子中我们看到在创建存储过程之前使用了delimiter //;,创建完成之后又再次 使用了命令 delimiter ;。

delimiter 是界定符,我们知道,在mysql命令行客户端,是通过分号(;)来界定一个命令是否完成的。在存储过程中,我们会多次使用到分号,但是这并不代表命令的结束,所以说我们需要使用delimiter命令来改变这个界定符。

mysql> delimiter //; 改变界定符为 //

mysql> delimiter ; 重新改变界定符为分号

所以说我们如果使用mysql命令行创建存储过程的话,我们必须在创建存储过程之前使用上述命令改变界定符。

接下来我们看到procedure_name()中的IN/OUT/INOUT,这是代表什么意思呢?

一个IN类型的参数会传递一个值到存储哦过程中,也就是我们在编程语言中自定义函数的参数。如果参数前面没有指定是IN/OUT/INOUT,那默认会是IN,看下面的例子:

mysql>delimiter //

mysql> create procedure in_proced(IN param VARCHAR(100))

-->begin

-->insert into proced(name,type) values(param,'onmpw');

-->end

-->//

mysql>delimiter ;

mysql> call in_proced(‘onmpw.com');

这就是在参数前指定IN的含义。

下面我们看OUT,指定为OUT的参数将从存储过程中传递一个值给调用者,也就是说,OUT可以认为这个参数就是我们自定义函数中的返回值。

mysql> delimiter //

mysql> create procedure out_proced(OUT param INT)

-->begin

-->select count(*) into param from proced;

-->end

-->//

mysql>delimiter ;

mysql> call out_proced(@a);

mysql>select @a;

+------+

| @a |

+------+

| 3 |

+------+

最后就是INOUT,很明显INOUT指定的参数被调用者初始化,其值在存储过程中可以被修改,并且任何改变对于调用者来说都是可见的。

看下面的例子:

mysql> delimiter //

mysql> create procedure inout_proced(INOUT param INT)

--> begin

--> select count(*) into param from proced where id>param;

--> end

-->//

mysql>delimiter ;

mysql>set @a = 3;

mysql>call inout_proced(@a);

mysql>select @a; 查看变量的值是否改变

以上就是创建一个简单的存储过程的方式。

删除存储过程

删除存储过程的语法:

DROP PROCEDURE IF EXISTS procedure_name

下面是使用实例:

mysql>drop procedure if exists proced;

修改存储过程

存储过程的修改时不能改变存储过程内的sql语句的,只能改变其属性,其语法如下:

ALTER PROCEDURE proc_name [characteristic ...]

characteristic:

COMMENT 'string'

| LANGUAGE SQL

| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

| SQL SECURITY { DEFINER | INVOKER }

总结:无论是删除存储过程还是修改存储过程,必须保证你要修改或者删除存储过程没有被其他存储过程使用,例如你有存储过程A,和存储过程B。A在B中被使用,如果我们想修改A或者删除A,必须确保B中不再使用A,否则如果我们删除A以后,再调用B的时候就会报错。

举个例子:

mysql>delimiter //

mysql>create procedure A(IN pa1 INT,OUT pa2 INT)

-->begin

-->select count(*) into pa2 from proced where id>pa1;

-->end

-->//

mysql>create procedure B(INOUT pa INT)

-->begin

-->declare v int;

-->call A(pa,v);

-->set pa = v;

-->end

-->//

mysql>delimiter ;

mysql>drop procedure A;

mysql>set @a=5;

mysql>call B(@a);

ERROR 1305 (42000): PROCEDURE test.A does not exists

以上就是对存储过程简单的介绍,希望对大家学习mysql存储过程有所帮助。

以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值