我有一张包含ID
和name
的表格。我想通过这个表的每一行。
ID
是primary key
和auto_increment
。
我不能使用(?)单个查询来获取所有行,因为表格很大。 我正在为每一个结果做点什么。我希望有可能停止这项任务并在以后继续。
我以为我可以这样做:
for (int i = 0; i < 90238529; i++) {
System.out.println("Current ID :" + i);
query = "SELECT name FROM table_name WHERE id = " + i;
...
}
但这不起作用,因为auto_increment
跳过了一些数字。
如前所述,我需要一个选项来停止这项任务,让我能够在我离开的地方重新开始。与上面的示例代码一样,我知道当前条目的ID
,如果我想再次启动它,我只需设置int i = X
。
答案 0 :(得分:6)
使用单个查询来获取所有记录:
query = "SELECT name FROM table_name WHERE id > ? ORDER BY id";
然后迭代ResultSet
并读取您希望的记录数(您不必读取ResultSet返回的所有行)。
下次运行查询时,请传递上一次执行中获得的最后一个ID。
答案 1 :(得分:4)
你提到这是一张大桌子。请注意MySQL Connector/J API Implementation Notes说
,这一点很重要<强>
ResultSet
强>默认情况下,ResultSet完全检索并存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于MySQL网络协议的设计更容易实现。如果您正在使用具有大量行或大值的ResultSet,并且无法在JVM中为所需内存分配堆空间,则可以告诉驱动程序一次将结果流回一行。
要启用此功能,请按以下方式创建Statement实例:
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);
所以,我认为你需要这样做,我会使用a try-with-resources
Statement。接下来,我建议您让数据库帮助您迭代行
String query = "SELECT id, name FROM table_name ORDER BY id";
try (PreparedStatement ps = conn.prepareStatement(query,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.printf("id=%d, name=%s%n", id, name);
}
} catch (SQLException e) {
e.printStackTrace();
}
答案 2 :(得分:0)
我不能使用单个查询来获取所有行,因为表格很大,我正在对每个结果做一些事情。此外,我希望有可能停止此任务并稍后继续。
这些原因都不会消除使用单个查询。它只会影响性能(长时间保持一个连接处于活动状态,而不断打开和关闭连接,这可以使用连接池进行缓解)。
如上所述,我需要一个选项来停止这项任务,但我可以在我离开的地方重新开始。与上面的示例代码一样,我知道当前条目的ID,如果我想再次启动它,我只需设置int i = X
如果你考虑一下,这也不会像你自己说的那样工作
但这不起作用,因为auto_increment跳过了一些数字。
更重要的是,自您上次查询数据库以来,可能已插入或删除了行。
首先,这听起来像是一个经典的XY问题,(您正在描述问题解决方案的问题,而不是实际问题)。其次,似乎正在使用RDBM来实现它从未真正设计过的东西(一个队列)。
如果您真的想这样做,而不是使用更合适的数据库,您可以使用多种方法。您的第一个问题是您希望从某个点/状态恢复,但是这不存储在数据库中,因此在有多个数据库连接的情况下不起作用。解决这个问题的第一种方法是引入一个&#34;处理过的&#34;表中的字段(如果要从任意点恢复,可以使用UPDATE语句清除),现在根据您实际尝试解决的问题,这可能是一个简单的真/假字段,当前处理线程的唯一标识符或关系表。根据要求。
然后你可以回到使用SQL来获取你想要的数据。