Как проверить, существует ли таблица в базе данных Android SQLite?

87

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

Однако, когда таблица еще НЕ существует, а первый метод, запущенный для объекта SQLiteDatabase, который у меня есть, - это вызов query (...), мой logcat показывает ошибку «I / Database (26434): sqlite return: error code = 1, msg = no such table: appdata ", и конечно же, таблица appdata не создается.

Есть идеи почему?

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

ИЗМЕНИТЬ
Это было опубликовано после двух ответов ниже:
Думаю, я нашел проблему. Я по какой-то причине решил, что для каждой таблицы должен был создаваться отдельный SQLiteOpenHelper, даже если оба обращаются к одному и тому же файлу базы данных. Я думаю, что рефакторинг этого кода для использования только одного OpenHelper и создание обеих таблиц внутри onCreate может сработать лучше ...

Camperdave
источник

Ответы:

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
Gray
11
Не забывайтеcursor.close();
styler1972 07
1
По неизвестной причине имя таблицы чувствительно к регистру. Я предпочитаю использоватьselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten
4
Хороший ответ, но мучительная грамматика! Обязательно следует называть isTableExisting ().
Крис Хаттон
1
Это сработало для меня, но мне пришлось заключить запрос в try / catch, иначе мое приложение вылетело бы, если таблица не существовала.
Брейден Холт
52

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

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

Это гарантирует, что таблица всегда создается и не вызывает ошибок, если она уже существует.

Chrisbtoo
источник
Вот как я создаю таблицу в методе onCreate внутри класса SQLiteOpenHelper. В Android рекомендуется разрешить этому классу создавать таблицу, так как это позволяет приложению автоматически обновлять свою базу данных и в целом, по-видимому, более эффективен. К сожалению, этот кодовый блок, который выполняет код, очень похожий на тот, который вы написали, не
запускается
Это отлично работает, а также работает с индексами, например: «создать индекс, если не существует [...]».
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
Использование исключений для управления потоком - это то, чего следует стыдиться, а не учить других. Проверяя сообщение таким образом, вдвойне.
Ник Кардосо
При умеренном использовании я не думаю, что есть что-то плохое в использовании исключений в таких случаях, как описанный выше. Конечно, мне не стыдно.
robguinness
Я считаю, что 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;
AndroidDebaser
источник
8

Да, оказалось, что теория в моем редактировании была правильной: проблема, из-за которой метод onCreate не запускался, заключалась в том, что SQLiteOpenHelperобъекты должны ссылаться на базы данных, а не иметь отдельную таблицу для каждой таблицы. Объединение обеих таблиц в одну SQLiteOpenHelperрешило проблему.

Camperdave
источник
2

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

Кроме того, вы можете принудительно воссоздать базу данных, убедившись, что все соединения с ней закрыты и вызываются, Context#deleteDatabaseа затем используют, SQLiteOpenHelperчтобы предоставить вам новый объект db.

Рич Шулер
источник
Итак, я получаю объект своей базы данных с помощью вызова getWritableDatabase (), извините, я забыл это указать. Кроме того, я уверен, что onUpgrade () не вызывается, поскольку этот метод имеет вызов Log.d (...) в качестве первой строки, которую я не вижу в базе данных. Я попробую удалить весь файл базы данных, и мы посмотрим,
исправит
К сожалению, удаление всей базы данных (я использовал корневой проводник для очистки файла) не помогло. Я использую две таблицы в своем приложении - одна из них инициализирована идеально, а другая, которая доставляла мне проблемы все время, - нет.
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

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

.....

Шринатх Ганеш
источник