执行;sp_msforeachdb";在Java应用程序中
嗨,社区:) 我来和你分享我的一个问题 我必须提取SQL Server实例的每个数据库中每个表的列表,我发现以下查询:执行;sp_msforeachdb";在Java应用程序中,java,sql-server,stored-procedures,jdbc,sp-msforeachdb,Java,Sql Server,Stored Procedures,Jdbc,Sp Msforeachdb,嗨,社区:) 我来和你分享我的一个问题 我必须提取SQL Server实例的每个数据库中每个表的列表,我发现以下查询: EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables' 它在MicrosoftSQLServerManagementStudio上运行得非常好,但是当我尝试在Java程序中执行它时(包括用于SQLServer的JDBC驱动程序),它说它不会返回任何结果 我的Java代码如下所示: this.
EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'
它在MicrosoftSQLServerManagementStudio上运行得非常好,但是当我尝试在Java程序中执行它时(包括用于SQLServer的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
+-----------+--------+
| Databases | Tables |
+-----------+--------+
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();
}
}
感谢所有愿意帮助我的人,
祝你今天愉快:)
编辑1:
我不确定SQL Server的JDBC驱动程序是否支持我的查询,因此我将尝试以另一种方式实现我的目标
我试图得到的是SQL Server实例上每个数据库的所有表的列表,输出格式如下:
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
+-----------+--------+
| Databases | Tables |
+-----------+--------+
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();
}
}
所以现在我想问有人能帮我通过Java的JDBC for SQL Server驱动程序使用SQL查询找到解决方案吗
我还想感谢从和得到的非常快速的答案。如果您没有收到错误,一个问题可能是
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
我有时也会使用信息模式视图,因为更容易看到模式名称以及其他内容:
-- 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
)(它只会获取最后一条记录)。只是一个小小的警告。如果一个语句可以返回no或多个结果,则不应使用executeQuery
,而是该方法返回一个布尔值,指示第一个结果的类型:
true
:结果是一个ResultSet
false
:结果是更新计数
如果结果为true
,则使用检索ResultSet
,否则检索更新计数。如果更新计数为-1
,则表示没有更多结果。请注意,当当前结果为ResultSet
时,更新计数也将为-1
。如果没有更多的结果或者结果是更新计数,getResultSet()
应该返回null,这也是一个好消息
现在,如果您想检索更多结果,可以调用(或其兄弟接受int
参数)。boolean
的返回值与execute()
的返回值具有相同的含义,因此false
并不意味着没有更多的结果
只有当getMoreResults()
返回false并且getUpdateCount()
返回-1
时,才会有更多的结果(正如Javadoc中所述)
本质上,这意味着如果您想正确处理所有结果,您需要执行以下操作:
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();
}
注:部分答案基于我对更新的回答
我找到了解决办法强>
读过之后,我发现我也遇到了同样的情况
我的最终代码如下:
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
+-----------+--------+
| Databases | Tables |
+-----------+--------+
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();
}
}
this.instances=实例;
对于(int i=0;i0)
{
this.statement.getMoreResults();
继续;
}
如果(行计数==0)
{
this.statement.getMoreResults();
继续;
}
ResultSet rs=this.statement.getResultSet();
如果(rs!=null)
{
while(rs.next())
{
this.sortie.ecriresults(rs);//将结果写入文件
}
rs.close();
this.statement.getMoreResults();
继续;
}
打破
}
这个.statement.close();
}
捕获(例外e)
{
e、 printStackTrace();
}
}
它试过了,我的文件里有我想要的一切
谢谢大家的帮助!:)强大>哇,快速回答!我可以把它包含到我的Java程序中吗?我对JDBC不太熟悉,所以我只是猜测你可以把这整个东西放在executeQuery()
命令中。如果这不起作用,您可以尝试使用基本的exec sp_who
或其他方法,以确保可以通过这种方式从进程中获得结果集。使用与你的应用程序相同的用户/密码登录SSMS也不会有什么坏处。我明天会尝试,并会通知你我的进展情况。无论如何,谢谢你的帮助!你的帖子很完整,教了我很多关于一些方法还没有掌握。问题是我实现了你的解决方案,但我无法让它与我的查询一起工作。。。“我认为司机不支持。”VincentKelleher不幸的是,我会看看是否能找到替代方案。非常感谢!我花了好几天的时间到处搜索,似乎没有人尝试过。。。