使用 ODBC 或 JDBC 获取 Select 语句的列元数据的标准方法?

Standard way to use ODBC or JDBC to get column metadata of Select statement?

是否有一种跨供应商兼容的方法来获取 ODBC 或 JDBC 中任意 SELECT 语句的列元数据而无需执行查询?

我作为供应商正在构建分析工具。我不能假设用户可以创建临时表。在声明中添加 TOP 或 LIMIT 会起作用吗?这能保证快速 return 时间吗?

我也愿意使用 Apache Calcite 或其他 SQL 解析库。我不知道这些库是否真的知道参数和 return 类型的函数。

我怀疑答案是 "no" 但哪些供应商更容易获得前期支持?

在JDBC中可以准备语句,然后检索ResultSetMetaData using PreparedStatement.getMetaData():

Connection connection = ...;
try (PreparedStatement pstmt = connection.prepareStatement("your statement")) {
    ResultSetMetaData rsmd = pstmt.getMetaData();
    int columnCount = rsmd.getColumnCount()

    // java.sql.Types type of first column
    int columnType = rsmd.getColumnType(1);
}

但是,此方法是可选的(允许驱动程序不实现它,并且 - 根据 javadoc - 在某些实现中它可能很昂贵),因此不能保证它适用于所有 JDBC司机。

有关详细信息,请参阅 javadoc。

我不太了解ODBC,但据我所知它具有类似的功能。

在 @Mark 的 JDBC 回答中添加来自 ODBC 方面的见解:

ODBC 确实有一个名为 SQLDescribeCol 的低级机制用于检索列信息(如果可能)。然而,它通常被那些构建 ODBC 接口层(例如,pyodbc)或其他直接从 C/C++ 应用程序写入 ODBC API 的人使用。

我不记得曾经见过实现类似于 JDBC 的 PreparedStatement#getMetaData 的 ODBC 接口层。例如,.NET 中的 System.Data.Odbc.OdbcCommand 有一个显式 .Prepare() 方法,但它没有检索结果集元数据的方法;为此,您需要一个 OdbcDataReader 对象,您可以通过调用 .ExecuteReader().

获得一个对象

所以 AFAIK 获取结果集元数据的最 "cross-vendor-compatible" 方法是将实际查询包装在一个 return 没有行的外部查询中,例如对于 C# 中的 ODBC ...

string actual_query = "SELECT many_columns FROM many_tables WHERE many_conditions";
string metadata_query = $"SELECT * FROM ({actual_query}) AS subquery WHERE 1=0";
var cmd = new OdbcCommand(metadata_query, conn);
OdbcDataReader rdr = cmd.ExecuteReader();
DataTable dt = rdr.GetSchemaTable();

... 并希望查询优化器足够聪明,知道它不必处理来自子查询的 "many_conditions",因为外部查询永远不会 return 任何行。