Table_name using dynamic SQL procedure stored as an input parameter (the MySQL)

Mysql on how to create and use stored procedures, reference notes "MySQL stored procedures and functions to create," and the official website: https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html

In this chapter show examples use the stored procedure input parameters, and solve problems using the table name as input parameters, because before encountered requires the use of the table name as stored procedure parameters, difficult to handle.

Problem Description:

Suppose we have a total of 12 TEST1-TEST12 vehicle odometer same structure, we want these 12 tables go heavy, then logically simpler way is to write 12 or writing a stored procedure to process each stored procedure execution time change the name of a table and recompile, but this is all too much trouble.

Then it is easy for them to think whether you can use a table name as input parameters, so that each perform a given table name.

Thus the initial procedure stored code as follows:

DELIMITER //
DROP PROCEDURE IF EXISTS Del_Dupilicate;
CREATE DEFINER=`root`@`localhost` PROCEDURE `Del_Dupilicate`(in table_name varchar(64))
BEGIN
DECLARE v_min_id,v_group_count INT;
DECLARE v_get_on_time,v_get_off_time DATETIME;
DECLARE v_car_no VARCHAR(255);
DECLARE done INT DEFAULT FALSE;
DECLARE my_cur CURSOR FOR SELECT get_on_time,get_off_time,car_no,min(id),count(1) AS count FROM table_name GROUP BY get_on_time,get_off_time,car_no HAVING count>1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN my_cur;
myloop: LOOP
FETCH my_cur INTO v_get_on_time,v_get_off_time,v_car_no,v_min_id,v_group_count;
IF done THEN
LEAVE myloop;
END IF;
DELETE FROM table_name WHERE get_on_time=v_get_on_time AND get_off_time=v_get_off_time AND car_no=v_car_no AND id>v_min_id;
COMMIT;
END LOOP;
CLOSE my_cur;
END;
//
DELIMITER ;

The storage process can be compiled normally, but it will be reported to the Executive table not exist error, because mysql mistakenly input variable table_name as a real database table name, which is obviously wrong.

So how does reference variables in SQL? One possible solution is to use dynamic SQL, the SQL statement into a variable fight and then execute dynamic SQL.

Therefore, according to the official website ( https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html syntax) provided for the above-described procedure in the delete statement can be rewritten as the following format:

@ del_sql the concat = SET ( 'the DELETE the FROM', table_name, 'the WHERE get_on_time =', v_get_on_time, 'the AND get_off_time =', v_get_off_time, 'the AND car_no =', v_car_no, 'the AND ID>', v_min_id) 
the PREPARE stmt the FROM @del_sql ; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 
// attention to prepare is currently available only in stored procedures, functions and triggers do not apply.

Ps: Note that the official website of the syntax used in the example prepare as a placeholder, but after the test can not be used as a placeholder for the table name (in fact, the official website only as an example of the integer literal placeholder??? I guess all database objects using? as a placeholder will be error), you want to be integrated into the SQL table variable name can only use the concat function, a function of the input concat support local variables, user defined variables and input variables.

Well, delete statement is processed, but for the cursor select statement in it? Official website clearly stated the cursor can not use dynamic SQL, which is not available prepare the statement, it can only change the thinking of.

What is the role of the cursor is it? Is to obtain a result set to be traversed, then the possibility of using a temporary table instead of a cursor to store the result set, so you can create a temporary table (temporary table mysql is the session level using dynamic SQL, different sessions can use a temporary table with the same name, session temporary tables are automatically dropped when released):

set @tmp_table_name=concat(table_name,'_tmp');
set @cur_sql=concat('create temporary table ',@tmp_table_name,' as select get_on_time,get_off_time,car_no,min(id) as min_id,count(1) AS count FROM ',table_name,' GROUP BY get_on_time,get_off_time,car_no HAVING count>1');
PREPARE stmt FROM @cur_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Then the whole logic stored procedures can be changed, because we have intermediate result sets into a temporary table, then you do not need to traverse the cursor, and even declare the local variables while also saving (because these local variables are used to traverse the cursor storage column values), you can just delete ... join, so the final stored procedure amended as follows:
CREATE DEFINER=`root`@`localhost` PROCEDURE `Del_Dupilicate`(in table_name varchar(64))
BEGIN

set @tmp_table_name=concat(table_name,'_tmp');

set @cur_sql=concat('create temporary table ',@tmp_table_name,' as select get_on_time,get_off_time,car_no,min(id) as min_id,count(1) AS count FROM ',table_name,' GROUP BY get_on_time,get_off_time,car_no HAVING count>1');
PREPARE stmt FROM @cur_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

set @del_sql=concat('delete a from ',table_name,' a join ',@tmp_table_name,' b on a.get_on_time=b.get_on_time and a.get_off_time=b.get_off_time and a.car_no=b.car_no and a.id != b.min_id');
PREPARE stmt FROM @del_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

set @drop_tmp_sql=concat('drop temporary table ',@tmp_table_name);
PREPARE stmt FROM @drop_tmp_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

END
 调用:
call Del_Dupilicate('TEST1');
 上述存储过程经过了实测,可以正常的删除重复数据。

Guess you like

Origin www.cnblogs.com/leohahah/p/11596900.html