2

こんにちはStackOverflowコミュニティ:)

私はあなたに私の問題の1つを共有するために来ました...

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 driverを介してSQLクエリを使用しています.

また、 Tim LehnerMark Rotteveelから得た非常に迅速な回答にも感謝します。

4

3 に答える 3

4

ステートメントが結果を返さないか複数を返す可能性がある場合は、を使用しないでください。executeQuery代わりexecute()に、このメソッドはboolean最初の結果のタイプを示すを返します。

  • true:結果はResultSet
  • false:結果は更新カウントです

結果がtrue、の場合は、を使用getResultSet()してResultSet、それ以外の場合getUpdateCount()は更新カウントを取得します。更新カウントがそうである場合、-1それはそれ以上の結果がないことを意味します。更新カウントは-1、現在の結果が。の場合にも発生することに注意してくださいResultSetgetResultSet()結果がこれ以上ない場合、または結果が更新カウントである場合は、nullを返す必要があることも知っておくとよいでしょう。

さらに結果を取得したい場合は、呼び出しますgetMoreResults()(またはその兄弟が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();
}

注:この回答の一部は、Java SQLに対する私の回答に基づいています:Statement.hasResultSet()?

于 2013-02-04T19:37:11.233 に答える
1

エラーが発生しない場合、1 つの問題sp_msforeachdbとして、すべてのレコードを含む 1 つのセットではなく、データベースごとに個別の結果セットが返される可能性があります。その場合は、動的 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)の方法は、リンク サーバーを介して意図したとおりに機能しない可能性があることに注意してください(最後のレコードのみを取得します)。ちょっとした注意事項です。

于 2013-02-04T16:19:19.277 に答える
1

アップデート

私は解決策を見つけました!

Java で使用されている sp_spaceused に関する記事を読んだ後、私も同じケースにいることがわかりました。

私の最終的なコードは次のとおりです。

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();
    }
}

試してみたところ、私のファイルには必要なものがすべて含まれています。

助けてくれてありがとう!:)

于 2013-02-05T09:47:32.827 に答える