如何检查Android SQLite数据库中是否存在表?


87

我有一个Android应用程序,需要检查数据库中是否已经有记录,如果没有,则处理一些事情并最终将其插入,如果数据确实存在,则只需从数据库中读取数据即可。我正在使用SQLiteOpenHelper的子类来创建和获取SQLiteDatabase的可重写实例,我认为如果表不存在,该表将自动负责创建表(因为执行此操作的代码位于onCreate(... ) 方法)。

但是,当该表尚不存在,并且第一个方法对我拥有的SQLiteDatabase对象执行了对query(...)的调用时,我的logcat显示错误“ I / Database(26434):sqlite返回:error code = 1,msg =否这样的表:“ appdata”,当然,没有创建appdata表。

有什么想法吗?

我正在寻找一种方法来测试表是否存在(因为如果不存在,则数据肯定不在其中,并且在写入表之前似乎不需要读取它,这似乎可以创建表)正确),或一种确保它已被创建并且只是空的方法,以便在第一次调用query(...)时及时进行

编辑
这是在以下两个答案之后发布的:
我想我可能已经发现了问题。我出于某种原因决定应该为每个表创建一个不同的SQLiteOpenHelper,即使它们都访问相同的数据库文件。我认为将代码重构为仅使用一个OpenHelper,并在其onCreate中创建两个表可能会更好。

Answers:


126

试试这个:

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
这对我有用,但是我不得不将查询包装在try / catch中,否则当表不存在时我的应用程序将崩溃。
布雷登·霍尔特

52

我对Android SQLite API一无所知,但是如果您能够直接在SQL中与之对话,则可以执行以下操作:

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

这将确保始终创建表,并且如果表已经存在则不会引发任何错误。


这就是我在SQLiteOpenHelper类内的onCreate方法中创建表的方式。在android中,建议让该类创建表,因为它允许该应用自动更新其数据库,并且通常来说效率更高。不幸的是,执行代码的代码块与您编写的代码块非常相似,没有及时运行:(
camperdave 2010年

这很好用,也可以与索引一起使用,即:“如果不存在则创建索引”。
埃里克·佛捷

5
这实际上是所提问题的最佳答案。
2016年

1
但问题并没有要求创建一个
-10101010

12

尽管这个问题已经有了很多好的答案,但是我想出了另一个我认为更简单的解决方案。用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是由于“没有这样的表”以外的其他原因引发的,则日志将指示您正在创建表,而实际上却不是。

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;

8

是的,事实证明我的编辑中的理论是正确的:导致onCreate方法无法运行的问题是SQLiteOpenHelper对象应该引用数据库,并且每个表都没有单独的对象。将两个表打包到一个表就SQLiteOpenHelper解决了这个问题。


2

您提到您已经创建了一个扩展SQLiteOpenHelper并实现该onCreate方法的类。您是否确定正在执行所有该类的数据库获取调用?您只应通过获取SQLiteDatabase对象SQLiteOpenHelper#getWritableDatabasegetReadableDatabase否则onCreate在必要时将不会调用该方法。如果您正在执行此操作,请检查并查看是否SQLiteOpenHelper#onUpgrade正在调用方法。如果是这样,则数据库版本号在某个时间点已更改,但是在这种情况下永远不会正确创建表。

顺便说一句,您可以通过确保关闭与数据库的所有连接并进行调用Context#deleteDatabase,然后使用SQLiteOpenHelper来为您提供一个新的db对象,来强制重新创建数据库。


好吧,我正在通过getWritableDatabase()调用来获取数据库对象,对不起,我忘记指定了。另外,我确定没有调用onUpgrade(),因为该方法的第一行有Log.d(...)调用,而我在数据库中看不到它。我将尝试删除整个数据库文件,我们将看看是否可以通过某种方式修复它...
camperdave 2010年

不幸的是,删除整个数据库(我使用root资源管理器清除文件)无效。我在应用程序中使用了两个表-其中一个表已完美初始化,但是一直给我带来麻烦的另一个表却没有。
camperdave 2010年

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(context,“ 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

.....

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.