Bagaimana cara memeriksa apakah tabel ada dalam database Android SQLite?

87

Saya memiliki aplikasi android yang perlu memeriksa apakah sudah ada catatan di database, dan jika tidak, memproses beberapa hal dan akhirnya memasukkannya, dan cukup membaca data dari database jika datanya memang ada. Saya menggunakan subclass SQLiteOpenHelper untuk membuat dan mendapatkan instance SQLiteDatabase yang dapat ditulis ulang, yang menurut saya secara otomatis akan menangani pembuatan tabel jika belum ada (karena kode untuk melakukannya ada di onCreate (... ) metode).

Namun, ketika tabel BELUM ada, dan metode pertama yang dijalankan pada objek SQLiteDatabase yang saya miliki adalah panggilan ke kueri (...), logcat saya menunjukkan kesalahan "I / Database (26434): sqlite return: error code = 1, msg = no such table: appdata ", dan tentu saja, tabel appdata tidak sedang dibuat.

Ada ide mengapa?

Saya mencari salah satu metode untuk menguji apakah tabel itu ada (karena jika tidak, data pasti tidak ada di dalamnya, dan saya tidak perlu membacanya sampai saya menulisnya, yang tampaknya membuat tabel benar), atau cara untuk memastikan bahwa itu dibuat, dan kosong, pada saat panggilan pertama ke kueri (...)

EDIT
Ini diposting setelah dua jawaban di bawah ini:
Saya pikir saya mungkin telah menemukan masalahnya. Saya untuk beberapa alasan memutuskan bahwa SQLiteOpenHelper yang berbeda seharusnya dibuat untuk setiap tabel, meskipun keduanya mengakses file database yang sama. Saya pikir refactoring kode itu untuk hanya menggunakan satu OpenHelper, dan membuat kedua tabel di dalamnya onCreate dapat bekerja lebih baik ...

camperdave
sumber

Jawaban:

127

Coba yang ini:

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;
    }
}
Nikolay DS
sumber
Terima kasih banyak untuk ini. Bekerja dengan baik. +1
Gray
11
Jangan lupacursor.close();
styler1972
1
Untuk alasan yang tidak diketahui, tablename peka huruf besar kecil. Saya lebih suka menggunakanselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten
4
Jawaban bagus tapi tata bahasa yang menyakitkan! Pasti harus dipanggil 'isTableExisting ()'.
Chris Hatton
1
Ini berfungsi untuk saya tetapi saya harus membungkus kueri dalam coba / menangkap atau aplikasi saya akan mogok ketika tabel tidak ada.
Braden Holt
52

Saya tidak tahu apa-apa tentang Android SQLite API, tetapi jika Anda dapat berbicara langsung dengannya dalam SQL, Anda dapat melakukan ini:

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

Yang akan memastikan bahwa tabel selalu dibuat dan tidak menimbulkan kesalahan apa pun jika sudah ada.

chrisbtoo
sumber
Begitulah cara saya membuat tabel dalam metode onCreate di dalam kelas SQLiteOpenHelper. Di android, disarankan untuk membiarkan kelas itu membuat tabel, karena ini memungkinkan aplikasi untuk memperbarui database-nya secara otomatis, dan tampaknya lebih efisien secara umum. Sayangnya, blok kode yang mengeksekusi kode seperti yang Anda tulis tidak berjalan tepat waktu :(
camperdave
Ini bekerja dengan baik dan juga bekerja dengan indeks, yaitu: "buat indeks jika tidak ada [...]".
Eric Fortier
5
Ini sebenarnya jawaban terbaik untuk pertanyaan yang diajukan.
Android Asli
1
tetapi pertanyaannya tidak meminta untuk membuatnya
10101010
12

Meskipun sudah ada banyak jawaban bagus untuk pertanyaan ini, saya menemukan solusi lain yang menurut saya lebih sederhana. Kelilingi kueri Anda dengan blok percobaan dan tangkapan berikut:

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.
    }
}

Itu berhasil untuk saya!

robguinness
sumber
1
Bukankah lebih baik meletakkan pernyataan Log di dalam blok if ()? Sepertinya jika SQLiteException muncul karena alasan lain selain "tidak ada tabel seperti itu", log akan menunjukkan bahwa Anda membuat tabel, padahal sebenarnya tidak.
2
Menggunakan pengecualian untuk mengontrol aliran adalah sesuatu yang memalukan, tidak diajarkan kepada orang lain. Memeriksa pesan dengan cara itu, dua kali lipatnya.
Nick Cardoso
Jika digunakan dengan hemat, menurut saya tidak ada yang salah dengan menggunakan pengecualian dalam kasus penggunaan seperti yang dijelaskan di atas. Tentu saja tidak ada yang membuat saya malu.
robguinness
Saya pikir e.getMessage().contains("no such table")lebih buruk daripada menggunakan pengecualian untuk aliran kontrol. Keduanya adalah gaya yang buruk, tetapi penguraian pesan kesalahan untuk teks tertentu adalah gaya yang sangat buruk.
jox
11

Inilah yang saya lakukan:

/* 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;
AndroidDebaser
sumber
8

Ya, ternyata teori yang saya edit benar: masalah yang menyebabkan metode onCreate tidak berjalan, adalah fakta bahwa SQLiteOpenHelperobjek harus merujuk ke database, dan tidak memiliki database terpisah untuk setiap tabel. Mengemas kedua tabel menjadi satu SQLiteOpenHelpermemecahkan masalah.

camperdave
sumber
2

Anda menyebutkan bahwa Anda telah membuat kelas yang memperluas SQLiteOpenHelperdan mengimplementasikan onCreatemetode tersebut. Apakah Anda memastikan bahwa Anda melakukan semua panggilan perolehan database Anda dengan kelas itu? Anda seharusnya hanya mendapatkan SQLiteDatabaseobjek melalui the SQLiteOpenHelper#getWritableDatabasedan getReadableDatabasejika tidak, onCreatemetode tidak akan dipanggil saat diperlukan. Jika Anda sudah melakukan itu, periksa dan lihat apakah SQLiteOpenHelper#onUpgrademetode yang dipanggil sebagai gantinya. Jika demikian, maka nomor versi database diubah di beberapa titik waktu tetapi tabel tidak pernah dibuat dengan benar ketika itu terjadi.

Selain itu, Anda dapat memaksa pembuatan kembali database dengan memastikan semua koneksi ke database tersebut ditutup dan memanggil Context#deleteDatabaselalu menggunakan SQLiteOpenHelperuntuk memberi Anda objek db baru.

Rich Schuler
sumber
Saya mendapatkan objek database saya melalui panggilan getWritableDatabase (), maaf saya lupa menyebutkannya. Juga, saya yakin onUpgrade () tidak dipanggil, karena metode itu memiliki panggilan Log.d (...) sebagai baris pertama yang tidak saya lihat di database. Saya akan mencoba menghapus seluruh file database, dan kita akan melihat apakah itu bisa memperbaikinya ...
camperdave
Sayangnya, menghapus seluruh database (saya menggunakan root explorer untuk membersihkan file) tidak berhasil. Saya menggunakan dua tabel di aplikasi saya - salah satunya diinisialisasi dengan sempurna, namun tabel lainnya yang selama ini membuat saya kesulitan tidak melakukannya.
camperdave
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 memelihara tabel sqlite_master yang berisi informasi dari semua tabel dan indeks dalam database.
  • Jadi di sini kita hanya menjalankan perintah SELECT di atasnya, kita akan mendapatkan kursor yang memiliki hitungan 1 jika tabel ada.
Akshansh singh
sumber
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;
}
Yogesh Rathi
sumber
0

no such table exists: error datang karena setelah Anda membuat database dengan satu tabel setelah itu setiap kali Anda membuat tabel dalam database yang sama, kesalahan ini muncul.

Untuk mengatasi kesalahan ini Anda harus membuat database baru dan di dalam metode onCreate () Anda dapat membuat beberapa tabel dalam database yang sama.

Megha
sumber
0

Kondisi penting JIKA TIDAK ADA untuk memeriksa tabel sudah ada atau tidak dalam database

Suka...

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

saya menghadapinya dan menghadapinya dengan mencoba menangkap sesederhana itu saya melakukan apa yang saya inginkan dalam tabel jika tidak ada akan menyebabkan kesalahan jadi tangkap dengan pengecualian dan buatlah :)

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

Aly Abdelaal
sumber
-1

..... Toast t = Toast.makeText (konteks, "coba ...", 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

.....

Srinath Ganesh
sumber