2

我正在构建一个报告工具,我需要对远程数据库执行查询并将结果集存储在我自己的数据库中(因为我没有远程数据库的写权限,而且我需要缓存结果以防止进一步执行)。此外,我需要此功能,因此我可以将两个结果集连接在一起并根据生成的结果生成结果。

现在,我的问题是我不知道如何基于 jdbc ResultSet 创建表。是否有任何开源工具或脚本可以处理这个问题?

我的应用程序基于 Spring 3.1.0 并使用 JDBC 来查询本地和远程数据库。我要存储结果的本地数据库是 MySQL 5.5.20。(这是存储在 MySQL 中的好主意吗?它提供了足够的性能吗?)

4

5 回答 5

8

我们可以从结果集中提取最近的匹配结构并构造一个表。
但这不可能是精确的副本,就表名、键、引擎类型、字段是否可为空等而言

以下代码片段可帮助您以某种方式继续获得适当的结果。

String sql = "select * from visitors";
ResultSet rs = stmt.executeQuery( sql );
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
String tableName = null;
StringBuilder sb = new StringBuilder( 1024 );
if ( columnCount > 0 ) { 
    sb.append( "Create table " ).append( rsmd.getTableName( 1 ) ).append( " ( " );
}
for ( int i = 1; i <= columnCount; i ++ ) {
    if ( i > 1 ) sb.append( ", " );
    String columnName = rsmd.getColumnLabel( i );
    String columnType = rsmd.getColumnTypeName( i );

    sb.append( columnName ).append( " " ).append( columnType );

    int precision = rsmd.getPrecision( i );
    if ( precision != 0 ) {
        sb.append( "( " ).append( precision ).append( " )" );
    }
} // for columns
sb.append( " ) " );

System.out.println( sb.toString() );

使用上述部分代码执行,打印以下字符串:

Create table visitors ( ip VARCHAR( 6 ), bro VARCHAR( 6 ) )

让我希望这可以帮助您进一步进行。

类似的示例可以在以下位置找到:使用 ResultSet 创建表???

更新 1

我如何处理只存在于一个数据库中而不存在于另一个数据库中的类型

仅依赖于客户端应用程序的结果集时,您无能为力。
它应该始终是从复合数据类型(如,等)中选择适当数据的主选择查询。示例geometryaddress
select addess.city, address.zipcode, x( geometry_column ), y( geometry_column )

举一个geometry数据类型的例子:
MySQL 有对其空间支持的定义。但我不确定它们与SQL Server 的 Spatial Data 实现相比有多好。

geometry是一种复合数据类型,因此不能通过直接查询来检索。
您需要从这些数据列解析数据并以可读可识别的数据格式返回的依赖函数。
示例create table geom ( g geometry );
将 ResultSet 从select g from geom使用 JAVA 转换为 create table 语句将导致unknwon列的数据类型g

Create table geom ( g UNKNOWN )

在列上使用x(g),y(g)坐标函数g将返回正确且可接受的数据类型。
查询select x(g), y(g) from geom将转换为

Create table  ( x(g) DOUBLE( 23, 31 ), y(g) DOUBLE( 23, 31 ) ) 

更新 2
可能会使用关系结合多个表生成结果集。结果集字段也有可能由表达式及其别名组成。因此,生成的列字段或别名的数据类型是动态确定的。元数据不知道查询中的表、列名及其原始/父数据类型的确切名称。

所以,无法获得

  1. 表的单一名称并使用它。
  2. 父列的数据类型并使用它。

注意:这也适用于所有其他跨数据库特定数据类型,例如NVARCHAR等。但是,请参阅此帖子以了解 MySQL 中 NVARCHAR 用法的替代方法

在尝试这种动态数据迁移之前,客户端应用程序应该有责任了解等效的数据类型并相应地使用它们。

此外,有关更多信息,请参阅Microsoft Access、MySQL 和 SQL Server 的数据类型和范围。

于 2012-06-29T20:43:14.843 回答
3

也许这有点棘手,但我认为它可能会帮助你。

JDBC ResultSet 对象有一个getMetaData()方法,该方法返回一个ResultSetMetaData对象,其中包含列名和列类型等。你可以这样做:

ResultSet rs;
String strSQL;

...

strSQL = "create table tbl ("
for(i=0;i<rs.getMetaData().getColumnCount(),i++) {
    if(i>0)
        strSQL += ", "
    strSQL += rs.getMetaData().getColumnName(i) 
           + " " 
           + rs.getMetaData().getColumnType(i);
}
strSQL+= ")"

....

您可以通过这种方式构造一个包含您需要的列的有效 SQL DML。之后,剩下的就是填充表格。

希望这对您有所帮助。

于 2012-06-29T20:50:33.237 回答
1

您可能拥有基于执行选择查询的 ResultSet。现在,我们可以执行单个查询来创建表,而不是获取 ResultSet 然后遍历它来创建表。

您的原始查询:

select * from table_name

而不是执行这个和迭代,执行这个

create table new_table_name as (select * from table_name)

于 2013-09-18T09:02:50.560 回答
0

如此所述,您可以使用普通的 SQL 来执行此操作,如下所示:

CREATE TABLE artists_and_works
  SELECT artist.name, COUNT(work.artist_id) AS number_of_works
  FROM artist LEFT JOIN work ON artist.id = work.artist_id
  GROUP BY artist.id;
于 2012-06-29T19:49:05.070 回答
0

如果您想要一个通用的解决方案来处理数据库之间不同但在 java 中类型相同的数据类型,您可以使用JDBCType。只需采用 Ravinder Reddy 解决方案并更改此行:

String columnType = rsmd.getColumnTypeName( i );

String columnType = JDBCType.valueOf(rsmd.getColumnType(i)).getName();

希望能帮助到你。

于 2018-06-21T17:07:11.060 回答