Android SQLite veritabanında bir tablo olup olmadığı nasıl kontrol edilir?


87

Veritabanında halihazırda bir kayıt olup olmadığını kontrol etmesi ve yoksa, bazı şeyleri işleyip sonunda eklemesi ve veri mevcutsa verileri veritabanından okuyup okuması gereken bir android uygulamam var. Yeniden yazılabilir bir SQLiteDatabase örneği oluşturmak ve almak için SQLiteOpenHelper'ın bir alt sınıfını kullanıyorum; bu, zaten mevcut değilse tabloyu otomatik olarak oluşturmayı düşündüğüm (çünkü bunu yapacak kod onCreate'de (... ) yöntem).

Ancak, tablo henüz OLMADIĞINDA ve sahip olduğum ilk yöntem SQLiteDatabase nesnesi üzerinde çalıştırıldığında, bir sorgu (...) çağrısı olduğunda, logcat'im "I / Database (26434): sqlite döndü: hata code = 1, msg = böyle bir tablo yok: appdata "ve tabii ki appdata tablosu oluşturulmuyor.

Neden hakkında bir fikriniz var mı?

Tablonun var olup olmadığını test etmek için bir yöntem arıyorum (çünkü yoksa, veriler kesinlikle içinde değil ve tabloya yazana kadar okumam gerekmiyor, bu da tabloyu oluşturuyor gibi görünüyor düzgün) veya ilk sorgu çağrısı için zamanında oluşturulduğundan ve boş olduğundan emin olmanın bir yolu (...)

DÜZENLE
Bu, aşağıdaki iki cevaptan sonra yayınlanmıştır:
Sorunu bulduğumu düşünüyorum. Her ikisi de aynı veritabanı dosyasına erişmesine rağmen, bazı nedenlerden dolayı her tablo için farklı bir SQLiteOpenHelper oluşturulması gerektiğine karar verdim. Bu kodu yalnızca bir OpenHelper kullanacak şekilde yeniden düzenlemenin ve onCreate'in içinde her iki tabloyu oluşturmanın daha iyi çalışabileceğini düşünüyorum ...

Yanıtlar:


127

Bunu dene:

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

Bunun için çok teşekkürler. Harika çalışıyor. +1
Grey

11
Unutmacursor.close();
styler1972

1
Bilinmeyen bir nedenle, tablo adı büyük / küçük harfe duyarlıdır. select * from sqlite_master where UPPER(name) = 'ROUTES'.
Kullanmayı

4
Güzel cevap ama acı dilbilgisi! Kesinlikle 'isTableExisting ()' olarak adlandırılmalıdır.
Chris Hatton

1
Bu benim için çalıştı, ancak sorguyu bir dene / yakala ile sarmam gerekiyordu, yoksa tablo yokken uygulamam çöküyordu.
Braden Holt

52

Android SQLite API hakkında hiçbir şey bilmiyorum, ancak onunla doğrudan SQL'de konuşabiliyorsanız, şunu yapabilirsiniz:

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

Bu, tablonun her zaman oluşturulmasını ve zaten mevcutsa herhangi bir hata atmamasını sağlayacaktır.


SQLiteOpenHelper sınıfı içindeki onCreate yönteminde tabloyu bu şekilde oluşturuyorum. Android'de, uygulamanın veritabanını otomatik olarak güncellemesine izin verdiği ve görünüşe göre genel olarak daha verimli olduğu için bu sınıfın tabloyu oluşturmasına izin verilmesi önerilir. Maalesef, yazdığınız kod
bloğu

Bu harika çalışıyor ve aynı zamanda dizinlerle de çalışıyor, yani: "yoksa dizin oluştur [...]".
Eric Fortier

5
Bu aslında sorulan soru için en iyi cevap.
Orijinal Android

1
ancak soru bir tane oluşturmayı
istemiyor

12

Bu soruya halihazırda çok sayıda güzel cevap olmasına rağmen, daha basit olduğunu düşündüğüm başka bir çözüm buldum. Sorgunuzu bir try bloğu ve aşağıdaki yakalama ile çevreleyin:

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

Benim için çalıştı!


1
Log deyimini if ​​() bloğunun içine koymak daha iyi olmaz mıydı? Görünüşe göre SQLiteException "böyle bir tablo yok" dışında başka bir nedenle atılırsa, günlük, siz aslında yapmadığınız halde tabloyu sizin oluşturduğunuzu gösterecektir.

2
Akışı kontrol etmek için istisnaları kullanmak utanılacak bir şeydir, başkalarına öğretilmez. Mesajı bu şekilde kontrol etmek, iki kez.
Nick Cardoso

Az kullanılıyorsa, yukarıda açıklanan gibi kullanım durumlarında istisnaların kullanılmasında yanlış bir şey olduğunu düşünmüyorum. Kesinlikle utandığım bir şey yok.
robguinness

e.getMessage().contains("no such table")Kontrol akışı için istisnalar kullanmaktan daha kötü olduğunu düşünüyorum . Her ikisi de kötü stildir, ancak belirli bir metin için hata mesajlarını ayrıştırmak bile çok kötü bir stildir.
jox

11

Ben de öyle yaptım:

/* 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

Evet, düzenlememdeki teori doğru çıktı: onCreate yönteminin çalışmamasına neden olan sorun, SQLiteOpenHelpernesnelerin veritabanlarına başvurması ve her tablo için ayrı bir tane olmamasıydı. Her iki tabloyu da tek bir tabloyu birleştirmek SQLiteOpenHelpersorunu çözdü.


2

Yöntemi genişleten SQLiteOpenHelperve uygulayan bir sınıf yarattığınızdan bahsettiniz onCreate. O sınıfla tüm veri tabanınızın aramalarını gerçekleştirdiğinizden emin misiniz? Yalnızca elde gerektiğini SQLiteDatabasearacılığıyla nesneleri SQLiteOpenHelper#getWritableDatabaseve getReadableDatabaseaksi onCreategerektiğinde yöntemi denir edilmeyecektir. Bunu zaten yapıyorsanız, kontrol edin veSQLiteOpenHelper#onUpgrade bunun yerine yöntemin çağrılıp çağrılmadığını . Öyleyse, veritabanı sürüm numarası zaman içinde bir noktada değiştirildi, ancak bu gerçekleştiğinde tablo hiçbir zaman düzgün oluşturulmadı.

Bir kenara, veritabanına yapılan tüm bağlantıların kapatıldığından ve arayarak Context#deleteDatabaseve ardından SQLiteOpenHelpersize yeni bir db nesnesi vermek için kullanarak veritabanının yeniden oluşturulmasını zorlayabilirsiniz .


Veritabanı nesnemi getWritableDatabase () çağrısı aracılığıyla alıyorum, üzgünüm bunu belirtmeyi unuttum. Ayrıca, onUpgrade () 'nin çağrılmadığından eminim, çünkü bu yöntemin veritabanında görmediğim ilk satırı olarak bir Log.d (...) çağrısı var. Tüm veritabanı dosyasını silmeyi deneyeceğim ve bunun bir şekilde
düzeltip

Ne yazık ki, tüm veritabanını silmek (dosyayı temizlemek için kök gezgini kullandım) işe yaramadı. Uygulamamda iki tablo kullanıyorum - bunlardan biri mükemmel bir şekilde başlatıldı, ancak diğeri baştan beri bana sorun çıkarıyor.
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, veritabanındaki tüm tablo ve indekslerin bilgilerini içeren sqlite_master tablosunu tutar.
  • Yani burada basitçe SELECT komutunu çalıştırıyoruz, eğer tablo varsa 1 numaralı imleci elde edeceğiz.

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 geliyor çünkü bir kez bir tablo ile veritabanı oluşturduğunuzda, aynı veritabanında her tablo oluşturduğunuzda bu hatayı veriyor.

Bu hatayı çözmek için yeni veritabanı oluşturmanız gerekir ve onCreate () yönteminin içinde aynı veritabanında birden çok tablo oluşturabilirsiniz.


0

Önemli bir durum mevcut değilseTablonun zaten var olup olmadığını kontrol etmek için

sevmek...

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

0

bununla karşılaştım ve bununla başa çıkmaya çalışın ki, tablodaki istediğimi yapacağım kadar basit yakala, yoksa hataya neden olur, bu yüzden istisnalarla yakalayın ve oluşturun :)

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

..... Toast t = Toast.makeText (bağlam, "dene ...", 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

.....

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.