5

Java でデータベース プログラムを作成しており、テーブルが存在しない場合はテーブルを作成したいと考えています。Java で SQL テーブルの存在を検出するにはどうすればよいですか?DatabaseMetaData.getTables()から学びました。そして私はそれを使用しようとしています:

private boolean tableExists() throws SQLException {
    System.out.println("tableExists()");

    DatabaseMetaData dbmd = conn.getMetaData();
    ResultSet rs = dbmd.getTables(null, null, this.getTableName(), null);

    System.out.println("TABLE_NAME: " + rs.getString("TABLE_NAME"));

    return rs.getRow() == 1;
}

問題は、テーブルが作成された後でもrs.getRow()常に を返すことです。0を使用rs.getString("TABLE_NAME")すると、結果セットが空であることを示す例外がスローされます。

私が考えた解決策の 1 つは、CREATE TABLEステートメントを実行し、スローされた例外をキャッチすることです。ただし、プログラムの制御フローに例外を使用するという考えは好きではありません。

FWIW、私はHSQLDBを使用しています。ただし、RDMS エンジンに依存しない Java コードを作成したいと考えています。DatabaseMetaData.getTables()私がやりたいことをするために使用する別の方法はありますか?tableExists()または、私のメソッドを書くための他の解決策はありますか?

追加した:

ここに記載されている提案を使用して、実稼働コードで機能するように見える解決策を見つけました。

private void createTable() throws SQLException {
    String sqlCreate = "CREATE TABLE IF NOT EXISTS " + this.getTableName()
            + "  (brand           VARCHAR(10),"
            + "   year            INTEGER,"
            + "   number          INTEGER,"
            + "   value           INTEGER,"
            + "   card_count           INTEGER,"
            + "   player_name     VARCHAR(50),"
            + "   player_position VARCHAR(20))";

    Statement stmt = conn.createStatement();
    stmt.execute(sqlCreate);
}

現在、テーブルが実際に作成されることをアサートする JUnit テストも作成しています。

public void testConstructor() throws Exception {
    try (BaseballCardJDBCIO bcdb = new BaseballCardJDBCIO(this.url)) {
        String query = "SELECT count(*) FROM information_schema.system_tables WHERE table_name = '" + bcdb.getTableName() + "'";
        Connection conn = DriverManager.getConnection(this.url);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        Assert.assertTrue(rs.next());
        Assert.assertEquals(1, rs.getInt(1));
        Assert.assertFalse(rs.next());
    }
}

このテストはassertEquals()、次のメッセージで失敗します。

FAILED: expected: <1> but was: <0>
4

4 に答える 4

8

私が見つけた解決策はうまくいくようです:

private void createTable() throws SQLException {
    String sqlCreate = "CREATE TABLE IF NOT EXISTS " + this.getTableName()
            + "  (brand           VARCHAR(10),"
            + "   year            INTEGER,"
            + "   number          INTEGER,"
            + "   value           INTEGER,"
            + "   card_count           INTEGER,"
            + "   player_name     VARCHAR(50),"
            + "   player_position VARCHAR(20))";

    Statement stmt = conn.createStatement();
    stmt.execute(sqlCreate);
}

IF NOT EXISTSSQL ステートメントの正しい場所に配置する必要がありました。

于 2012-08-10T21:37:05.890 に答える
3

Java docsのResultSet定義から:

ResultSet オブジェクトは、現在のデータ行を指すカーソルを維持します。最初、カーソルは最初の行の前に配置されます。next メソッドはカーソルを次の行に移動し、ResultSet オブジェクトに行がなくなると false を返すため、while ループで使用して結果セットを反復処理できます。

next()したがって、常にメソッドを呼び出す必要があります。そうしないgetRow()と、カーソルが最初の行の前に配置されるため、常にゼロが返されます。

于 2012-08-10T21:18:42.110 に答える
1

あなたが探しているもののための組み込みのmysql機能があります:http://dev.mysql.com/doc/refman/5.0/en/create-table.html

IF NOT EXISTSつまり、テーブル作成クエリの最後に追加するだけです。

編集:
これを行う一般的な方法はありません。ほとんどのデータベースにはinformation_schemeテーブルがありますが、情報を判別するためのクエリは次のようになります。

SELECT count(*) FROM information_schema.system_tables WHERE table_schem = 'public' AND table_name = 'user';

これは、sqlite、mysql、msql、mariadb、postgres+おそらく他の多くの機能で機能します。

于 2012-08-10T21:13:46.857 に答える
-2

これが必ずしもあなたの目標に役立つかどうかはわかりませんが、PythonとMySQLを使用してこの問題に遭遇したとき、スクリプトを自動的に実行するように、各「テーブルの作成」ステートメントの前に「テーブルの削除」ステートメントを追加しました既存のテーブルを削除してから、各テーブルを再構築します。それはあなたのニーズにはうまくいかないかもしれませんが、それは私が私の同様の問題で成功したと思った1つの解決策です。

于 2012-08-10T21:15:06.997 に答える