为什么在这里需要“ while(rs.next())”?

时间:2018-08-08 20:26:59

标签: java jdbc

我想从数据库“ 日志”中选择最大行数,并将其存储在变量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);
}

但是除非我使用while(rs.next()),否则它将无法正常工作。


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

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

5 个答案:

答案 0 :(得分:75)

为什么?

最初,光标位于第一个元素的之前。您需要推进一次以访问第一个元素。

显然是这样做的,因为如您所见,使用循环遍历结果非常方便。来自official documentation

  

将光标从其当前位置向前移动一行。 (defn collatz-iter [x] (cond (= x 1) nil (even? x) (/ x 2) :else (inc (* 3 x)))) (defn collatz [n] (take-while some? (iterate collatz-iter n))) (collatz 12) ;; => (12 6 3 10 5 16 8 4 2 1) 光标最初位于第一行之前;第一个对方法的调用接下来使第一行成为当前行;第二个调用使第二行成为当前行,依此类推。


解决方案

因此,虽然不需要任何循环,但需要将光标前进一次。从技术上讲,一个nil就足够了:

ResultSet

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

  

当对rs.next();方法的调用返回rs.next(); // Access the result 时,光标将位于最后一行之后。 需要当前行的next方法的任何调用都会导致抛出false

因此,在这种情况下,代码将失败。

因此,您应该对此案件负责,并使用返回的ResultSet来保护您的访问权限:

SQLException

答案 1 :(得分:21)

来自the official documentation(您应该读过btw):

  

最初,光标位于第一行之前。 next方法将光标移动到下一行,并且由于ResultSet对象中没有更多行时它返回false,因此可以在while循环中使用它来迭代结果集。

基本上,您需要移动它,一次移动一次就足够了:

 rs.next(); 
 System.out.println(rs.getInt("L")); 

答案 2 :(得分:10)

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

if(rs.next()) {
    // other code here
}

当您要带回多行时,将使用while

答案 3 :(得分:8)

  

一个ResultSet游标最初位于第一行之前,   首先调用该方法,然后将第一行作为当前行,   第二次调用使第二行成为当前行,依此类推。

考虑您有这样的事情。

$filename    = basename( $file_path );
       // keep this! see https://bugs.php.net/bug.php?id=73597
       $sftp_link   = intval( $this->sftp_link );
       $remote_path = "ssh2.sftp://{$sftp_link}/{$this->path}";
       $remote_file = "{$remote_path}{$filename}";

您的“ rs”最初指向1之前,当您调用rs.next()时,它将使箭头前进以指向1

->1->2->3
^

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

希望这会有所帮助

答案 4 :(得分:1)

执行命令有不同类型。 光标用于从您执行的查询中读取数据。当执行“读取”时,默认情况下使用“仅向前光标”,因此仅在调用Recorset.Next()后才得到下一个结果!我不想在这里更深入。您可以在这里阅读有关游标的信息:https://docs.microsoft.com/en-us/sql/ado/guide/data/types-of-cursors-ado?view=sql-server-2017

您情况下最好的解决方案是使用标量结果集,该结果集将仅返回一个单元格,这正是您要实现的目标,而不必遍历结果集。以下示例说明了如何实现:

"ABC" => true
"ASD*ABC" => true
"JULY*ABC*RTEW" => true
"ASDABC" => false

我们正在使用 ExecuteScalar 仅返回一个单元格。请记住,即使您的查询返回多行/多列,这也只会始终返回非常好的单元格