Android SQLiteデータベースにテーブルが存在するかどうかをどのように確認しますか?


87

データベースにすでにレコードがあるかどうかを確認する必要があるAndroidアプリがあります。ない場合は、いくつかの処理を行って最終的に挿入し、データが存在する場合はデータベースからデータを読み取るだけです。SQLiteOpenHelperのサブクラスを使用して、SQLiteDatabaseの書き換え可能なインスタンスを作成および取得しています。これは、テーブルがまだ存在しない場合は自動的に処理されると考えていました(これを行うコードはonCreate(... ) 方法)。

ただし、テーブルがまだ存在せず、SQLiteDatabaseオブジェクトで実行された最初のメソッドがquery(...)の呼び出しである場合、logcatに「I / Database(26434):sqlitereturned:error」というエラーが表示されます。 code = 1、msg =そのようなテーブルはありません:appdata "、そして確かに、appdataテーブルは作成されていません。

理由について何かアイデアはありますか?

テーブルが存在するかどうかをテストする方法を探しています(存在しない場合、データは確かにテーブルにないため、テーブルを作成しているように見える、テーブルに書き込むまで読み取る必要はありません)適切に)、または最初のquery(...)の呼び出しに間に合うように、作成されて空であることを確認する方法

編集
これは以下の2つの答えの後に投稿されました:
私は問題を見つけたかもしれないと思います。どちらも同じデータベースファイルにアクセスしているにもかかわらず、何らかの理由で、テーブルごとに異なるSQLiteOpenHelperを作成することにしました。そのコードをリファクタリングして1つのOpenHelperのみを使用し、onCreate内に両方のテーブルを作成するとうまくいくと思います...

回答:


127

これを試してください:

public boolean isTableExists(String tableName, boolean openDb) {
    if(openDb) {
        if(mDatabase == null || !mDatabase.isOpen()) {
            mDatabase = getReadableDatabase();
        }

        if(!mDatabase.isReadOnly()) {
            mDatabase.close();
            mDatabase = getReadableDatabase();
        }
    }

    String query = "select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'";
    try (Cursor cursor = mDatabase.rawQuery(query, null)) {
        if(cursor!=null) {
            if(cursor.getCount()>0) {
                return true;
            }
        }
        return false;
    }
}

これをどうもありがとう。よく働く。+1
グレイ

11
忘れないでくださいcursor.close();
styler1972 2012年

1
理由は不明ですが、テーブル名では大文字と小文字が区別されます。私はむしろ使用しますselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten 2013

4
いい答えですが、文法が苦痛です!確かに「isTableExisting()」と呼ばれるべきです。
クリスハットン2014年

1
これは私にとってはうまくいきましたが、クエリをtry / catchでラップする必要がありました。そうしないと、テーブルが存在しないときにアプリがクラッシュしていました。
Braden Holt

52

Android SQLite APIについては何も知りませんが、SQLで直接話すことができる場合は、次のようにすることができます。

create table if not exists mytable (col1 type, col2 type);

これにより、テーブルが常に作成され、既に存在する場合はエラーがスローされないことが保証されます。


これが、SQLiteOpenHelperクラス内のonCreateメソッドでテーブルを作成する方法です。Androidでは、そのクラスにテーブルを作成させることをお勧めします。これにより、アプリはデータベースを自動的に更新でき、一般的には明らかに効率が高くなります。残念ながら、あなたが書いたものとよく似たコードを実行するコードブロックは時間内に実行されていません:(
camperdave 2010年

これはうまく機能し、インデックスでも機能します。つまり、「存在しない場合はインデックスを作成します[...]」。
Eric Fortier 2013

5
これは実際に尋ねられた質問に対する最良の答えです。
オリジナルのAndroid

1
しかし、質問はそれを作成することを求めていません
10101010 2017年

12

この質問に対する良い答えはすでにたくさんありますが、私はもっと簡単だと思う別の解決策を思いつきました。クエリをtryブロックと次のキャッチで囲みます。

catch (SQLiteException e){
    if (e.getMessage().contains("no such table")){
            Log.e(TAG, "Creating table " + TABLE_NAME + "because it doesn't exist!" );
            // create table
            // re-run query, etc.
    }
}

それは私のために働いた!


1
Logステートメントをif()ブロック内に配置する方が良いのではないでしょうか。「そのようなテーブルがありません」以外の理由でSQLiteExceptionがスローされた場合、ログにはテーブルを作成していることが示されますが、実際には作成されていません。

2
例外を使用してフローを制御することは恥ずべきことであり、他の人に教えられることではありません。そのようにメッセージをチェックすることは、二重にそうです。
Nick Cardoso

控えめに使用すれば、上記のようなユースケースで例外を使用しても問題はないと思います。確かに私が恥ずかしいことは何もありません。
robguinness 2018年

e.getMessage().contains("no such table")制御フローに例外を使用するよりも悪いと思います。どちらも悪いスタイルですが、特定のテキストのエラーメッセージの解析は非常に悪いスタイルです。
jox

11

これは私がしたことです:

/* open database, if doesn't exist, create it */
SQLiteDatabase mDatabase = openOrCreateDatabase("exampleDb.db", SQLiteDatabase.CREATE_IF_NECESSARY,null);

Cursor c = null;
boolean tableExists = false;
/* get cursor on it */
try
{
    c = mDatabase.query("tbl_example", null,
        null, null, null, null, null);
        tableExists = true;
}
catch (Exception e) {
    /* fail */
    Log.d(TAG, tblNameIn+" doesn't exist :(((");
}

return tableExists;

8

はい、私の編集の理論は正しかったことがわかりました。onCreateメソッドが実行されない原因となった問題は、SQLiteOpenHelperオブジェクトがデータベースを参照する必要があり、テーブルごとに個別のデータベースを持たないという事実でした。両方のテーブルを1つにパックするとSQLiteOpenHelper、問題が解決しました。


2

メソッドを拡張SQLiteOpenHelperして実装するクラスを作成したとのことですがonCreate。そのクラスですべてのデータベース取得呼び出しを実行していることを確認していますか?あなただけ取得する必要がありますSQLiteDatabase経由でオブジェクトをSQLiteOpenHelper#getWritableDatabaseし、getReadableDatabaseそうでない場合はonCreate、必要なときにメソッドが呼び出されません。それを行っている場合SQLiteOpenHelper#onUpgradeは、代わりにメソッドが呼び出されているかどうかを確認してください。その場合、データベースのバージョン番号はある時点で変更されましたが、そのときにテーブルが正しく作成されませんでした。

余談ですが、データベースへのすべての接続が閉じていることを確認して呼び出しContext#deleteDatabase、次にを使用しSQLiteOpenHelperて新しいdbオブジェクトを提供することにより、データベースの再作成を強制できます。


さて、getWritableDatabase()呼び出しを介してデータベースオブジェクトを取得しています。申し訳ありませんが、指定するのを忘れました。また、onUpgrade()が呼び出されていないことは確かです。そのメソッドには、データベースに表示されていない最初の行としてLog.d(...)呼び出しがあるためです。データベースファイル全体を削除してみますが、
それで問題が解決

残念ながら、データベース全体の削除(ルートエクスプローラーを使用してファイルを削除しました)は機能しませんでした。私はアプリで2つのテーブルを使用しています。1つは完全に初期化されていますが、もう1つはずっと問題を抱えていました。
camperdave 2010年

2
 // @param db, readable database from SQLiteOpenHelper

 public boolean doesTableExist(SQLiteDatabase db, String tableName) {
        Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);

    if (cursor != null) {
        if (cursor.getCount() > 0) {
            cursor.close();
            return true;
        }
        cursor.close();
    }
    return false;
}
  • sqliteは、データベース内のすべてのテーブルとインデックスの情報を含むsqlite_masterテーブルを維持します。
  • したがって、ここでは単にSELECTコマンドを実行しているだけで、テーブルが存在する場合はカウント1のカーソルを取得します。

0
 public boolean isTableExists(String tableName) {
    boolean isExist = false;
    Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);
    if (cursor != null) {
        if (cursor.getCount() > 0) {
            isExist = true;
        }
        cursor.close();
    }
    return isExist;
}

0

no such table exists: error その後、1つのテーブルでデータベースを作成すると、同じデータベースにテーブルを作成するたびにこのエラーが発生するためです。

このエラーを解決するには、新しいデータベースを作成する必要があり、onCreate()メソッド内で同じデータベースに複数のテーブルを作成できます。


0

重要な条件は、存在しない場合です、テーブルがデータベースにすでに存在しているかをチェックします

お気に入り...

String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "("
            + KEY_PLAYER_ID + " TEXT,"
            + KEY_PLAYER_IMAGE + " TEXT)";
db.execSQL(query);

0

私はそれに直面し、それが存在しない場合はテーブルでやりたいことをするのと同じくらい簡単にキャッチしてみるとエラーが発生するので、例外でキャッチして作成します:)

SQLiteDatabase db=this.getWritableDatabase();
        try{
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }catch (SQLiteException e){
            db.execSQL("create table o_vacations (id integer primary key ,name text ,vacation text,date text,MONTH text)");
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }


-1

.....トーストt = Toast.makeText(context、 "try ..."、Toast.LENGTH_SHORT); t.show();

    Cursor callInitCheck = db.rawQuery("select count(*) from call", null);

    Toast t2a = Toast.makeText(context, "count rows " + callInitCheck.getCount() , Toast.LENGTH_SHORT);
    t2a.show();

    callInitCheck.moveToNext();
    if( Integer.parseInt( callInitCheck.getString(0)) == 0) // if no rows then do
    {
        // if empty then insert into call

....。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.