JDBC ResultSet 获取具有表别名的列

Posted

技术标签:

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

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

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

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

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

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

【问题讨论】:

【参考方案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 语句时自行管理。这个解决方案将取决于你的语法回报。

【讨论】:

@Bohemian - 您可以使用 ResultSetMetaData::getTableName(int) 函数来获取表名。不过,我不确定结果是否取决于 jdbc 实现。 docs.oracle.com/javase/7/docs/api/java/sql/…【参考方案8】:

把你的sql改成

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

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

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

【讨论】:

以上是关于JDBC ResultSet 获取具有表别名的列的主要内容,如果未能解决你的问题,请参考以下文章

在Postgres中加入两个表后如何为具有相同名称的列提供别名

如何从子查询中获取 ResultSet 的别名?

使用 java 创建具有约束的配置单元表并使用 jdbc 程序检查配置单元表的列约束

如何使用普通 JDBC 获取目标表的名称和外键列的列

从 jdbc/postgresql 获取新创建表的列元数据

在 JDBC 中获取列名