如何确定ResultSet中是否存在列名?


71

由于ResultSet包含从动态SQL返回的数据,是否有任何方法确定ResultSet包含是否包含特定的列名?

例如,如果我跑步rs.getString("Column_ABC")"Column_ABC"实际上并不存在,它将抛出异常。

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

Answers:


115

使用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;
}

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


10
这基本上是正确的,但getColumnName其参数应从1而不是0开始。您需要for (int x = 1; x <= columns; x++)
Adrian Smith

34
搜索列名并不奇怪。在高度动态的,用户可配置的系统中,列集可能会根据用户的选择而大相径庭。是的,可以确定该集合,但是假设它始终是硬编码的,因此已知是不正确的。
Gullbyrd 2014年

7
ResultSetMetaData.getColumnLabel如果您有兴趣获取由ASSQL查询子句定义的名称,则可以使用。
桑托什

3
我建议使用equalsIgnoreCase检查名称是否相同。在我的情况下,我在查询中使用了小写的列名,该列名从getColumnName()函数中以大写形式返回
Luca Regazzi,

3
是的,数据库模式应该是众所周知的。但是,您可能会遇到以下情况:一个存储的proc从中返回一列JOIN,而另一个存储的proc不返回该列。仅执行所需的联接可能对性能有好处,而不是选择不必要的具有默认值的列以匹配您的应用可能消耗的理论架构。通过使用类似的rs.containsColumn(x)方法,一个方法可以读取任何一个存储的proc的结果,而不是第二个方法(少一个)rs.get***(),该方法与第一个方法相同。没有?
s.co.tt

10
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;
}

1
欢迎使用堆栈溢出。您的答案似乎无法回答问题。它丢弃对的调用findColumn,并且始终返回true。请先验证,然后再发布答案。
mjuarez

8
@mjuarez,findColumn在这种情况下,命令返回并不重要。理应忽略。此isThere方法肯定并不总是返回true。findColumn如果找不到该列,则抛出SQLException。这个答案似乎很好。
杰瑞德(Jared)

6

不知道这是否比Erick的回答有效或更低,但是更容易。

String str;

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

1
毫无疑问,它更容易理解。但是,不管我没有看到JDBC驱动程序返回“ SQLServer”异常的事实,如果列名无效或发生了更为通用的SQL错误,ResultSet方法都将返回SQLException(这使了解发生了什么事情变得困难:如果错列名或如果发生实际误差)+信息@ ResultSet中的Javadoc
若奥·迪亚斯·阿马罗

33
-1异常应仅在特殊情况下使用,然后应将其记录下来。采取简单的方法往往会创建难以理解和维护的代码。如果使用服务器端结果集并且在进行此调用之前丢失了与数据库的连接,则即使该列存在,此方法也将引发异常。如果代码使用此检查(例如)来确定整个数据库是否需要初始化,则这种情况可能导致灾难性的后果。
艾里克·罗伯逊

感谢João,您是对的。我的意思是SQLException。试图选择一个通用的。
2014年


-4
/**
 * 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中,您可以选择在Re​​sultSet#getObject方法中传递类类型


这应该是正确的答案。这是一种安全的方法,可提供从行获取对象的类型,填充/映射对象,无论是否要填充对象,客户端或基础业务逻辑都应知道期望值,并安全检查其数据。
thekevshow's

1
我不同意,埃里克·罗伯逊(Erick Robertson)在上述答案的评论中解释了原因。
Pieter De Bie

2
尽管这可行,但它滥用了异常处理背后的思想。

-17

如果不是rs.getString(“ Column_ABC”)=什么都没有'您的代码在这里


8
这是一个坏主意,也是错误的。当某列不存在时,它不会返回任何内容。它抛出一个SQLException,您必须捕获并处理它。绝对不要使用抛出异常的方式进行这样的简单检查。您应该始终寻找一个实际上返回布尔值的方法-一种实际上会执行正确检查的方法。
艾里克·罗伯逊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.