JDBC: 获取涉及SQL查询的表名

8

有没有办法通过JDBC执行的SQL查询了解涉及的表的名称?

例如:

SELECT r.roleId FROM User u, UserRole r where r.userId = u.userId and u.name = "Jonh Smith"

我不仅需要此查询的结果集,还需要实际的表名(“User”和“Role”)。我不关心视图名称,但如果无法获取视图中使用的基础表,则不是很重要,但必须能够处理嵌套查询。
至于为什么我需要这个信息,那是因为我正在创建一个平台,让其他开发人员在其上构建应用程序。在我的平台上,我允许其他开发人员注册自己的查询,并将它们存储在数据库中。我不希望开发人员必须手动注册表名以及查询本身。因此,在执行查询时,我实际上并不知道该查询正在做什么。

5
无意冒犯,但您所描述的(“我允许其他开发人员注册他们自己的查询并将它们存储在数据库中...因此在执行查询时,我实际上并不知道该查询正在做什么。”)是一种等待发生 SQL 注入攻击的行为。 - Brian Roach
1
@BrianRoach 好吧,我应该在问题上说清楚,其他开发人员不会在我的服务器上运行他们的应用程序。每个对我的平台的“定制”将由开发人员自己单独部署。因此,我可以相信查询不会被利用。应用程序的普通用户将无法访问查询。 - Hoffmann
2个回答

4
我还没有找到如何完全满足您需要的方法,但我会发布这篇文章,因为它太长了不能作为评论。我找到的最接近的方法是ResultSetMetaData。这是一个关于如何获取它的教程:链接。但是该教程没有展示如何获取表名,这个方法叫做getTableName
/**
 * Gets the designated column's table name. 
 *
 * @param column the first column is 1, the second is 2, ...
 * @return table name or "" if not applicable
 * @exception SQLException if a database access error occurs
 */
String getTableName(int column) throws SQLException;

我认为您需要遍历所有的列,并将表名放入一个 Set 中。这样得到的结果应该是使用的所有表,但是问题是,如果该列在选择中没有暴露出来,那么您将无法发现这个表。我尚未找到解决方法。


嗯,当我提出这个问题时,我并不是很有希望能得到解决方案,但实际上这对我的情况确实有效。然而,我还有另一个问题,在我的平台上,我让开发人员提供他们正在使用的JDBC驱动程序的.jar文件。因此,我无法保证他们使用的JDBC驱动程序与规范完全兼容,我能相信所有主要驱动程序都正确实现了ResultSetMetaData吗? - Hoffmann
请注意,因为有些驱动程序不实现这样的方法。例如,当使用Redshift的官方驱动程序时,getTableName返回null。 - Vilis
你有解决方案吗?我正在尝试创建一个框架组件,在其中可以访问SQL查询和预处理语句(Update/Delete/Insert)。我想要知道表名。在插入/更新/删除语句中,我无法使用getResultSet().getMetadata().getTableName() - ThrowableException

4

JSQLParser库(LGPL V2.1)似乎能够完全满足所需:

从SQL中提取表名

Statement statement = CCJSqlParserUtil.parse("SELECT * FROM MY_TABLE1");
Select selectStatement = (Select) statement;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tableList = tablesNamesFinder.getTableList(selectStatement);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接