问题描述
采购和接口对接的时候,因为沟通问题,导致采购提前放了问题数据订单进来,导致了两千多问题订单,还有七百多有效的问题订单,为了避免浪费,需要将这两千多有效的问题订单数据补全。
修复思路
订单表中数据缺失,用户表中有对应缺失信息。无法找回的信息固定写死一个值即可。
三种方式:
- 最笨的:从日志中,找回数据,然后手动填充到db。
- 正经开发人员:写一个程序,循环读取db,关联到乘客信息,然后将缺失的信息补充到订单表中即可。
- 伟大的DBA:写个while循环,读取出来所有的问题订单数据,记录值,while的判断就是剩余问题订单数量大于0,处理方式是,取limit 0,1条数据,然后将数据的id拿出来,关联到用户表,将用户信息中的字段拿出来,反修改到订单表中。然后将总数值重新查一下,进入下一轮循环。循环结束后,问题订单应该是已经被全部修复了。
我当然选择伟大的DBA形式了,前两种对我来说so easy,但是费时费力,有dba经验的开发人员,还是想自我提升db功底的~
修复过程
首先来一个mysql的while循环格式,so easy,随手就来。写好了格式,按照思路来一套,先查出来订单总数,记录到变量中(尝试了一下,while循环好像不支持直接查询然后比较,也可能是我的语法错误,待会儿贴出代码,有问题的话,或者有改进方案,欢迎评论指责我,我们一同进步嘛)。进while循环判断,判断是否大于0,如果大于0,开始业务逻辑。先查出来limit 0,1条数据,拿到id保存到变量中,通过id去查用户信息,拿到用户信息里面的有用数据,保存到变量中。update订单表,根据id修改,将数据赋值过去(根据id,防止不小心修改多条)。再查一下目前的问题订单数,更新变量值,进入下一轮循环。
采坑记录
这么完美的逻辑怎么会还有坑呢!!!!!
问题记录
- 首先运行,提示第一行有错误。单独运行的时候,第一行没问题,可以正常运行。
- 将第一行提出来,用变量保存,while循环用变量判断,依然提示有问题
- 将结束符修改一下,依然有问题。(知识点)
- 将变量提前定义。还是不行。(知识点)
- 百度发现,mysql的while循环只能放到存储过程中使用,无法单独执行。原谅我的无知,存储过程搞起!
- 将脚本放到存储过程中,依然报错 - -!!,报第一行有sql问题。我的sql有问题,肯定是sql问题了,内部都可以执行,那就肯定出在while格式上面。
- 百度mysql的while格式,一行一行,一个字母一个字母的比对,看看我的问题在哪,一个空格都不能少。最终发现第一行的格式一模一样,不会有错的呀。
- 换一个思路,没有报错的也看一下,业务sql没问题,就不用看了,继续往下看。终于比对出问题,其他的end可以不加结束符,但是while的结束符需要加上结束符 ';'。真难受啊,还是太膨胀!终于找到问题了。
知识点
- mysql的函数或者存储过程中,如果你要写多条sql一起执行,全部执行完z之后才需要结果的话,就需要将结束符修改一下。mysql的结束符是 ';',写存储过程的时候,每一条sql后面的结束符你都需要加上‘;’,这样的话,会导致一条sql执行完就整个结束了。为了避免这种情况,需要将结束符修改成其他的,全部结束后,再将结束符修改回来。
DELIMITER $$
BEGIN
.......
END $$
DELIMITER ;
- 提前定义变量。我用的mysql5.7,这个版本我的测试结果是不支持提前定义变量的,网上很多的教程都说需要提前定义变量,版本不同吧,反正我用的版本,只要提前定义变量就会报错。在mysql5.7里面,常用的定义变量或者赋值的就两种,
set @test = 11;
或者select @test := 111;
如果使用DECLARE COUNT INT DEFAULT 0;
这种方式,就会报错。可能也是我的语法有问题吧,但是目前为止,我还没有使用过提前定义正常的情况。如果使用提前定义的,然后报错了,不妨试一下,将提前定义的给去掉。我还没有去研究官方文档,后续研究之后再进行完善,目前也不能说的太肯定。 - 如果sql编译器报错,说第一行出问题,不要相信他,一个语法中,相关联的,所有地方都有可能出错,仔细排查!
- while 的end语句需要加上结束符,不加就会报错!
具体实现代码
重头戏来喽~最终的代码贴出来
CREATE DEFINER=`root`@`%` PROCEDURE `test`()
BEGIN
select @ccc := count(1) from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0;
WHILE @ccc > 0 DO
select @id := id from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0 limit 0,1;
select @column1 := column1 , @column2 := column2 from table2 where orderid = @id;
UPDATE table1 set column1 = @column1 , column2 = @column2 ,column3 = '2020-6-20' where id=@id;
select @ccc := count(1) from table1 where column1 is null and create_time > '2020-6-18' and order_status = 0;
END WHILE;
END
-- 执行
CALL test();