Java JDBC ResultSet获取具有表别名的列

Java JDBC ResultSet获取具有表别名的列,java,sql,oracle,jdbc,resultset,Java,Sql,Oracle,Jdbc,Resultset,假设我有一个这样的问题 SELECT * from table1 a, table2 b where (WHATEVER) 可能两个表都有相同的列名。所以我觉得通过网络访问数据会很好 resultSet.getString("a.columnName"); resultSet.getString("b.columnName"); 但这对我来说适得其反,我一无所获。我读了API,但他们并没有真正谈论这个案例。此功能是否依赖于供应商?使用列别名,如: SELECT A.ID 'A_ID', B.

假设我有一个这样的问题

SELECT * from table1 a, table2 b where (WHATEVER)
可能两个表都有相同的列名。所以我觉得通过网络访问数据会很好

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

但这对我来说适得其反,我一无所获。我读了API,但他们并没有真正谈论这个案例。此功能是否依赖于供应商?

使用列别名,如:

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

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

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);
请注意,JDBCAPI使用基于一的索引,即它们从
1
开始计数(而不是像java索引那样从
0
),因此第一列使用
1
,第二列使用
2
,以此类推



我建议使用选项1,因为引用命名列更安全:有人可能会更改查询中列的顺序,它会悄悄地破坏您的代码(您可能访问了错误的列,但不知道),但如果他们更改了列名称,您至少会在运行时遇到“无此类列”异常

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


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

好的,似乎没有像
resultSet.getString(“a.columnName”)这样的方法
您必须在sql级别为列别名,
但是由于有一个
getTableName(iCol)
方法,我希望大家在
java.sql.ResultSet
添加这样一个功能。

ResultSetMetadata.getColumnLabel()就是您所需要的

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

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

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

如果您使用的是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);
    }

}
导入java.sql.ResultSet;
导入java.sql.ResultSetMetaData;
导入java.sql.SQLException;
导入java.util.HashMap;
导入java.util.Map;
公共类结果服务器{
私人最终地图;
公共结果集(ResultSet rs)抛出SQLException{
this.columnMap=newhashmap();
ResultSetMetaData md=rs.getMetaData();
int columnCount=md.getColumnCount();
对于(int index=1;index将sql更改为

SELECT a.*, b.* from table1 a, table2 b where (WHATEVER)
您可以通过表别名读取结果集

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

好的,看来我必须忘记nice*并命名所有内容,使用额外的映射。现在,您可以使用SQLite JDBC驱动程序通过示例代码段编辑答案,这只给我列名称,例如,
username
,而不是full
a.username
。有没有办法获得
a
,表别名?@Bohemian-您可以使用ResultSetMetaData::getTableName(int)函数获取表名。不过,我不确定结果是否取决于jdbc实现。
resultSet.getString("a.columnName");
resultSet.getString("b.columnName");