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

How does one check if a table exists in an Android SQLite database?

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

但是,当表尚不存在,并且第一个方法运行SQLiteDatabase对象时,我有一个调用查询(...),我的logcat显示错误"我/数据库(26434):sqlite返回:错误code = 1,msg =没有这样的表:appdata",果然,appdata表没有被创建。

有什么想法吗?

我正在寻找一种方法来测试表是否存在(因为如果不存在,数据肯定不在其中,我不需要读它,直到我写它,这似乎创建表正确的),或者确保它被创建的方法,并且只是空的,及时进行第一次查询调用(...)

编辑


这是在以下两个答案之后发布的:


我想我可能已经发现了这个问题。我出于某种原因决定为每个表创建一个不同的SQLiteOpenHelper,即使它们都访问相同的数据库文件。我认为重构该代码只使用一个OpenHelper,并在其中创建两个表onCreate可能会更好...


试试这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
    }
}


我对Android SQLite API一无所知,但如果你能直接在SQL中与它交谈,你可以这样做:

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

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


这就是我做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 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;

虽然这个问题已经有很多好的答案,但我想出了另一个我认为更简单的解决方案。使用try块和以下catch来查询查询:

1
2
3
4
5
6
7
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.
    }
}

它对我有用!


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
 // @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的游标。


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

另外,您可以通过确保关闭数据库的所有连接并调用Context#deleteDatabase然后使用SQLiteOpenHelper为您提供新的数据库对象来强制重新创建数据库。


重要条件是IF NOT EXISTS检查表是否已存在于数据库中

喜欢...

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

1
2
3
4
5
6
7
8
9
10
11
 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;
}

no such table exists: error即将推出,因为一旦您在同一数据库中创建表时创建具有一个表的数据库,就会出现此错误。

要解决此错误,您必须创建新数据库,并且在onCreate()方法中,您可以在同一数据库中创建多个表。


.....
Toast t = Toast.makeText(context,"try ...",Toast.LENGTH_SHORT);
t.show();

1
2
3
4
5
6
7
8
9
    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

.....