在Android应用程序数据库中检查列是否存在

28

在Android中,有没有一种简单的方法可以查看应用程序数据库中的表中是否存在某个列?(我知道已经有类似于这个问题的问题了,但好像没有任何一个是特定于Android的。)

7个回答

50

cursor.getColumnIndex(String columnName)如果该列不存在,则返回-1。因此,我基本上会执行一个简单的查询,例如"SELECT * FROM xxx LIMIT 0,1" ,并使用游标确定您要查找的列是否存在。

或者,您可以尝试查询列"SELECT theCol FROM xxx"并捕获异常。


这正是我所想的,但我收到了一个SQLiteException,说“没有这样的列:test”。我正在检查该列是否在表中,如果不存在,则插入它。 - Lunchbox
你是在查询期间还是在getColumnIndex期间遇到了异常?如果是在查询期间:你确定没有在查询中指定要测试的列(不要使用“SELECT col FROM...”,而应该改为执行“SELECT * FROM..”)吗?否则会抛出你提到的错误,你必须捕获它。 - martinpelant
2
尝试使用SQLiteDatabase.rawQuery("SELECT * FROM table LIMIT 0,1", null);而不是使用构建器。 - martinpelant
如果表中没有行,该怎么办? - user2520215
使用第二种方法。 - user2154462
显示剩余2条评论

38

根据 @martinpelants 的回答,我的函数如下:

private boolean existsColumnInTable(SQLiteDatabase inDatabase, String inTable, String columnToCheck) {
    Cursor mCursor = null;
    try {
        // Query 1 row 
        mCursor = inDatabase.rawQuery("SELECT * FROM " + inTable + " LIMIT 0", null);

        // getColumnIndex() gives us the index (0 to ...) of the column - otherwise we get a -1
        if (mCursor.getColumnIndex(columnToCheck) != -1)
            return true;
        else
            return false;

    } catch (Exception Exp) {
        // Something went wrong. Missing the database? The table?
        Log.d("... - existsColumnInTable", "When checking whether a column exists in the table, an error occurred: " + Exp.getMessage());
        return false;
    } finally {
        if (mCursor != null) mCursor.close();
    }
}

只需拨打电话:

boolean bla = existsColumnInTable(myDB,"MyTable","myColumn2check");

6
你应该在 finally 块中关闭游标! - WonderCsabo

5
我实际上编写了这个函数,看起来相当简洁:
private boolean field_exists( String p_query )
{
    Cursor mCursor  = mDb.rawQuery( p_query, null );

    if  (  ( mCursor != null ) && ( mCursor.moveToFirst()) )
    {
        mCursor.close();
        return true ;
    }

    mCursor.close();
    return false ;
}

我这样称呼它:

if  ( field_exists( "select * from sqlite_master "              
    + "where name = 'mytable' and sql like '%myfield%' " ))
{
    do_something ;
}

4

这是我对问题的解决方案,它在flexo的解决方案基础上进行了一些补充。

你可以将此方法放置在任何类中,例如扩展SQLiteOpenHelper的类中。

public static boolean columnExistsInTable(SQLiteDatabase db, String table, String columnToCheck) {
    Cursor cursor = null;
    try {
        //query a row. don't acquire db lock
        cursor = db.rawQuery("SELECT * FROM " + table + " LIMIT 0", null);

        // getColumnIndex()  will return the index of the column 
        //in the table if it exists, otherwise it will return -1
        if (cursor.getColumnIndex(columnToCheck) != -1) {
            //great, the column exists
            return true;
        }else {
            //sorry, the column does not exist
            return false;
        }

    } catch (SQLiteException Exp) {
        //Something went wrong with SQLite. 
        //If the table exists and your query was good,
        //the problem is likely that the column doesn't exist in the table.
        return false;
    } finally {
        //close the db  if you no longer need it
        if (db != null) db.close();
        //close the cursor 
        if (cursor != null) cursor.close();
    }
}

1
这看起来更加清晰,但我不确定关闭数据库总是一个好主意。 - ban-geoengineering
1
是的,@ban-geoengineering,我不确定这一点,这就是为什么我说只有在你不再需要它时才关闭它。 - lwdthe1
光标在任何返回时都成功关闭(对于那些像我一样有疑虑的人) - djdance

2
如果您使用ActiveAndroid:
public static boolean createIfNeedColumn(Class<? extends Model> type, String column) {
        boolean isFound = false;
        TableInfo tableInfo = new TableInfo(type);

        Collection<Field> columns = tableInfo.getFields();
        for (Field f : columns) {
            if (column.equals(f.getName())) {
                isFound = true;
                break;
            }
        }
        if (!isFound) {
            ActiveAndroid.execSQL("ALTER TABLE " + tableInfo.getTableName() + " ADD COLUMN " + column + " TEXT;");
        }
        return isFound;
    }

它检查模型中是否存在某列,但在设备上的数据库中不存在。 - undefined

1

有可能只是发表了相同但更短的解决方案。这是基于@flexo的版本进行简化的。

  private boolean doesColumnExistInTable(SupportSQLiteDatabase db, String tableName, String columnToCheck) {
        try (Cursor cursor = db.query("SELECT * FROM " + tableName + " LIMIT 0", null)) {
            return cursor.getColumnIndex(columnToCheck) != -1;
        } catch (Exception Exp) {
            // Something went wrong. we'll assume false it doesn't exist
            return false;
        }
    }

而在 Kotlin 中

  private fun doesColumnExistInTable(db: SupportSQLiteDatabase, tableName: String, columnToCheck: String): Boolean {
        try {
            db.query("SELECT * FROM $tableName LIMIT 0", null).use { cursor -> return cursor.getColumnIndex(columnToCheck) != -1 }
        } catch (e: Exception) {
            // Something went wrong. we'll assume false it doesn't exist
            return false
        }
    }

columnToCheck 是什么? - Abdullah Jacksi
@AbdullahZakhoi columnToCheck 是我想要检查其是否存在于表格中的列的字符串名称。 - scottyab

0

这是我的测试代码:

String neadle = "id"; //searched field name
String tableName = "TableName";
boolean found = false;

SQLiteDatabase mDb = ActiveAndroid.getDatabase();
Cursor mCursor  = mDb.rawQuery( "SELECT * FROM sqlite_master WHERE name = '"+tableName+"' and sql like '%"+neadle+"%'" , null);
mCursor.moveToFirst();
String fie = ",";

if (mCursor.getCount() > 0) {
    String[] fields = mCursor.getString(mCursor.getColumnIndex("sql")).split(",");
    for (String field: fields) {
        String[] fieldNameType = field.trim().split(" ");
        if (fieldNameType.length > 0){
            fie += fieldNameType[0]+",";
        }
    }
}else {
    //table not exist!
}
if (mCursor != null) mCursor.close();
// return result: 
found = fie.contains(","+neadle+",");

对于ActiveAndroid,您可以使用以下代码从类中获取表名称: - Tom
Cache.getTableInfo(type).getTableName() - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接