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

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

然而,当表还不存在时,第一个运行在 SQLiteDatabase 对象上的方法是调用 query (...) ,我的 logcat 显示一个错误“ I/Database (26434) : sqlite 返回: error code = 1,msg = no such table: appdata”,果然,appdata 表没有被创建。

知道为什么吗?

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

剪辑
这是在以下两个答案之后贴出的:
我想我找到问题所在了。由于某种原因,我认为应该为每个表创建一个不同的 SQLiteOpenHelper,即使它们都访问同一个数据库文件。我认为重构代码,只使用一个 OpenHelper,并在其 onCreate 中创建两个表可能会更好..。

128892 次浏览

I know nothing about the Android SQLite API, but if you're able to talk to it in SQL directly, you can do this:

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

Which will ensure that the table is always created and not throw any errors if it already existed.

You mentioned that you've created an class that extends SQLiteOpenHelper and implemented the onCreate method. Are you making sure that you're performing all your database acquire calls with that class? You should only be getting SQLiteDatabase objects via the SQLiteOpenHelper#getWritableDatabase and getReadableDatabase otherwise the onCreate method will not be called when necessary. If you are doing that already check and see if th SQLiteOpenHelper#onUpgrade method is being called instead. If so, then the database version number was changed at some point in time but the table was never created properly when that happened.

As an aside, you can force the recreation of the database by making sure all connections to it are closed and calling Context#deleteDatabase and then using the SQLiteOpenHelper to give you a new db object.

Yep, turns out the theory in my edit was right: the problem that was causing the onCreate method not to run, was the fact that SQLiteOpenHelper objects should refer to databases, and not have a separate one for each table. Packing both tables into one SQLiteOpenHelper solved the problem.

no such table exists: error is coming because once you create database with one table after that whenever you create table in same database it gives this error.

To solve this error you must have to create new database and inside the onCreate() method you can create multiple table in same database.

This is what I did:

/* 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 this one:

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;
}
}

Although there are already a lot of good answers to this question, I came up with another solution that I think is more simple. Surround your query with a try block and the following 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.
}
}

It worked for me!

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

.....

 // @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 maintains sqlite_master table containing information of all tables and indexes in database.
  • So here we are simply running SELECT command on it, we'll get cursor having count 1 if table exists.
 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;
}

Important condition is IF NOT EXISTS to check table is already exist or not in database

like...

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

i faced that and deal with it by try catch as simple as that i do what i want in table if it not exist will cause error so catch it by exceptions and create it :)

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");
}


Kotlin solution, based on what others wrote here:

    fun isTableExists(database: SQLiteDatabase, tableName: String): Boolean {
database.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '$tableName'", null)?.use {
return it.count > 0
} ?: return false
}