Як перевірити, чи існує таблиця в базі даних Android SQLite?


87

У мене є додаток для Android, якому потрібно перевірити, чи вже є запис у базі даних, а якщо ні, то обробити деякі речі та врешті-решт вставити їх та просто прочитати дані з бази даних, якщо вони існують. Я використовую підклас SQLiteOpenHelper для створення та отримання перезаписуваного екземпляра SQLiteDatabase, який, на мою думку, автоматично подбав про створення таблиці, якщо вона ще не існувала (оскільки код для цього знаходиться в onCreate (... ) метод).

Однак, коли таблиця ще НЕ існує, і перший метод, запущений на об'єкті SQLiteDatabase, який є у мене, є викликом запиту (...), мій logcat показує помилку "I / База даних (26434): повернено sqlite: помилка code = 1, msg = такої таблиці немає: appdata ", і, звичайно, таблиця appdata не створюється.

Будь-які ідеї чому?

Я шукаю будь-який метод, щоб перевірити, чи існує таблиця (тому що якщо вона не існує, даних, звичайно, немає в ній, і мені не потрібно їх читати, поки я не напишу в неї, що, здається, створює таблицю належним чином), або спосіб переконатися, що він створюється і є просто порожнім, вчасно для першого виклику запиту (...)

EDIT
Це було опубліковано після двох відповідей нижче:
Я думаю, що, можливо, я знайшов проблему. Я чомусь вирішив, що для кожної таблиці повинен бути створений інший SQLiteOpenHelper, хоча обидва мають доступ до одного файлу бази даних. Я думаю, що рефакторинг цього коду, щоб використовувати лише один 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

1
З невідомої причини назва таблиці чутлива до регістру. Я скоріше використовуюselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten

4
Приємна відповідь, але болюча граматика! Напевно, має називатися 'isTableExisting ()'.
Кріс Хаттон,

1
Це працювало для мене, але мені довелося обернути запит у спробі / лові, інакше мій додаток зірвався б, коли таблиці не існувало.
Braden Holt

52

Я нічого не знаю про Android SQLite API, але якщо ви можете поговорити з ним безпосередньо в SQL, ви можете зробити це:

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

Що гарантуватиме, що таблиця завжди створюється і не видає помилок, якщо вона вже існувала.


Ось так я створюю таблицю в методі onCreate усередині класу SQLiteOpenHelper. В android рекомендується дозволити цьому класу створювати таблицю, оскільки це дозволяє додатку автоматично оновлювати базу даних, і, очевидно, є загалом ефективнішим. На жаль, той блок коду, який виконує код, подібний до того, який ви написали, не запускається вчасно :(
camperdave

Це чудово працює, а також працює з індексами, тобто: "створити індекс, якщо не існує [...]".
Eric Fortier

5
Це насправді найкраща відповідь на поставлене запитання.
Оригінальний Android

1
але питання не задає його створення
10101010

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
Використання винятків для управління потоком - це те, чого слід соромитись, а не вчити інших. Перевіряючи повідомлення таким чином, подвійно.
Нік Кардозу

Якщо використовувати економно, я не думаю, що є щось погане у використанні винятків у таких випадках, як описаний вище. Звичайно нічого, чого я не соромлюсь.
розбійність

Я думаю, 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об’єкти повинні посилатися на бази даних, а не мати окрему для кожної таблиці. Упакування обох таблиць в одну SQLiteOpenHelperвирішило проблему.


2

Ви згадали, що створили клас, який розширює SQLiteOpenHelperта впроваджує onCreateметод. Ви переконуєтесь, що виконуєте всі дзвінки з бази даних для отримання даних із цим класом? Ви повинні отримувати тільки SQLiteDatabaseоб'єкти з допомогою SQLiteOpenHelper#getWritableDatabaseі в getReadableDatabaseіншому випадку onCreateметод не буде викликатися , коли це необхідно. Якщо ви це вже робите, перевірте, чи SQLiteOpenHelper#onUpgradeзамість цього викликається метод th . Якщо так, тоді номер версії бази даних був змінений у певний момент часу, але таблиця ніколи не була створена належним чином, коли це сталося.

Окрім того, ви можете примусити відновити базу даних, переконавшись, що всі підключення до неї закриті та викликаючи, Context#deleteDatabaseа потім використовуючи, SQLiteOpenHelperщоб дати вам новий об’єкт db.


Ну, я отримую свій об'єкт бази даних через виклик getWritableDatabase (), вибачте, я забув це вказати. Крім того, я впевнений, що onUpgrade () не викликається, оскільки для цього методу першим рядком є ​​виклик Log.d (...), якого я не бачу в базі даних. Я спробую видалити весь файл бази даних, і ми побачимо, чи це якось виправляє ...
camperdave

На жаль, видалення всієї бази даних (для очищення файлу я використовував провідник root) не вдалося. Я використовую дві таблиці в своєму додатку - одна з них ідеально ініціалізована, однак інша, яка весь час створювала мені проблеми, ні.
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 підтримує таблицю 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 приходить, тому що після того, як ви створюєте базу даних з однією таблицею, щоразу, коли ви створюєте таблицю в одній базі даних, це видає цю помилку.

Щоб вирішити цю помилку, вам потрібно створити нову базу даних, а всередині методу 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 (контекст, "спробувати ...", 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

.....

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.