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

69

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

Однако, когда таблица еще не существует, а первый метод запускается на объекте SQLiteDatabase, у меня есть вызов запроса (...), в моем логарифме отображается ошибка "I/Database (26434): sqlite return: код ошибки = 1, msg = no такая таблица: appdata", и, конечно же, таблица appdata не создается.

Любые идеи о том, почему?

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

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

Теги:
database

10 ответов

7
Лучший ответ

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

  • 0
    Ницца! Спасибо, что сработало для меня
101

Попробуйте следующее:

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

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

    Cursor cursor = mDatabase.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;
}
  • 0
    Большое спасибо за это. Работает отлично. +1
  • 1
    Большая помощь! Благодарю.
Показать ещё 11 комментариев
42

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

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

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

  • 0
    Вот как я создаю таблицу в методе onCreate внутри класса SQLiteOpenHelper. В Android рекомендуется, чтобы этот класс создавал таблицу, поскольку он позволяет приложению автоматически обновлять свою базу данных, и в целом он, очевидно, более эффективен. К сожалению, тот кодовый блок, который выполняет код, очень похожий на тот, который вы написали, не запускается вовремя :(
  • 0
    Это прекрасно работает, а также работает с индексами, а именно: «создайте индекс, если не существует [...]».
Показать ещё 2 комментария
10

Хотя на этот вопрос уже есть много хороших ответов, я придумал другое решение, которое, я думаю, более простое. Объедините свой запрос с помощью блока try и следующего catch:

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 вызывается по другой причине, чем «нет такой таблицы», в журнале будет указано, что вы создаете таблицу, а на самом деле это не так.
  • 0
    Ты абсолютно прав ... Хороший улов!
Показать ещё 2 комментария
9

Это то, что я сделал:

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

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

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

  • 0
    Ну, я получаю объект базы данных через вызов getWritableDatabase (), извините, я забыл это указать. Кроме того, я уверен, что onUpgrade () не вызывается, так как этот метод имеет вызов Log.d (...) в качестве первой строки, которую я не вижу в базе данных. Я попытаюсь удалить весь файл базы данных, и мы увидим, если это как-то исправит это ...
  • 0
    К сожалению, удаление всей базы данных (я использовал root explorer для очистки файла) не сработало. Я использую две таблицы в своем приложении - одна из них отлично инициализирована, а другая, которая доставляла мне неприятности, - нет.
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
 // @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, если таблица существует.
  • 1
    Подумайте над объяснением вашего кода
0

..... Toast t = Toast.makeText(контекст, "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

.....

0

no such table exists: error происходит потому, что после создания базы данных с одной таблицей после этого всякий раз, когда вы создаете таблицу в той же базе данных, она дает эту ошибку.

Чтобы решить эту ошибку, вам необходимо создать новую базу данных и внутри метода onCreate() вы можете создать несколько таблиц в одной базе данных.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню