该存储过程用于在 当前数据库 中查找包含指定字符串的所有表和字段。
输出结果:每张表只返回一次记录,列出该表中包含目标字符串的字段列表(逗号分隔)。
适用场景:
- 数据库迁移或审计时,快速定位含敏感信息的字段。
- 找出数据库中某个 URL、邮箱、关键字或特定内容所在的字段。
- 不知道具体表或字段名时,快速全库搜索。
DROP PROCEDURE IF EXISTS find_tables_with_string_safe$$
DELIMITER $$
CREATE PROCEDURE find_tables_with_string_safe(IN search_str VARCHAR(255))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE t_name VARCHAR(255);
DECLARE c_name VARCHAR(255);
DECLARE sql_text TEXT;
DECLARE cur1 CURSOR FOR
SELECT table_name, column_name
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND data_type IN ('char','varchar','text','tinytext','mediumtext','longtext');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS tmp_find_results;
CREATE TEMPORARY TABLE tmp_find_results (
table_name VARCHAR(255),
column_name VARCHAR(255)
);
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO t_name, c_name;
IF done = 1 THEN
LEAVE read_loop;
END IF;
SET sql_text = CONCAT(
'INSERT INTO tmp_find_results(table_name, column_name) ',
'SELECT ''', t_name, ''', ''', c_name, ''' ',
'FROM `', t_name, '` WHERE `', c_name, '` LIKE ', QUOTE(CONCAT('%', search_str, '%')), ' LIMIT 1'
);
SET @sql_text = sql_text;
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur1;
-- 最后返回结果,每张表只取一次表名,多个列会多行返回
SELECT table_name, GROUP_CONCAT(column_name SEPARATOR ',') AS matched_columns
FROM tmp_find_results
GROUP BY table_name
ORDER BY table_name;
END$$
DELIMITER ;