如何检查结果集是不是有一行或更多?

Posted

技术标签:

【中文标题】如何检查结果集是不是有一行或更多?【英文标题】:How to check if resultset has one row or more?如何检查结果集是否有一行或更多? 【发布时间】:2011-02-05 05:04:01 【问题描述】:

如何使用 JDBC 检查结果集是否有一行或多行?

【问题讨论】:

这确实是 JDBC 中缺少的东西,原因是并非所有数据库系统都支持提前获取结果集的大小(因为结果不是预取的)。不幸的是,这意味着您无法在支持它的数据库(例如 mysql)中轻松使用这些功能。 Java ResultSet how to check if there are any results的可能重复 【参考方案1】:

我的明智建议:获取第一个结果行,然后尝试获取下一个结果行。如果尝试成功,则您有不止一行。

如果有不止一行,并且您想要处理该数据,则需要缓存第一行中的内容,或者使用可滚动的结果集,以便您可以在通过结果。

您还可以通过在查询的其余部分执行SELECT COUNT(*) 来直接向 SQL 询问此信息;结果将是 0、1 或更多,具体取决于查询的其余部分将返回多少行。这很容易实现,但需要对数据库进行两次查询,假设您接下来要读取和处理实际查询。

【讨论】:

【参考方案2】:
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
boolean isMoreThanOneRow = rs.first() && rs.next();

你没有问这个,但你可能需要它:

boolean isEmpty = ! rs.first();

通常,我们不需要行数,因为我们使用 WHILE 循环而不是 FOR 循环来迭代结果集:

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) 
    // retrieve and print the values for the current row
    int i = rs.getInt("a");
    String s = rs.getString("b");
    float f = rs.getFloat("c");
    System.out.println("ROW = " + i + " " + s + " " + f);

但是,在某些情况下,您可能希望将结果窗口化,并且您需要提前将记录计数显示给用户,例如 Row 1 to 10 of 100。您可以先使用SELECT COUNT(*) 进行单独查询,以获取记录计数,但请注意,该计数只是近似值,因为可以在执行两个查询的时间之间添加或删除行。

来自ResultSet Overview的样本

【讨论】:

isMoreThanOneRow 给我错误,请求的操作不支持只转发结果集。 @Vodo-SioskBaas,您需要在executeQuery 语句之后立即执行此操作,这样first() 就不需要倒带或更改您的光标,以便它可以倒带。跨度> 【参考方案3】:

有很多选择,由于您没有提供更多上下文,所以剩下的就是猜测。我的答案按复杂性和性能升序排序。

    只需运行select count(1) FROM ... 即可获得答案。您必须运行另一个实际选择并返回数据的查询。 使用rs.next() 进行迭代并数数,直到您满意为止。然后,如果您仍然需要实际数据,请重新运行相同的查询。 如果您的驱动程序支持向后迭代,请使用rs.next() 几次,然后使用rs.previous() 倒回。

【讨论】:

如果您的驱动程序不支持向后迭代,first() 通常可以重新开始。【参考方案4】:

您不需要 JDBC。通常的习惯用法是将所有结果收集到一个集合中,并利用集合方法,例如List#size()

List<Item> items = itemDAO.list();

if (items.isEmpty()) 
    // It is empty!
if (items.size() == 1) 
    // It has only one row!
 else 
    // It has more than one row!

list() 方法看起来像什么:

public List<Item> list() throws SQLException 
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    List<Item> items = new ArrayList<Item>();

    try 
        connection = database.getConnection();
        statement = connection.createStatement();
        resultSet = statement.executeQuery(SQL_LIST);
        while (resultSet.next()) 
            Item item = new Item();
            item.setId(resultSet.getLong("id"));
            item.setName(resultSet.getString("name"));
            // ...
            items.add(item);
        
     finally 
        if (resultSet != null) try  resultSet.close();  catch (SQLException logOrIgnore) 
        if (statement != null) try  statement.close();  catch (SQLException logOrIgnore) 
        if (connection != null) try  connection.close();  catch (SQLException logOrIgnore) 
    

    return items;

【讨论】:

这不能很好地扩展。如果结果集有数百万行怎么办? @mindas:那么SELECT * FROM table 他们已经没有意义了。那么你需要SELECT COUNT(*) FROM table。 JDBC 根本不是用于此特定目的的正确工具,这正是 JDBC 中不存在虚构的 ResultSet#size() 方法的原因。 原始问题从未说过它正在做SELECT * FROM table 我也没有建议过。最初的问题并没有假设所有数据实际上也是必要的。 @mindas:不管怎样,仍然没有理由使用 JDBC 来做这件事。要么使用 SQL 选择行数,要么使用集合方法获取结果大小。【参考方案5】:

使用ResultSetMetaData 类获取行数。

您可以从您的代码中创建ResultSetMetaData,例如:

ResultSetMetaData rsmd = resultSet.getMetaData();   //get ResultSetMetaData
rsmd.getColumnCount();       // get row count from resultsetmetadata

【讨论】:

-1 ResultSetMetaData 与行数无关。rsmd.getColumnCount() 为您提供结果集的列数【参考方案6】:

如果要确保正好一行,可以确保第一行是最后一行:

ResultSet rs = stmt.executeQuery("SELECT a FROM Table1 WHERE b=10");
if (rs.isBeforeFirst() && rs.next() && rs.isFirst() && rs.isLast()) 
    // Logic for where there's exactly 1 row
    Long valA = rs.getLong("a");    
    // ... 
 
else   
    // More that one row or 0 rows returned.    
    // .. 

【讨论】:

这不起作用,因为rs.next() 已经跳到下一个结果集,它会给你错误的数据。我在 join 子句上对其进行了测试,它删除了一个元素【参考方案7】:

此实现允许您检查查询结果是否为空,但代价是复制了一些行。

ResultSet result = stmt.executeQuery("SELECT * FROM Table");

if(result.next()) 
   // Duplicate the code which should be pasted inside while
   System.out.println(result.getInt(1));
   System.out.println(result.getString(2));

   while(result.next())
   System.out.println(result.getInt(1));
   System.out.println(result.getString(2));
   
else
System.out.println("Query result is empty");

缺点:

    在此实现中,部分代码将被复制。 您无法知道结果中有多少行。

【讨论】:

以上是关于如何检查结果集是不是有一行或更多?的主要内容,如果未能解决你的问题,请参考以下文章

对空结果集的非法操作 - 如何检查它是不是为空? [复制]

如何在不使用大型结果集的情况下检查一个字符串是不是是另一个字符串的子字符串?

Postgres检查jsonb数组是不是不包含值返回空结果集

JDBC——ResultSet结果集对象

MS SQL语句declare游标的求助

如何将 DBUtils 结果集转换为由更多域对象组合而成的 JavaBeans?