JDBC ResultSet获取具有表别名的列

时间:2011-08-28 21:21:40

标签: java sql oracle jdbc resultset

想象一下,我有一个像

这样的查询
SELECT * from table1 a, table2 b where (WHATEVER)

也许两个表都有相同的列名。所以我觉得通过

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

但这对我不利,我一无所获。我读了API,但他们并没有真正谈论这个案例。这样的功能供应商是否依赖?

8 个答案:

答案 0 :(得分:45)

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使用基于一个的索引 - 即它们来自1(而不是来自0的java索引),因此请使用1对于第一列,第二列为2,等等


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

答案 1 :(得分:13)

ResultSetMetadata.getColumnLabel()是您需要的

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

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

ResultSetMetaData rsmd = rset.getMetaData();
rsmd.getColumnLabel(1);

答案 2 :(得分:8)

使用列别名,如:

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

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

答案 3 :(得分:5)

如果您使用的是MySQL,请添加

&useOldAliasMetadataBehavior=true

到你的connectionString。

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

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

}

答案 4 :(得分:1)

好吧,似乎没有类似resultSet.getString("a.columnName");的方法 并且你必须在sql级别为列添加别名, 但是因为我希望有一个getTableName(iCol)方法 java.sql.ResultSet添加此功能。

答案 5 :(得分:0)

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

SELECT a.column, b.column FROM table1 a, table2 b

String value = rs.getString(1);

答案 6 :(得分:0)

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

答案 7 :(得分:0)

把你的sql改成

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

您可以通过表别名从结果集读取

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