代码之家  ›  专栏  ›  技术社区  ›  WolfmanDragon

如何检查cachedrowset中是否存在列名?

  •  9
  • WolfmanDragon  · 技术社区  · 16 年前

    我正在从可能发生更改的视图中查询数据。我需要知道该列是否存在,然后才能执行 crs.get******() .I发现我可以像这样查询元数据,以便在向列请求数据之前查看它是否存在。

    ResultSetMetaData meta = crs.getMetaData();
    int numCol = meta.getColumnCount();
    
    for (int i = 1; i < numCol+1; i++) 
        if(meta.getColumnName(i).equals("name"))
            return true;
    

    有没有更简单的方法来检查列是否存在?

    编辑: 它必须是数据库不可知论者。这就是我引用 CachedRowSet 而不是数据库。

    6 回复  |  直到 6 年前
        1
  •  8
  •   Jared    16 年前

    对于一般的JDBCAPI,没有一个简单的方法(至少我不知道,也找不到……我在自己的工具集中有完全相同的代码)。

    (您的代码不完整):

    ResultSetMetaData meta = crs.getMetaData();
     int numCol = meta.getColumnCount();
    
    for (int i = 1; i < numCol+1; i++) 
    {
        if(meta.getColumnName(i).equals("name"))
        {return true;}
    
    }
    return false;
    

    也就是说,如果您使用专有的、特定于数据库的API和/或SQL查询,我确信您可以找到更优雅的方法来执行相同的操作……但您必须为需要处理的每个数据库编写自定义代码。如果我是你,我会坚持使用JDBCAPI。

    你提出的解决方案中有什么让你觉得不正确的地方吗?我觉得这很简单…

        2
  •  8
  •   Peter Mullarkey    14 年前

    如果列不在cachedRowset中,则可以采用更短的方法来使用findcolumn()将为invalidColumname引发一个sqlException。

    例如

     try {
         int foundColIndex = results.findColumn("nameOfColumn");
    } catch {
      // do whatever else makes sense
    }
    

    可能是滥用了异常处理(根据effectiveJava第二版第57项),但它是循环遍历元数据中所有列的替代方法。

        3
  •  1
  •   OscarRyz    16 年前

    哪个数据库?

    我认为在Oracle中,有一些表列出了列。

    我不记得它是否也适用于视图,但我想它们确实适用,它类似于:

    select colum_name from all_views where view_name like 'myview'
    

    select name from all_objects where object_name like 'myview' and object_type='view'
    

    我不记得确切的语法。不过,您应该拥有空间权限。

    每个RDBMS都应该有类似的东西。

    您还可以执行查询

    select * from myView where 1 = 0 ; 
    

    并且从元数据中获取列,如果您希望它避免在获取数据之前了解列是否存在。

        4
  •  1
  •   Joshua    16 年前

    不,真的没有更好的方法。您可能需要重新确定问题所在。如果您可以重新定义问题,有时它会使解决方案更简单,因为问题已经改变了。

        5
  •  0
  •   davek    15 年前

    警告:以下注释完全来自内存,没有任何支持性文档:)

    如果我没记错的话,当Oracle缓存的行集实现与连接池一起使用时,有一个神秘的问题让我想起了它曾经那么丑陋的一面。似乎有一个对缓存行集对象中保持的连接的无声引用(即使它应该断开连接),它关闭了随后在垃圾收集时从池中打开的另一个连接。出于这个原因,我最终放弃并编写了自己的数据对象层(现在我将把它移交给Spring&Hibernate)。

        6
  •  0
  •   Lutosław    6 年前

    旧线程,但我刚刚遇到了同样的问题,最终得到了一个实用函数:

    private Set<String> getColumnNames(ResultSet cached) throws SQLException {
        ResultSetMetaData metaData = cached.getMetaData();
        return IntStream.range(1, metaData.getColumnCount())
                        .mapToObj(i -> {
                            try {
                                return metaData.getColumnName(i);
                            } catch (SQLException e) {
                                throw new RuntimeException(e);
                            }
                        }).collect(toSet());
    }
    

    如果我们不必在lambda中捕获异常(没有一些难看的黑客),那将是非常激烈的。