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

时间:2019-08-06 15:48:27

标签: jdbc odbc apache-calcite

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

我正在作为供应商构建分析工具。我不能认为用户可以创建临时表。在语句中抛出TOP或LIMIT是否可行?这样可以保证快速返回时间吗?

我也对Apache Calcite或其他SQL解析库开放。我不知道这些库中的任何一个是否真的知道函数的参数和返回类型。

我怀疑答案是否定的,但是哪些供应商更容易预先支持?

2 个答案:

答案 0 :(得分:2)

在JDBC中,您可以准备语句,然后使用ResultSetMetaData来检索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,但据我所知它具有类似的功能。

答案 1 :(得分:2)

通过ODBC方面的见识添加到@Mark的JDBC答案:

ODBC确实具有一种名为SQLDescribeCol的低级机制,用于检索列信息(如果可能)。但是,构建ODBC接口层(例如,pyodbc)或其他直接从C / C ++应用程序写入ODBC API的人员通常使用这种方法。

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

因此AFAIK获取结果集元数据的最“跨供应商兼容”的方式是将实际查询包装在不返回任何行的外部查询中,例如用于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”,因为外部查询永远不会返回任何行。