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

jQuery Ajax+JSP批量删除数据触发ORA-01722错误求助

解决批量删除时ORA-01722无效数字的问题

这个错误的根源很明确:前端传递的是逗号拼接的ID字符串,但后端错误地将其当作单个ID处理,导致Oracle无法把带逗号的字符串转换成数字类型。咱们一步步拆解问题并修复:

问题定位

  1. 前端AJAX代码中,你用.join()把选中的ID拼成了一个字符串(比如"1,2,3"),然后作为id参数传递给后端。
  2. 后端用request.getParameterValues("id")获取参数,但这个方法是用来获取同名多参数的(比如表单里多个同名checkbox的原生提交场景),而你这里只传了一个逗号分隔的字符串,所以checkedid数组里只有一个元素:"1,2,3"。
  3. 之后循环时,你把这个带逗号的字符串传给pst.setString(1, check),执行DELETE FROM student_signup WHERE (STUDENT_ID = ?)时,Oracle会尝试把"1,2,3"转换成数字,自然就抛出ORA-01722错误了。

修复方案(两种可选)

方案一:前端传递数组,后端正确接收

修改前端AJAX代码,直接传递ID数组,不用拼接成字符串,jQuery会自动处理为多参数形式:

$(document).ready(function () { 
    $('#trash').click(function (event) { 
        event.preventDefault(); 
        // 直接获取ID数组,跳过join()步骤
        var ids = $('.checkitem:checked').map(function () { 
            return $(this).val(); 
        }).get(); 
        
        if(ids.length > 0) { 
            if (confirm("Are you sure you want to delete these records?")) { 
                $.ajax({ 
                    url: 'TeacherStudentDeletion.jsp', 
                    type: 'POST', 
                    // 传递数组,jQuery会自动转为id=1&id=2&id=3的格式
                    data: {id: ids}, 
                    success: function (result) { 
                        $('tbody').html(result); 
                    }, 
                    error: function () { 
                        alert('Error while deletion. Please try again.'); 
                    } 
                }) 
            } else { 
                return false; 
            } 
        } else { 
            alert("Please select the user first."); 
        } 
    }) 
});

后端代码保持request.getParameterValues("id")的逻辑即可,现在checkedid数组里会是每个单独的ID字符串,循环执行删除时就能正确匹配数字类型的STUDENT_ID了。

方案二:后端处理逗号分隔的字符串(更高效的批量删除)

如果不想修改前端,可以在后端把接收到的逗号分隔字符串拆分成数组,并且用批量SQL优化删除操作(避免多次执行DELETE,提升性能):

修改后端JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %> 
<%@ page import="java.sql.*" %> 
<% 
boolean success = false; 
Connection con = null; 
PreparedStatement pst = null; 
ResultSet rs = null; 
try { 
    // 用getParameter获取单个逗号分隔的字符串
    String idStr = request.getParameter("id"); 
    if(idStr != null && !idStr.isEmpty()) { 
        String[] checkedid = idStr.split(","); 
        Class.forName("oracle.jdbc.driver.OracleDriver"); 
        con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SUNILREDDY", "oracle"); 
        
        // 使用批量PreparedStatement,安全且高效
        String s1 = "DELETE FROM student_signup WHERE STUDENT_ID = ?"; 
        pst = con.prepareStatement(s1); 
        for (String id : checkedid) { 
            // 转为int类型,匹配数据库字段的数字类型
            pst.setInt(1, Integer.parseInt(id)); 
            pst.addBatch(); 
        } 
        int[] results = pst.executeBatch(); 
        // 检查是否有成功删除的记录
        for(int res : results) { 
            if(res > 0) { 
                success = true; 
                break; 
            } 
        }
    } 
    
    if (success) { 
        String s2 = "select * from student_signup"; 
        pst = con.prepareStatement(s2); 
        rs = pst.executeQuery(); 
        while (rs.next()) { %> 
        <tr> 
            <th> 
                <div class="pretty p-icon p-curve p-has-indeterminate"> 
                    <input type="checkbox" class="checkitem" value="<%= rs.getInt("STUDENT_ID") %>" name="check"/> 
                    <div class="state"> 
                        <i class="icon mdi mdi-check"></i> 
                        <label>Check</label> 
                    </div> 
                    <div class="state p-is-indeterminate"> 
                        <i class="icon mdi mdi-minus"></i> 
                        <label>Indeterminate</label> 
                    </div> 
                </div> 
            </th> 
            <th scope="row"><%= rs.getInt("ROLLNO") %></th> 
            <th><%= rs.getInt("STUDENT_ID") %></th> 
            <td><%= rs.getString("STUDENT_FIRSTNAME") %></td> 
            <td><%= rs.getString("STUDENT_LASTNAME") %></td> 
            <td><%= rs.getString("COURSE_NAME") %></td> 
        </tr> 
        <% } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} finally { 
    // 必须关闭数据库资源,防止连接泄漏
    try { if(rs != null) rs.close(); } catch(Exception e) {} 
    try { if(pst != null) pst.close(); } catch(Exception e) {} 
    try { if(con != null) con.close(); } catch(Exception e) {} 
} 
%>

额外优化建议

  • 把数据库连接代码抽成独立工具类,不要直接写在JSP里,便于维护和复用。
  • 永远在finally块中关闭数据库资源,避免内存泄漏。
  • 方案二的批量PreparedStatement能有效防止SQL注入,推荐优先使用。

内容的提问来源于stack exchange,提问作者Sunil Reddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:44:21