【问题标题】:JDBC ResultSet get columns with table aliasJDBC ResultSet 获取具有表别名的列
【发布时间】:2011-11-05 15:28:50
【问题描述】:

想象一下我有一个类似的查询

SELECT * from table1 a, table2 b where (WHATEVER)

可能两个表具有相同的列名。所以我认为通过

访问数据会很好
resultSet.getString("a.columnName");
resultSet.getString("b.columnName");

但这适得其反,我什么也得不到。我阅读了 API,但他们并没有真正谈论这个案例。这样的功能供应商是否依赖?

【问题讨论】:

    标签: java sql oracle jdbc resultset


    【解决方案1】:

    JDBC 将通过查询中指定的内容简单地命名列 - 它不知道表名等。

    你有两个选择:

    选项1:在查询中以不同的方式命名列,即

    SELECT
        a.columnName as columnNameA,
        b.columnName as columnNameB,
        ...
    from table1 a, table2 b where (WHATEVER)
    

    然后在您的 java 代码中引用列别名:

    resultSet.getString("columnNameA");
    resultSet.getString("columnNameB");
    


    选项 2:在调用 JDBC API 时参考列位置

    resultSet.getString(1);
    resultSet.getString(2);
    

    注意 JDBC API 使用 one-based 索引 - 即它们从 1 开始计数(不像 java 索引那样从 0 开始计数),所以在第一列使用 1,@ 987654327@ 第二列等


    我会推荐选项 1,因为引用命名列更安全:有人可能会更改查询中列的顺序,它会默默地破坏您的代码(您将访问错误的列但不知道),但如果他们更改列名,您至少会在运行时获得“没有这样的列”异常。

    【讨论】:

    • 好吧,看来我将不得不忘记漂亮的 * 并命名所有内容并使用额外的映射。
    【解决方案2】:

    ResultSetMetadata.getColumnLabel() 是你需要的

    (编辑) 示例示例,如 bharal 在评论中所述

    SELECT * from table1 a, table2 b where (WHATEVER)
    
    ResultSetMetaData rsmd = rset.getMetaData();
    rsmd.getColumnLabel(1);
    

    【讨论】:

    • 你可以通过示例代码 sn-p 编辑答案
    • 使用 SQLite JDBC 驱动程序,这只会给我列名,例如username,而不是完整的 a.username。有没有办法得到a,表别名?
    【解决方案3】:

    使用列别名,例如:

    SELECT A.ID 'A_ID', B.ID 'B_ID' FROM TABLE1 AS A, TABLE2 AS B...
    

    并指定您要检索的所有列(这是一个很好的做法)。

    【讨论】:

      【解决方案4】:

      如果您使用的是 MySQL,只需添加

      &useOldAliasMetadataBehavior=true
      

      到您的连接字符串。

      之后你就可以使用这个小助手了:

      import java.sql.ResultSet;
      import java.sql.ResultSetMetaData;
      import java.sql.SQLException;
      import java.util.HashMap;
      import java.util.Map;
      
      public class ResultSetHelper {
      
          private final Map<String, Integer> columnMap;
      
          public ResultSetHelper(ResultSet rs) throws SQLException {
              this.columnMap = new HashMap<>();
              ResultSetMetaData md = rs.getMetaData();
              int columnCount = md.getColumnCount();
              for (int index = 1; index <= columnCount; index++) {
                  String columnName = md.getColumnLabel(index);
                  if (!columnMap.containsKey(columnName)) {
                      columnMap.put(columnName, index);
                  }
      
                  String tableAlias = md.getTableName(index);
                  if (tableAlias != null && !tableAlias.trim().isEmpty()) {
                      columnMap.put(tableAlias + "." + columnName, index);
                  }
              }
          }
      
          public Integer getColumnIndex(String columnName) {
              return columnMap.get(columnName);
          }
      
          public Integer getColumnIndex(String tableAlias, String columnName) {
              return columnMap.get(tableAlias + "." + columnName);
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        好的,好像没有resultSet.getString("a.columnName");这样的方法 你必须在 sql 级别为你的列加上别名, 但因为有一个 getTableName(iCol) 方法我希望大家 java.sql.ResultSet添加这样的功能。

        【讨论】:

          【解决方案6】:

          您可以在 SQL 级别使用别名。 然后通过索引检索数据。 (但这种方法会使维护成为一场真正的噩梦)

          SELECT a.column, b.column FROM table1 a, table2 b
          
          String value = rs.getString(1);
          

          【讨论】:

            【解决方案7】:

            我的一个想法是使用getTableName(iCol) 来获取重复命名列的表名,然后包装您自己的键的散列(带有表名前缀),它将指向正确的列索引,并以这种方式引用您的列值。这将需要在开始时通过元数据进行初始循环来设置。我看到的唯一问题是您也在给表名起别名。我还没有找到一种从 jdbc 获取这些表名别名的方法,而无需在构建 sql 语句时自行管理。这个解决方案将取决于你的语法回报。

            【讨论】:

            【解决方案8】:

            把你的sql改成

            SELECT a.*, b.* from table1 a, table2 b where (WHATEVER)
            

            你可以通过表别名从resulset中读取

            resultSet.getString("a.columnName");
            resultSet.getString("b.columnName");
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-12-31
              • 2011-02-06
              • 2017-05-12
              • 2012-08-08
              • 2014-06-25
              • 1970-01-01
              • 2014-01-06
              相关资源
              最近更新 更多