喜的StackOverflow社区:)
我来给大家分享一下我的问题之一......
我要提取的SQL Server实例的每个数据库中每个表的名单 ,我发现这个查询:
EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'
它完美的微软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:
我不知道那的JDBC驱动程序SQL Server支持我的查询,所以我会尽量让我以另一种方式的目标。
我想要得到的是对一个SQL Server实例的每个数据库中的所有表的列表 ,输出格式为以下几点:
+-----------+--------+
| Databases | Tables |
+-----------+--------+
所以,现在我问有人可以帮我去使用直通Java的JDBC SQL查询的SQL Server驱动程序的解决方案。
我还要感谢非常快速解答我从拿到添莱纳和马克Rotteveel 。
如果一个语句可以返回没有或多个结果,你不应该使用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()?
如果你没有得到一个错误,一个问题可能是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
) 如你打算通过链接服务器可能无法正常工作 (它将只抢到最后一个记录)。 只是一个小的警告。
UPDATE
我已经找到了解决方案!
看完后约注释sp_spaceused正在与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();
}
}
它尝试过了,我的文件中有我想要的一切在里面。
感谢大家的帮助 ! :)