为什么这里需要"while(rs.next())"?

Jad*_*ast 41 java jdbc

我想从我的数据库" Logs "中选择最大行号并将其存储在变量中m.

这是我的代码:

ResultSet rs = stmt.executeQuery("Select max(Line) as L from logs");

while (rs.next()) {          // Why do I need this
    int m = rs.getInt("L");
    System.out.println(m);
}
Run Code Online (Sandbox Code Playgroud)

但除非我使用,否则它不起作用while(rs.next()).


如果我理解正确,rs.next()将光标移动到下一行,但在这里,在这个结果中,我只有一行.

那么,有人可以解释为什么循环是必要的吗?我唯一能想到的是第一个光标是在列名上设置的,我是对的吗?

Zab*_*uza 76

为什么?

光标最初放在第一个元素之前.您需要前进一次才能访问第一个元素.

这显然是因为使用循环遍历结果非常方便,如您所见.从官方文档:

将光标从当前位置向前移动一行.甲ResultSet光标最初位于第一行之前 ; 对方法的第一次调用使得第一行成为当前行; 第二个调用使第二行成为当前行,依此类推.


因此,虽然您不需要任何循环,但您需要将光标前进一次.单从rs.next();技术上就足够了:

rs.next();
// Access the result
Run Code Online (Sandbox Code Playgroud)

但是,您可能想要考虑根本没有匹配的情况,因为:

当对next方法的调用返回时false,光标位于最后一行之后.任何ResultSet需要当前行的方法的调用都将导致SQLException抛出.

所以在这种情况下代码会失败.

因此,您应该考虑案例并使用返回boolean来保护您的访问权限:

if (rs.next()) {
    // Access result ...
} else {
    // No match ...
}
Run Code Online (Sandbox Code Playgroud)

  • 没有`group by`的`select max(...)...`语句总是会返回一行,即使没有记录与`where`子句匹配,在这种情况下返回的值是'null`.所以,一个简单的`rs.next();`对于这个SQL是完全正确的. (9认同)
  • 为了确保清晰,我使用`if(rs.first()){...}`.它会做同样的事情,但阅读起来会更清楚. (3认同)
  • @Andreas我会保留检查,所以我的Java的正确性不依赖于不同语言规定的规则.但我认为这是个人偏好.实际上我_may_考虑在一个性能关键的函数中跳过它,如果分支真的引起麻烦,但只有在它上面的注释表明假设是什么.至少,当下次有人改变SQL并且不考虑重新审视周围Java代码的逻辑时,这可以起到保护作用. (3认同)

Eug*_*ene 22

官方文档(你应该阅读btw):

最初,光标位于第一行之前.下一个方法将光标移动到下一行,因为当ResultSet对象中没有更多行时它返回false,它可以在while循环中用于迭代结果集.

你基本上需要移动它,在你的情况下移动它就足够了:

 rs.next(); 
 System.out.println(rs.getInt("L")); 
Run Code Online (Sandbox Code Playgroud)


Mak*_*oto 11

您可以将其转换为使用简单的if语句.

if(rs.next()) {
    // other code here
}
Run Code Online (Sandbox Code Playgroud)

while当你有多行时可以使用.

  • @YCF_L这取决于确切的查询:考虑一个空表,没有`group by`的`max`将返回带有`null`的单行,但是使用`group by`它将不返回任何行 (6认同)
  • 不需要if条件只是`rs.next(); int m = rs.getInt("L");`因为max总是返回一个结果 (2认同)
  • @MoritzBoth当然,对于问题中的查询YCF_L是绝对正确的,但是给出的问题 - 很多时候 - 简化的例子,你应该考虑更大的图景.在这种情况下,我的回复是由YCF_L的初始评论中的_always_触发的. (2认同)

Adi*_*udi 9

ResultSet游标最初位于第一行之前,第一次调用方法next使第一行成为当前行,第二次调用使第二行成为当前行,依此类推.

认为你有类似的东西.

->1->2->3
^
Run Code Online (Sandbox Code Playgroud)

你的"rs"最初指向1之前,当你调用rs.next()时它会使箭头指向1

  ->1->2->3
    ^
Run Code Online (Sandbox Code Playgroud)

因此,如果您不调用next()方法,则不会得到结果.

希望这可以帮助