MySQL存储过程故障排查:查找含login值的列并写入logins_map表
问题分析与修复方案
核心错误点
- 匹配逻辑完全颠倒:原代码中用
login LIKE CONCAT("%", columnName, "%"),实际是检查login值是否包含列内容,和需求(列内容包含login值)完全相反。 - 标识符未转义:直接拼接表名、列名到SQL语句,若名称含空格、关键字会触发语法错误。
- 重复插入问题:原逻辑会对每一条匹配记录插入一次表名和列名,导致
logins_map出现大量重复数据。
修正后的存储过程
CREATE PROCEDURE CheckLoginsAndInsert() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE tableName, columnName VARCHAR(255); DECLARE cur CURSOR FOR SELECT table_name, column_name FROM table_column_info; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO tableName, columnName; IF done THEN LEAVE read_loop; END IF; -- 仅当存在匹配时,插入一次表名和列名 SET @query = CONCAT( 'INSERT INTO logins_map (table_name, column_name) ', 'SELECT DISTINCT ?, ? ', 'FROM DUAL ', 'WHERE EXISTS (', 'SELECT 1 FROM `', tableName, '` t ', 'JOIN email_mapping em ON t.`', columnName, '` LIKE CONCAT("%", em.login, "%")', ')' ); SET @tbl = tableName; SET @col = columnName; PREPARE stmt FROM @query; EXECUTE stmt USING @tbl, @col; DEALLOCATE PREPARE stmt; END LOOP; CLOSE cur; END //
关键改进说明
- 修正匹配逻辑:将关联条件改为
t.columnName`` LIKE CONCAT('%', em.login, '%'),确保列内容包含login值。 - 标识符转义:用反引号`包裹表名和列名,兼容特殊字符与关键字场景。
- 避免重复插入:通过
FROM DUAL配合EXISTS子查询,仅在存在至少一个匹配时插入一次记录,而非每条匹配都插入。 - 优化参数传递:将插入的表名、列名用参数传递,降低SQL注入风险,同时保证字符串拼接的安全性。
内容的提问来源于stack exchange,提问作者buntos
相关产品推荐
相关产品推荐

