You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:54:07