繁体   English   中英

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

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

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

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

关于为什么的任何想法?

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

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

试试这个:

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 中与之对话,则可以执行以下操作:

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

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

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

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

它对我有用!

这就是我所做的:

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

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

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

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

 // @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 的游标。

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

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

喜欢...

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

我面对这个问题并通过 try catch 处理它,就像我在表中做我想做的一样简单,如果它不存在会导致错误,所以通过异常捕获它并创建它:)

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

no such table exists: error即将发生,因为一旦您创建带有一张表的数据库,那么每当您在同一数据库中创建表时,都会出现此错误。

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

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

.....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM