【问题标题】:How can I determine if the column name exist in the ResultSet?如何确定 ResultSet 中是否存在列名?
【发布时间】:2011-04-05 17:14:59
【问题描述】:

由于ResultSet包含动态SQL返回的数据,有没有办法判断ResultSet是否包含特定的列名?

例如,如果我运行rs.getString("Column_ABC"),但"Column_ABC" 并不真正存在,则会抛出异常。

如何测试ResultSet 是否可以从名为"Column_ABC" 的列中获取数据?

【问题讨论】:

    标签: java jdbc resultset


    【解决方案1】:
    private boolean isThere(ResultSet rs, String column){
        try{
            rs.findColumn(column);
            return true;
        } catch (SQLException sqlex){
            logger.debug("column doesn't exist {}", column);
        }
    
        return false;
    }
    

    【讨论】:

    • @mjuarez,在这种情况下,findColumn 命令返回并不重要。理所当然地忽略了。这个isThere 方法肯定不会总是返回true。 findColumn 如果未找到该列,则抛出 SQLException。这个答案似乎很好。
    【解决方案2】:

    resultSet.getColumnMetaData().contains(columnName)

    【讨论】:

    • 你能根据变量名修改你的答案吗?你能解释一下它是如何工作的吗?
    • ResultSet接口没有getColumnMetaData方法
    【解决方案3】:
    /**
     * returns default value if column is not present in resultset
     * 
     * @param rs
     * @param columnLabel
     * @param defaultValue
     * @return
     */
    @SuppressWarnings("unchecked")
    private static <T> T getValueFromResultSet(final ResultSet rs,
            String columnLabel, T defaultValue) {
        try {
            return (T) rs.getObject(columnLabel);
        } catch (SQLException e) {
            return defaultValue;
        }
    }
    

    在 java 版本 >=7 中,您可以选择在 ResultSet#getObject 方法中传递 Class 类型

    【讨论】:

    • 这应该是正确的答案。这是一种从行中提供获取对象类型的安全方法,填充/映射一个对象,无论它是否打算被填充,客户端或底层业务逻辑应该知道会发生什么,并安全检查它的数据.
    • 我不同意,Erick Robertson 在上述答案的 cmets 中解释了原因。
    • 虽然这行得通,但它滥用了异常处理背后的想法。
    【解决方案4】:

    不确定这是否比 Erick 的答案更有效,但它更容易。

    String str;
    
    try {
        str = rs.getString(columnName);
    } catch (java.sql.SQLException e) {
        str = null;
    }
    

    【讨论】:

    • 毫无疑问,它更容易理解。但是,不管我没有看到 JDBC 驱动程序返回“SQLServer”异常这一事实,如果列名无效或发生更一般的 SQL 错误(这使知道发生了什么的工作变得困难),ResultSet 方法将返回 SQLException:如果列名错误或发生实际错误)+info@ResultSet Javadoc
    • -1 应仅在特殊情况下使用异常,然后将其记录下来。采取简单的方法往往会创建难以理解和维护的代码。如果您正在使用服务器端结果集并且在进行此调用之前失去了与数据库的连接,那么即使该列存在,此方法也会引发异常。如果代码使用此检查(例如)来确定整个数据库是否需要初始化,这种情况可能会导致灾难性后果。
    • 谢谢 João 你是对的。我的意思是 SQLException。试图选择一个通用的。
    【解决方案5】:

    使用ResultSetMetaData 类。

    public static boolean hasColumn(ResultSet rs, String columnName) throws SQLException {
        ResultSetMetaData rsmd = rs.getMetaData();
        int columns = rsmd.getColumnCount();
        for (int x = 1; x <= columns; x++) {
            if (columnName.equals(rsmd.getColumnName(x))) {
                return true;
            }
        }
        return false;
    }
    

    我不明白为什么永远需要这个功能。正在执行的查询或存储过程应该有已知的结果。查询的列应该是已知的。需要这样的功能可能表明某处存在设计问题。

    【讨论】:

    • 这基本上是正确的,但是getColumnName的参数是从1而不是0开始的。你需要for (int x = 1; x &lt;= columns; x++)
    • 搜索列名没什么奇怪的。在高度动态的、用户可配置的系统中,列集可能会根据用户选择而有很大差异。是的,可以确定该集合,但假设它始终是硬编码的,因此已知是不正确的。
    • 如果您有兴趣获取 SQL 查询的 AS 子句定义的名称,可以使用 ResultSetMetaData.getColumnLabel
    • 我建议使用equalsIgnoreCase 来检查名称是否相同。在我的情况下,我在查询中有一个小写的列名,它从getColumnName() 函数以大写形式返回
    • 是的,DB 模式应该是众所周知的。 但是,您可能会遇到这样一种情况,即一个存储过程从JOIN 返回一列,而另一个存储过程不返回该列。仅执行所需的连接可能对性能有好处,而不是选择具有默认值的不必要的列来匹配您的应用程序可能使用的理论架构。通过拥有类似rs.containsColumn(x) 的东西,一个方法可以读取任一存储过程的结果,而不是第二个方法,它少一个rs.get***(),否则与第一个相同。没有?
    【解决方案6】:

    如果不是 rs.getString("Column_ABC")= nothing 那么 ' 你的代码在这里

    【讨论】:

    • 这是个坏主意,也是错误的。当列不存在时,它不会返回任何内容。它会抛出一个 SQLException,您必须捕获并处理它。您永远不应该使用抛出的异常来进行这样的简单检查。您应该始终寻找一种实际返回布尔值的方法 - 实际执行正确检查的方法。
    猜你喜欢
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多