无法修改的无输出参数存储过程,如何获取插入记录数?
获取无输出参数存储过程的插入记录数
在无法修改目标存储过程的前提下,你可以通过以下几种方式获取插入的记录数:
方法1:事务内对比表行数(通用可靠方案)
利用事务的原子性,在调用存储过程前后分别查询两张目标表的行数,计算差值得到总插入数。这种方法适用于所有支持事务的数据库,只要能确保操作期间没有其他并发进程修改这两张表,结果就准确。
代码示例
Connection conn = ...; try { conn.setAutoCommit(false); // 开启事务,保证前后查询与存储过程调用在同一事务内 // 查询两张表的初始行数 Statement countStmt = conn.createStatement(); ResultSet rsTable1Init = countStmt.executeQuery("SELECT COUNT(*) FROM table1"); rsTable1Init.next(); long table1InitCount = rsTable1Init.getLong(1); ResultSet rsTable2Init = countStmt.executeQuery("SELECT COUNT(*) FROM table2"); rsTable2Init.next(); long table2InitCount = rsTable2Init.getLong(1); // 调用目标存储过程 String sqlQuery = "{call storedprocedure(?)}"; Array input = methodForBuildingInput(); CallableStatement procStmt = conn.prepareCall(sqlQuery); procStmt.setArray(1, input); procStmt.execute(); // 查询调用后的表行数 ResultSet rsTable1Final = countStmt.executeQuery("SELECT COUNT(*) FROM table1"); rsTable1Final.next(); long table1FinalCount = rsTable1Final.getLong(1); ResultSet rsTable2Final = countStmt.executeQuery("SELECT COUNT(*) FROM table2"); rsTable2Final.next(); long table2FinalCount = rsTable2Final.getLong(1); // 计算总插入记录数 long totalInserted = (table1FinalCount - table1InitCount) + (table2FinalCount - table2InitCount); log.write(totalInserted + " records were written"); conn.commit(); } catch (SQLException e) { if (conn != null) conn.rollback(); e.printStackTrace(); } finally { if (conn != null) { try { conn.setAutoCommit(true); // 恢复自动提交模式 } catch (SQLException e) { e.printStackTrace(); } } }
方法2:利用数据库特定语法捕获插入结果(按需选择)
部分数据库支持直接捕获存储过程的插入结果,比如SQL Server的OUTPUT子句,你可以通过包装SQL语句来实现:
// 仅适用于SQL Server String wrappedSql = "DECLARE @temp TABLE (id INT); " + "INSERT INTO @temp EXEC storedprocedure ?; " + "SELECT COUNT(*) FROM @temp;"; PreparedStatement stmt = conn.prepareStatement(wrappedSql); stmt.setArray(1, input); ResultSet rs = stmt.executeQuery(); rs.next(); long total = rs.getLong(1); log.write(total + " records were written");
注意:不同数据库的语法差异较大,MySQL等数据库没有类似的直接捕获方式,此方法需结合你的数据库类型使用。
方法3:遍历存储过程的结果集(依赖存储过程内部逻辑)
如果存储过程内部隐含返回了插入行数的结果集(比如执行了SELECT @@ROWCOUNT),你可以通过execute()方法遍历结果集获取数值:
CallableStatement statement = conn.prepareCall(sqlQuery); statement.setArray(1, input); boolean hasResultSet = statement.execute(); long total = 0; while (hasResultSet) { ResultSet rs = statement.getResultSet(); if (rs.next()) { total += rs.getLong(1); } hasResultSet = statement.getMoreResults(); } log.write(total + " records were written");
此方法仅在存储过程内部有返回行数的逻辑时有效,若存储过程没有输出任何结果集则无法使用。
内容的提问来源于stack exchange,提问作者Eric Bulgrin
相关产品推荐
相关产品推荐

