快速游标更新法在oracle中的应用和MySQL中游标应用于批量更新数据

情景

有一个项目价格体系表和一个项目订单表,项目价格表里面的价格更新,项目订单表里面的对应没有结算的订单价格更新 订单表更新后往来资金里面需要重新更新,现在项目订单数量太大,更新的时候太慢。

第一次处理

用触发器去处理 监听订单表,订单表被更新时触发器自动去更新往来资金表,但是触发器有一个坏处,我update我的订单表 是不行的,所以gg。

第二次处理

因为用到了上偏文章的FIND_IN_SET 所以我有个大胆的想法

BEGIN
	DECLARE temp int(11);
	
	SET temp = 0;

	#项目销售
	update income_pay_info ip
	join (
		select
			delivery_order_number,
			take_unit_id,
			sale_unit_price,
			check_weight
		from
			delivery_order
    where 
      FIND_IN_SET(id, numbers)
	) new on ip.source_order_number = new.delivery_order_number
	set amount = new.check_weight * new.sale_unit_price
	where
		ip.unit_id = new.take_unit_id
	and ip.source_type = 1
	and ip. status = 0;

  RETURN temp;
 end

我把我修改到的订单号(numbers)传到我的函数里面 我把需要的数据查到再进行修改 这样刚开始还好但是数据量慢慢大了就很慢 我加索引也没有用 这是因为丿date关联表修改就慢 这会造成全表扫描。

最后一次机会 给点面子 别给脸不要脸啊

又叫我改 真的是 客户问为什么慢 公司老哥来了个 你们带宽不够 这波忽悠 我又马上开始改
一二再 再而三,给个机会让我下次不要再改了,我终于在茫茫人海中找到了她——“快速游标更新法”
但是我看这MySQL不能用啊

在这里插入图片描述
不行 我要看哈美女冷静一下
在这里插入图片描述

oracle中游标的使用

冷静一下终于好了 还是开始我们今天的重头戏吧——好戏开场了 管好你的嘴 小子

方法一:隐试游标(更新一次提交一次)

begin
  for cr in (查询语句) loop  --循环
    update table_name set ...   --更新语句
    commit; --提交
  end loop;  --结束循环
end;

方法二:隐试游标(更新一千次提交一次)(推荐使用)

declare v_count numbers(10);
begin
  for cr in (查询语句) loop  --循环
    update table_name set ...   --更新语句
    v_count := v_count + 1;
    if v_count >= 1000 then
      commit; --提交
      v_count := 0;
    end if;
  end loop;  --结束循环
end;

为什么使用一千提交一次呢(自己人的默契)

方法三:推荐使用(使用 BULK COLLECT 和FORALL)

为啥我那么喜欢三呢(其实因为我懒啊 要不是没有事情做 我才不在这里写博客)
在这里插入图片描述

你看 我就是这样的人

游标在MySQL中使用

直接上代码

BEGIN
	DECLARE delivery_order_number VARCHAR(50);
	DECLARE take_unit_id INT;
	DECLARE sale_unit_price DECIMAL(8,2);
	DECLARE check_weight DECIMAL(8,2);

	-- 这个变量用于处理游标到最后一行的情况
	DECLARE s INT DEFAULT 0;

  -- 声明游标new (new是一个多行结果集)
  DECLARE new CURSOR FOR 
		SELECT delivery_order_number, take_unit_id, sale_unit_price, check_weight
		FROM delivery_order 
		WHERE FIND_IN_SET(id, numbers);

  -- 设置一个终止标记,SQLSTATE '02000'是一个未找到条件
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s = 1;

	-- 打开游标
	OPEN new;

  -- 获取游标当前指针的记录,读取一行数据并传递给变量
	FETCH new INTO delivery_order_number, take_unit_id, sale_unit_price, check_weight;
  
  -- 开始循环,判断是否游标已经到了最后作为循环条件
	WHILE s <> 1 DO 
			#供应商
			UPDATE income_pay_info ip 
			SET ip.amount = check_weight * sale_unit_price
			WHERE ip.source_order_number = delivery_order_number 
			AND ip.unit_id = take_unit_id 
			AND ip.source_type = 1
			AND ip.`status` = 0;
			-- 读取下一行的数据
			FETCH NEXT FROM new INTO delivery_order_number, take_unit_id, sale_unit_price, check_weight;
	END WHILE;
	
	-- 关闭游标
	CLOSE new;
END

看注解吧 还是很清楚的 我要去恰饭了,订单号还是通过numbers传进来的,谁的饭 好香啊,拜拜了您勒!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值