MySQL预处理语句执行失败,报1064语法错误求助
问题分析与解决
核心问题
- GROUP_CONCAT长度限制导致SQL截断:MySQL默认
GROUP_CONCAT的最大长度为1024字符,若objdata内容较长,拼接时会被截断,导致生成的INSERT语句不完整(比如仅写到values (1165就终止),触发1064语法错误。 - 多语句预处理执行限制:MySQL的
PREPARE默认不支持一次性执行多条SQL语句(除非开启multi_statements参数,但存在安全风险),你拼接的语句包含事务启动、多条操作、事务提交、删除语句,属于多语句批量执行,不符合预处理常规用法。 - 多余分号问题:
GROUP_CONCAT(objdata SEPARATOR ';')已给每个objdata添加分号,后续又额外加了';',会导致最后一条objdata语句后出现两个分号,引发语法错误。
解决步骤
1. 临时调整GROUP_CONCAT长度限制
在存储过程开头设置更大的长度阈值,避免内容被截断:
SET SESSION group_concat_max_len = 1048576; -- 设置为1MB,可根据实际需求调整
2. 拆分多语句执行,规避预处理批量执行风险
修改存储过程逻辑,改用游标遍历执行单条语句,再统一处理事务和删除操作:
CREATE DEFINER = 'root'@'localhost' PROCEDURE new_procedure() BEGIN DECLARE done INT DEFAULT 0; DECLARE v_objdata TEXT; DECLARE v_ids TEXT; -- 声明游标遍历qry_obj_dtl的objdata字段 DECLARE obj_cursor CURSOR FOR SELECT objdata FROM qry_obj_dtl; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -- 临时调整GROUP_CONCAT长度 SET SESSION group_concat_max_len = 1048576; -- 提前获取要删除的ID列表 SELECT GROUP_CONCAT(ID SEPARATOR ',') INTO v_ids FROM qry_obj_dtl; START TRANSACTION; -- 遍历执行每条objdata语句 OPEN obj_cursor; read_loop: LOOP FETCH obj_cursor INTO v_objdata; IF done THEN LEAVE read_loop; END IF; -- 执行单条SQL语句 SET @sql = v_objdata; PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP; -- 提交事务并执行删除操作 COMMIT; SET @del_sql = CONCAT('DELETE FROM qry_obj_dtl where id in (', v_ids, ')'); PREPARE del_stmt FROM @del_sql; EXECUTE del_stmt; DEALLOCATE PREPARE del_stmt; END
3. 检查objdata字段的原始SQL语法
确认qry_obj_dtl表中objdata字段存储的SQL语句本身无语法错误,比如INSERT语句的括号是否匹配、字段值是否正确转义(含特殊字符时)。
内容的提问来源于stack exchange,提问作者abp26
相关产品推荐
相关产品推荐

