Java String转MySQL char(9)报数据过长 存储过程删行问题求助
问题根因
- 字符串参数未加引号导致类型识别错误:你在拼接CallableStatement调用语句时,没有给字符串类型的参数
c加单引号包裹,MySQL会将传入的2021/2022识别为除法运算表达式而非字符串,运算后得到的数值转换为char类型时长度超出了char(9)的限制,这是报错的直接原因。你传入的原字符串2021/2022本身长度为9,完全匹配字段定义的char(9)长度,本身没有长度问题。 - 存储过程使用逻辑冗余:每次执行删除操作都动态删除、重建存储过程,完全没有必要,既增加不必要的数据库开销,还存在并发冲突风险。
- CallableStatement用法错误:CallableStatement本身支持参数绑定特性,可自动处理类型转换、引号包裹等问题,你当前用字符串拼接参数的写法完全浪费了该特性,还容易引发SQL注入风险。
修复方案
步骤1:提前在MySQL中创建存储过程
直接在MySQL客户端执行以下语句完成存储过程的预创建,无需在Java代码中动态生成:
DROP PROCEDURE IF EXISTS DELETE_ENROLLMENT; DELIMITER // CREATE PROCEDURE DELETE_ENROLLMENT( IN alumno DOUBLE(4,0), IN profesor DOUBLE(2,0), IN asignatura DOUBLE(3,0), IN c CHAR(9) ) BEGIN DELETE FROM MATRICULAS WHERE codigoAlumno=alumno AND codigoProfesor=profesor AND codigoAsignatura=asignatura AND curso=c; END // DELIMITER ;
注意这里需要临时修改语句分隔符为//,避免存储过程内部的分号导致创建语句提前中断。
步骤2:修改Java代码使用参数绑定
替换原有逻辑,使用CallableStatement的占位符绑定参数,避免字符串拼接:
public boolean borrarMatricula(Connection conn, int alumno, int profesor, int asignatura, String c){ boolean borrado = false; // 使用?作为参数占位符 String callSql = "{call DELETE_ENROLLMENT(?, ?, ?, ?)}"; try { CallableStatement cs = conn.prepareCall(callSql); // 按位置绑定参数,JDBC会自动处理类型转换和引号 cs.setInt(1, alumno); cs.setInt(2, profesor); cs.setInt(3, asignatura); cs.setString(4, c); cs.execute(); borrado = true; } catch(SQLException e){ Vista.muestraErrorSQL(e); } catch(Exception e){ e.printStackTrace(System.err); } return borrado; }
内容的提问来源于stack exchange,提问作者Martín Mato Búa
相关产品推荐
相关产品推荐

