您好StackOverflow社区:)
我来找你分享我的一个问题......
我必须提取SQL Server实例的每个数据库中每个表的列表,我找到了这个查询:
EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'
它在Microsoft SQL Server Management Studio上完美运行但是当我尝试在我的Java程序中执行 (包括SQL Server的JDBC驱动程序)时,它表示没有返回任何结果。
我的Java代码如下:
this.statement = this.connect.createStatement(); // Create the statement
this.resultats = this.statement.executeQuery("EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'"); // Execute the query and store results in a ResultSet
this.sortie.ecrireResultats(this.statement.getResultSet()); // Write the ResultSet to a file
感谢任何想要帮助我的人, 祝您有个愉快的一天:)
编辑1:
我不确定SQL Server的JDBC驱动程序是否支持我的查询,所以我会尝试以另一种方式实现我的目标。
我想要获得的是SQL Server实例上每个数据库的所有表的列表,输出格式如下:
+-----------+--------+
| Databases | Tables |
+-----------+--------+
所以现在我问有人可以帮助我通过Java的JDBC for SQL Server驱动程序来使用SQL查询来解决这个问题。
我还要感谢我从Tim Lehner和Mark Rotteveel得到的快速答案。
答案 0 :(得分:3)
如果语句可以返回no或多个结果,则不应使用executeQuery
,而应使用execute()
,此方法返回boolean
表示类型第一个结果:
true
:结果为ResultSet
false
:结果是更新计数如果结果为true
,则您使用getResultSet()
检索ResultSet
,否则getUpdateCount()
检索更新计数。如果更新计数为-1
,则表示没有更多结果。请注意,当前结果为-1
时,更新计数也为ResultSet
。如果没有更多结果或者结果是更新计数,那么getResultSet()
应该返回null也是一件好事。
现在,如果您想要检索更多结果,请致电getMoreResults()
(或其兄弟接受int
参数)。 boolean
的返回值与execute()
的返回值相同,因此false
并不意味着没有更多结果!
如果getMoreResults()
返回false并且getUpdateCount()
返回-1
(也在Javadoc中记录),则只会有更多结果
基本上这意味着如果您想要正确处理所有结果,您需要执行以下操作。请注意,我实际上没有尝试使用您的语句,也不确定SQL Server JDBC驱动程序是否正确实现了多个结果,因此它可能无法正常工作:
boolean result = stmt.execute(...);
while(true)
if (result) {
ResultSet rs = stmt.getResultSet();
// Do something with resultset ...
} else {
int updateCount = stmt.getUpdateCount();
if (updateCount == -1) {
// no more results
break;
}
// Do something with update count ...
}
result = stmt.getMoreResults();
}
注意:此答案的部分内容基于我对Java SQL: Statement.hasResultSet()?
的回答答案 1 :(得分:1)
如果您没有收到错误,一个问题可能是sp_msforeachdb
将为每个数据库返回一个单独的结果集,而不是一个包含所有记录的结果集。在这种情况下,您可以尝试使用一些动态SQL来合并所有行:
-- Use sys.tables
declare @sql nvarchar(max)
select @sql = coalesce(@sql + ' union all ', '') + 'select ''' + quotename(name) + ''' as database_name, * from ' + quotename(name) + '.sys.tables'
from sys.databases
select @sql = @sql + ' order by database_name, name'
exec sp_executesql @sql
我有时也会使用INFORMATION_SCHEMA视图,因为它更容易看到模式名称,其中包括:
-- Use INFORMATION_SCHEMA.TABLES to easily get schema name
declare @sql nvarchar(max)
select @sql = coalesce(@sql + ' union all ', '') + 'select * from ' + quotename(name) + '.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = ''BASE TABLE'''
from sys.databases
select @sql = @sql + ' order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME'
exec sp_executesql @sql
请注意这种字符串连接方法(select @sql = foo from bar
)may not work as you intend through a linked server(它只会获取最后一条记录)。只是一个小小的警告。
答案 2 :(得分:1)
<强>更新强>
我找到了解决方案!
在阅读an article about sp_spaceused being used with Java之后,我发现我处于相同的情况。
我的最终代码如下:
this.instances = instances;
for(int i = 0 ; i < this.instances.size() ; i++)
{
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
this.connect = DriverManager.getConnection("jdbc:sqlserver://" + this.instances.get(i), "tluser", "result");
this.statement = this.connect.prepareCall("{call sp_msforeachdb(?)}");
this.statement.setString(1, "Use ?; SELECT DB_NAME() AS DB, name FROM sys.tables WHERE DB_NAME() NOT IN('master', 'model', 'msdb', 'tempdb')");
this.resultats = this.statement.execute();
while(true)
{
int rowCount = this.statement.getUpdateCount();
if(rowCount > 0)
{
this.statement.getMoreResults();
continue;
}
if(rowCount == 0)
{
this.statement.getMoreResults();
continue;
}
ResultSet rs = this.statement.getResultSet();
if(rs != null)
{
while (rs.next())
{
this.sortie.ecrireResultats(rs); // Write the results to a file
}
rs.close();
this.statement.getMoreResults();
continue;
}
break;
}
this.statement.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
它试了一下,我的文件里面有我想要的一切。
谢谢大家的帮助! :)强> 的