是否存在一种跨供应商兼容的方式来获取ODBC或JDBC中任意SELECT语句的列元数据,而无需执行查询?
我正在作为供应商构建分析工具。我不能认为用户可以创建临时表。在语句中抛出TOP或LIMIT是否可行?这样可以保证快速返回时间吗?
我也对Apache Calcite或其他SQL解析库开放。我不知道这些库中的任何一个是否真的知道函数的参数和返回类型。
我怀疑答案是否定的,但是哪些供应商更容易预先支持?
答案 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”,因为外部查询永远不会返回任何行。