Mysql stored procedure traverses and sets certain field values in the table

origin

There are sub-tables in the mysql database, about 300 tables, all named geo_data_xxxxxxafter . During the previous test, a value was set for a field in the 300 tables, but I wanted to regenerate the data. Then we did a data cleaning and is_turnoutset the fields of 300 tables to nullvalues. If you want to update tables one by one, the workload is indeed a bit heavy.

This can be achieved using mysql stored procedures.

operate

General idea:

  • geo_data_xxxxxxTable names of all tables found first
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME REGEXP 'geo_data_[0-9]'
  • Traverse the loop and execute update
update 表名 set is_turnout = null

It seems perfect.

The complete statement is as follows:

DROP PROCEDURE IF EXISTS set_geo_turnout_null;
CREATE PROCEDURE set_geo_turnout_null()
BEGIN
	-- 该变量用于标识是否还有数据需遍历
	DECLARE flag INT DEFAULT 0;
	-- 创建一个变量用来存储遍历过程中的值
	DECLARE tbl_name VARCHAR(100);
	-- 查询出需要遍历的数据集合
	DECLARE tbl_list CURSOR FOR (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME REGEXP 'geo_data_[0-9]');
	-- 查询是否有下一个数据,没有将标识设为1,相当于hasNext
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
	-- 打开游标
	OPEN tbl_list;
		-- 取值设置到临时变量中
		FETCH tbl_list INTO tbl_name;
		-- 遍历未结束就一直执行
		WHILE flag != 1 DO
				-- targetSQL //你想要执行的目标功能,这里可以写多个SQL
				update tbl_name set is_turnout = null;
				-- 一定要记得把游标向后移一位
				FETCH tbl_list INTO tbl_name;
		END WHILE;
	-- 关闭游标
	CLOSE tbl_list;
END;

Oak, full of confidence, finish the execution and then call the speed, hehe

CALL set_geo_turnout_null();

Insert image description here

Ga?

Insert image description here

What the hell, if you don’t follow martial ethics, can this be wrong? ?

Troubleshooting

First of all, from the perspective of the problem, when executing update, my variable tbl_namewas not parsed, but was treated as a string.

Insert image description here

Later I thought, since the table name is a variable, can I splice it? I update concat('geo_data_','111111')tried it first, but it really didn't work.

After consulting the information, you can use mysql's dynamic sql to achieve it, similar to the following:

SET @table_name = 'your_table_name';
SET @sql = CONCAT('UPDATE ', @table_name, ' SET column1 = value1, column2 = value2 WHERE condition');

PREPARE stmt FROM @sql;
EXECUTE stmt;

Oak, try it quickly.

DROP PROCEDURE IF EXISTS set_geo_turnout_null;
CREATE PROCEDURE set_geo_turnout_null()
BEGIN
	-- 该变量用于标识是否还有数据需遍历
	DECLARE flag INT DEFAULT 0;
	-- 创建一个变量用来存储遍历过程中的值
	DECLARE tbl_name VARCHAR(100);
	-- 查询出需要遍历的数据集合
	DECLARE tbl_list CURSOR FOR (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME REGEXP 'geo_data_[0-9]');
	-- 查询是否有下一个数据,没有将标识设为1,相当于hasNext
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
	-- 打开游标
	OPEN tbl_list;
		-- 取值设置到临时变量中
		FETCH tbl_list INTO tbl_name;
		-- 遍历未结束就一直执行
		WHILE flag != 1 DO
				-- targetSQL //你想要执行的目标功能,这里可以写多个SQL
				SET @sql = CONCAT('UPDATE ', tbl_name, ' SET is_turnout = null');
				PREPARE stmt FROM @sql;
				EXECUTE stmt;
				-- 一定要记得把游标向后移一位,这个坑我替各位踩过了,不需要再踩了
				FETCH tbl_list INTO tbl_name;
		END WHILE;
	CLOSE tbl_list;
END;

Save, call...successful~~

Insert image description here

Optimization + log

The author is also deeply influenced by the idea of ​​packaging. When I see messy things, I want to pack them up and take them away.

In other words, one stored procedure can be split into two. Then I can updateencapsulate the dynamic SQL and set it as a stored procedure; then set the field value in the loop table as a stored procedure, and finally call the update stored procedure.

update动态sql, receiving an input parameter of table_name

DROP PROCEDURE IF EXISTS update_table_geo;
CREATE PROCEDURE update_table_geo(IN table_name VARCHAR(255))
BEGIN
	-- 日志
	select table_name;
	-- 动态sql语句
    SET @sql = CONCAT('UPDATE ', table_name, ' SET is_turnout = null');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END

循环处理存储过程

DROP PROCEDURE IF EXISTS set_geo_turnout_null;
CREATE PROCEDURE set_geo_turnout_null()
BEGIN
	-- 该变量用于标识是否还有数据需遍历
	DECLARE flag INT DEFAULT 0;
	-- 创建一个变量用来存储遍历过程中的值
	DECLARE tbl_name VARCHAR(100);
	-- 查询出需要遍历的数据集合
	DECLARE tbl_list CURSOR FOR (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME REGEXP 'geo_data_[0-9]');
	-- 查询是否有下一个数据,没有将标识设为1,相当于hasNext
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
	-- 打开游标
	OPEN tbl_list;
		-- 取值设置到临时变量中
		FETCH tbl_list INTO tbl_name;
		-- 遍历未结束就一直执行
		WHILE flag != 1 DO
				-- targetSQL //你想要执行的目标功能,这里可以写多个SQL
				-- 执行 update 动态sql
				call update_table_geo(tbl_name);
				-- 一定要记得把游标向后移一位
				FETCH tbl_list INTO tbl_name;
		END WHILE;
	CLOSE tbl_list;
END;

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_45248492/article/details/132577847