使用 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 任何行。
是否有一种跨供应商兼容的方法来获取 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 任何行。