如何检查 Android SQLite 数据库中是不是存在表?
Posted
技术标签:
【中文标题】如何检查 Android SQLite 数据库中是不是存在表?【英文标题】:How does one check if a table exists in an Android SQLite database?如何检查 Android SQLite 数据库中是否存在表? 【发布时间】:2011-03-04 18:54:04 【问题描述】:我有一个 android 应用程序需要检查数据库中是否已经有记录,如果没有,则处理一些内容并最终插入它,如果数据确实存在,则只需从数据库中读取数据。我正在使用 SQLiteOpenHelper 的子类来创建和获取 SQLiteDatabase 的可重写实例,我认为如果表不存在,它会自动处理创建表(因为执行此操作的代码在 onCreate(... ) 方法)。
但是,当表尚不存在,并且在我拥有的 SQLiteDatabase 对象上运行的第一个方法是调用 query(...) 时,我的 logcat 显示错误“I/Database(26434): sqlite返回:错误代码= 1,msg =没有这样的表:appdata“,并果然,不创建appdata表。
关于为什么的任何想法?
我正在寻找一种方法来测试表是否存在(因为如果不存在,则数据肯定不在其中,并且在写入之前我不需要读取它,这似乎正确创建表格),或者以确保它创建的方式,并且只是空的,并及时呼叫查询(...)
编辑 这是在以下两个答案之后发布的: 我想我可能找到了问题所在。我出于某种原因决定应该为每个表创建一个不同的 SQLiteOpenHelper,即使它们都访问同一个数据库文件。我认为重构该代码只能使用一个OpenHelper,并在它的oncreate内创建两个表可以更好地工作...
【问题讨论】:
【参考方案1】:试试这个:
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 别忘了cursor.close();
由于未知原因,表名区分大小写。我宁愿使用select * from sqlite_master where UPPER(name) = 'ROUTES'.
很好的答案,但语法很痛苦!肯定应该被称为“isTableExisting()”。
这对我有用,但我必须将查询包装在 try/catch 中,否则当表不存在时我的应用程序会崩溃。【参考方案2】:
我对 Android SQLite API 一无所知,但如果你能够直接用 SQL 与它对话,你可以这样做:
create table if not exists mytable (col1 type, col2 type);
这将确保始终创建表并且不会抛出任何错误(如果它已经存在)。
【讨论】:
这就是我在 SQLiteOpenHelper 类的 onCreate 方法中创建表的方式。在 android 中,建议让该类创建表,因为它允许应用程序自动更新其数据库,并且通常显然更有效。不幸的是,执行代码与您编写的代码非常相似的代码块没有及时运行:( 这很好用,也适用于索引,即:“如果不存在则创建索引 [...]”。 这实际上是所提问题的最佳答案。 但问题并没有要求创建一个【参考方案3】:虽然这个问题已经有了很多很好的答案,但我想出了另一个我认为更简单的解决方案。用 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.
它对我有用!
【讨论】:
将 Log 语句放在 if() 块中不是更好吗?看起来如果 SQLiteException 是由于“没有这样的表”之外的其他原因引发的,日志将表明您正在创建该表,而实际上您并没有。 使用异常来控制流程是一件可耻的事情,而不是教给别人的。以这种方式检查消息,更是如此。 如果谨慎使用,我认为在上述用例中使用异常没有任何问题。当然没有什么让我感到羞耻的。 我认为e.getMessage().contains("no such table")
比使用异常控制流更糟糕。两者都是糟糕的风格,但为特定文本解析错误消息甚至是非常糟糕的风格。【参考方案4】:
这就是我所做的:
/* 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;
【讨论】:
【参考方案5】:是的,事实证明我编辑的理论是正确的:导致 onCreate 方法无法运行的问题是 SQLiteOpenHelper
对象应该引用数据库,而不是每个表都有一个单独的对象。将两张表打包成一张SQLiteOpenHelper
解决了这个问题。
【讨论】:
【参考方案6】:您提到您创建了一个扩展SQLiteOpenHelper
的类并实现了onCreate
方法。您是否确保使用该类执行所有数据库获取调用?您应该只通过SQLiteOpenHelper#getWritableDatabase
和getReadableDatabase
获取SQLiteDatabase
对象,否则在必要时不会调用onCreate
方法。如果您正在这样做,请检查并查看是否正在调用 SQLiteOpenHelper#onUpgrade
方法。如果是这样,那么数据库版本号在某个时间点发生了更改,但发生这种情况时该表从未正确创建。
顺便说一句,您可以通过确保与数据库的所有连接都已关闭并调用Context#deleteDatabase
然后使用SQLiteOpenHelper
为您提供一个新的数据库对象来强制重新创建数据库。
【讨论】:
好吧,我正在通过 getWritableDatabase() 调用获取我的数据库对象,抱歉我忘了指定。另外,我确定没有调用 onUpgrade(),因为该方法有一个 Log.d(...) 调用作为我在数据库中没有看到的第一行。我会尝试删除整个数据库文件,我们会看看是否能以某种方式修复它... 不幸的是,删除整个数据库(我使用根资源管理器清除文件)不起作用。我在我的应用程序中使用了两个表 - 其中一个已完美初始化,但另一个一直给我带来麻烦的却没有。【参考方案7】: // @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 的游标。
【讨论】:
【参考方案8】:Kotlin 解决方案,基于其他人在这里写的:
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
【讨论】:
【参考方案9】: 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;
【讨论】:
【参考方案10】:no such table exists: error
即将到来,因为一旦您创建了一个包含一个表的数据库,之后每当您在同一个数据库中创建表时都会出现此错误。
要解决此错误,您必须创建新数据库,并且在 onCreate() 方法中,您可以在同一个数据库中创建多个表。
【讨论】:
【参考方案11】:重要的条件是IF NOT EXISTS检查表是否已经存在或不在数据库中
喜欢...
String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "("
+ KEY_PLAYER_ID + " TEXT,"
+ KEY_PLAYER_IMAGE + " TEXT)";
db.execSQL(query);
【讨论】:
【参考方案12】:我遇到了这个问题并通过尝试捕获来处理它,就像我在表中做我想要的那样,如果它不存在会导致错误,所以通过异常捕获它并创建它:)
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");
【讨论】:
【参考方案13】:..... 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
.....
【讨论】:
以上是关于如何检查 Android SQLite 数据库中是不是存在表?的主要内容,如果未能解决你的问题,请参考以下文章
带有 Sqlite 的 Android - 如何检查表是不是存在以及是不是为空