mysql中通过存储过程和游标来实现循环插入数据

需求:根据条件从一个表(后称为A)中查询符合条件的结果集,根据表A的结果集循环插入到另一个表(后称为B)中,

解决SQL:

drop procedure if exists handle_data; # 如果存在名字为handle_data的procedure则删除
delimiter // # 定义//为一句sql的结束标志,取消;的所代表的意义
#声明存储过程handle_data()
CREATE PROCEDURE handle_data ( ) 
  # 存储过程开始
  BEGIN
  # 定义一个变量,while循环时使用
  DECLARE deviceCode VARCHAR( 255 );
  # 为下面while循环建立一个退出标志,
  DECLARE flag INT DEFAULT 0;
  # 定义一个游标来记录sql查询的结果
  DECLARE deviceCodeList CURSOR FOR ( SELECT device_code FROM t_device WHERE DEVICE_TYPE_CODE IN ("SmokeDetector","HeatDetector","HydrantButton","ManualCallButton"));
  # 当游标遍历完后将flag的值设置为1
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
  # 打开游标
  OPEN deviceCodeList;
  # 将游标中的值赋给定义好的变量,实现for循环的要点
  FETCH deviceCodeList INTO deviceCode;
  # 当flag不等于1时,会一直循环
  WHILE flag != 1 DO
  
	  # 执行需要循环处理的SQL
	  # 插入数据到另一个表
      INSERT INTO `t_device_expand_property` (`DEVICE_CODE`,`PROPERTY_ID`,`PROPERTY_VALUE`) values(deviceCode,27,"27"),(deviceCode,21,"21");
	  # 游标往后移,注:不能漏
      FETCH deviceCodeList INTO deviceCode;
    end while;
  CLOSE deviceCodeList; # 关闭游标
  # 存储过程结束
  end //
    
delimiter ;
call handle_data();

注:1.变量定义要在CURSOR 之前;2.DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1要在打开游标之前;3.循环过程中定要执行FETCH xxx INTO xxx ,使游标后移;

简单表演示:
提供数据的表:

drop table if exists t_device;
CREATE TABLE `t_device` (
  `ID` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `DEVICE_NAME` varchar(128) DEFAULT NULL COMMENT '设备名称',
  `device_alias` varchar(128) DEFAULT NULL COMMENT '设备别名',
  `DEVICE_CODE` varchar(128) NOT NULL COMMENT '资产唯一编号',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `DEVICE_CODE` (`DEVICE_CODE`)
) ENGINE=InnoDB AUTO_INCREMENT=3718 DEFAULT CHARSET=utf8 COMMENT='设备表';
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (65, 'B3-364向东', 'B3-364向东', '5361bd9b1a6c435fa14ef3bf2404d8ef');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (66, 'B3-363向北', 'B3-363向北', '6516f1c522dc493099bad595b9795d9a');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (67, 'B3-269向北', 'B3-269向北', '61edb76574c9496ba550603806b49474');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (68, 'B3-247向北', 'B3-247向北', '2be4c022ed594abfba88ba6b0d027113');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (69, 'B3-247向北', 'B3-247向北', '8a067b67cff846c0a85b1dc88013db8e');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (70, 'B3-232向西', 'B3-232向西', 'b2f867f886fd4fb49c943a4135a91d03');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (71, 'B3-218向北', 'B3-218向北', 'f3fc66ee3d614df49171a11b249396b4');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (72, 'B3-209向南', 'B3-209向南', 'f4417cac5ebd468bad801430a9a55633');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (73, 'B3-206向南', 'B3-206向南', '4896a7a107db4efe90160303751a74bd');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (74, 'B3-198向西', 'B3-198向西', '46f6094a8cf54612a0e7f0937cdf59c0');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (75, 'B3-190向北', 'B3-190向北', 'ae78c2dbdec54a6da9748c3552512fde');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (76, 'B3-189向西', 'B3-189向西', '0da288ebd66f46e38cfcdd44260a7112');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (77, 'B3-180向西', 'B3-180向西', 'aaf59b3542fe49d7ae44700a8cbadbf9');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (78, 'B3169向南', 'B3169向南', '369b8c58f7d8444dafa45da6a5b09680');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (79, 'B3-159向北', 'B3-159向北', 'f6076ad7086a489e999cc729d49b5208');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (80, 'B3-151向东', 'B3-151向东', 'e37b615095b24a9b905bf5d0e8a4d634');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (81, 'B3-110向东', 'B3-110向东', 'eba5c92b869d4a16ac111c5885f75f4c');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (82, 'B3-098向东', 'B3-098向东', '4760537860204bbc97e38170e2b7ccda');
INSERT INTO `t_device`(`ID`, `DEVICE_NAME`, `device_alias`, `DEVICE_CODE`) VALUES (83, 'B3-017向东', 'B3-017向东', '350de6edaf5b4785915c0fe1eaccc818');

在这里插入图片描述

需要插入数据表:

drop table if exists t_device_property;
CREATE TABLE `t_device_property` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `DEVICE_CODE` varchar(32) NOT NULL COMMENT '设备编码',
  `PROPERTY_ID` varchar(32) NOT NULL COMMENT '属性ID',
  `PROPERTY_VALUE` varchar(255) DEFAULT NULL COMMENT '属性值',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=192 DEFAULT CHARSET=utf8 COMMENT='设备属性值表';

在这里插入图片描述

存储过程:

drop procedure if exists handle_data; # 如果存在名字为handle_data的procedure则删除
delimiter // # 定义//为一句sql的结束标志,取消;的所代表的意义
#声明存储过程handle_data()
CREATE PROCEDURE handle_data ( ) 
  # 存储过程开始
  BEGIN
  # 定义一个变量,while循环时使用
  DECLARE deviceCode VARCHAR( 255 );
  # 为下面while循环建立一个退出标志,
  DECLARE flag INT DEFAULT 0;
  # 定义一个游标来记录sql查询的结果
  DECLARE deviceCodeList CURSOR FOR ( SELECT device_code FROM t_device WHERE id>80);
  # 当游标遍历完后将flag的值设置为1
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
  # 打开游标
  OPEN deviceCodeList;
  # 将游标中的值赋给定义好的变量,实现for循环的要点
  FETCH deviceCodeList INTO deviceCode;
  # 当flag不等于1时,会一直循环
  WHILE flag != 1 DO
  
	  # 执行需要循环处理的SQL
	  # 插入数据到另一个表
      INSERT INTO `t_device_property` (`DEVICE_CODE`,`PROPERTY_ID`,`PROPERTY_VALUE`) values(deviceCode,27,"27");
	  # 游标往后移,注:不能漏
      FETCH deviceCodeList INTO deviceCode;
    end while;
  CLOSE deviceCodeList; # 关闭游标
  # 存储过程结束
  end //
    
delimiter ;
call handle_data();

在这里插入图片描述
其他存储过程示例:
表:

CREATE TABLE `t_exhibition_rel_floor` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `exhibition_code` varchar(64) NOT NULL COMMENT ' 展会编码',
  `floor` int(2) NOT NULL COMMENT '所在楼层',
  `passenger_flow_count` int(8) unsigned NOT NULL DEFAULT '0' COMMENT '客流摄像头统计人流数',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_exhibition_code_floor` (`exhibition_code`,`floor`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='展会楼层表';

在这里插入图片描述
存储过程:

drop procedure if exists handle_data; # 如果存在名字为handle_data的procedure则删除
delimiter // # 定义//为一句sql的结束标志,取消;的所代表的意义
#声明存储过程
create PROCEDURE handle_data()
	BEGIN
		 # 定义一个变量,while循环时存储展会编码
		DECLARE tmp_exhibition_code VARCHAR(64);
		 # 定义一个变量,while循环时存储楼层
		DECLARE tmp_floor int(2) DEFAULT 3;
		 # 定义一个变量,while循环时存储创建时间
		DECLARE tmp_create_time datetime DEFAULT NULL;
		 # 定义一个变量,while循环时存储更新时间
		DECLARE tmp_update_time datetime DEFAULT NULL;
		# 为下面while循环建立一个退出标志,
		DECLARE flag INT DEFAULT 0;
		# 定义一个游标tmp_index来记录sql查询的结果
		DECLARE tmp_index CURSOR FOR (SELECT t.exhibition_code,t1.floor,t.create_time,t.update_time FROM t_exhibition t inner JOIN t_exhibitor t1 on t.exhibition_code = t1.exhibition_code where floor IN (3,4,5) GROUP BY t.exhibition_code,t1.floor ORDER BY t.create_time asc);
		# 当游标遍历完后将flag的值设置为1
		DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
		# 打开游标
		OPEN tmp_index;
		# 将游标中的值赋给定义好的变量,实现for循环的要点
		FETCH tmp_index INTO tmp_exhibition_code,tmp_floor,tmp_create_time,tmp_update_time;
		# 当flag不等于1时,会一直循环
		WHILE flag != 1 DO
		
			# 执行需要循环处理的SQL
			# 插入数据到另一个表
			INSERT INTO `t_exhibition_rel_floor` (`exhibition_code`,`floor`,`passenger_flow_count`,create_time,update_time) values(tmp_exhibition_code,tmp_floor,0,tmp_create_time,tmp_update_time);
			# 游标往后移,注:不能漏
				FETCH tmp_index INTO tmp_exhibition_code,tmp_floor,tmp_create_time,tmp_update_time;
			end while;
		CLOSE tmp_index; # 关闭游标
		# 存储过程结束
		end //
    
delimiter ;
# 调用存储过程
call handle_data();

在这里插入图片描述

当需要对一个结果集进行循环处理时,可以使用游标(cursor)来实现。下面是一个示例,展示了如何在MySQL存储过程使用游标循环: ```sql DELIMITER // CREATE PROCEDURE process_data() BEGIN -- 声明变量来存储结果集的字段值 DECLARE done INT DEFAULT FALSE; DECLARE col1 VARCHAR(255); DECLARE col2 INT; -- 声明游标 DECLARE cur CURSOR FOR SELECT column1, column2 FROM your_table; -- 定义异常处理程序 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 打开游标 OPEN cur; -- 循环处理结果集 read_loop: LOOP -- 从游标读取下一行数据 FETCH cur INTO col1, col2; -- 如果已经读取完所有行,则退出循环 IF done THEN LEAVE read_loop; END IF; -- 在这里进行你的处理逻辑,可以使用 col1 和 col2 来访问字段值 -- 示例:打印字段值 SELECT col1, col2; END LOOP; -- 关闭游标 CLOSE cur; END // DELIMITER ; ``` 在上面的示例,首先声明了一些变量来存储结果集的字段值。然后,声明了一个游标,它通过SELECT语句从指定的表获取数据。接下来,定义了一个异常处理程序,用于在读取完所有行后设置`done`变量为TRUE。然后打开游标,并使用一个循环(`LOOP`)来逐行读取结果集数据。在循环,可以使用游标的FETCH语句将字段值赋给声明的变量。在每次循环,可以根据需要对字段值进行处理。最后,关闭游标。 你可以根据你的具体需求修改上述示例的代码。希望这能帮助到你!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值