28

Is there a nice way in Android to see if a column exists in a table in the application database? (I know there are questions similar to this one already, but there don't seem to be any that are Android specific.)

Lunchbox
  • 2,136
  • 7
  • 29
  • 40

7 Answers7

50

cursor.getColumnIndex(String columnName) returns -1 if, the column doesn't exist. So I would basically perform a simple query like "SELECT * FROM xxx LIMIT 0,1" and use the cursor to determine if the column, you are looking for, exists

OR

you can try to query the column "SELECT theCol FROM xxx" and catch an exception

martinpelant
  • 2,961
  • 1
  • 30
  • 39
  • That's what I thought, but I am getting an SQLiteException saying "no such column: test". I'm checking to see if the column is in the table and if not, then inserting it. – Lunchbox Jan 18 '11 at 01:55
  • are you getting the exception during the query or during the getColumnIndex? If durig the query: are you sure you don't specify the column you test in the query (don't do "SELECT col FROM..." but perform "SELECT * FROM.." instead)? otherwise it throws the error you are mentioning and you must catch it. – martinpelant Jan 18 '11 at 02:01
  • It happens during the query. I'm using SQLiteQueryBuilder to build the query and supply it with a projection map that spans the columns in the table. – Lunchbox Jan 18 '11 at 02:04
  • 2
    Try SQLiteDatabase.rawQuery("SELECT * FROM table LIMIT 0,1", null); instead of using the builder – martinpelant Jan 18 '11 at 02:09
  • I suppose I should have mentioned that I had a WHERE clause in that query as well. I removed that clause and got a successful query. And your solution works! Thank you. – Lunchbox Jan 18 '11 at 02:32
  • What if there are no rows in the table? – user2520215 Aug 18 '15 at 12:18
  • Use the second method then –  Aug 24 '15 at 11:38
38

My function based on @martinpelants answer:

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

Simply call:

boolean bla = existsColumnInTable(myDB,"MyTable","myColumn2check");
Sdghasemi
  • 5,370
  • 1
  • 34
  • 42
flexo
  • 1,120
  • 1
  • 9
  • 14
5

I actually wrote this function that seems pretty clean:

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

I call it like this:

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

Here is my solution to the issue which adds to flexo's solution a little.

You can put this method in any class, perhaps your SQLiteOpenHelper extending class.

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();
    }
}
lwdthe1
  • 1,001
  • 1
  • 16
  • 16
2

If you use 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;
    }
kutukoff
  • 43
  • 6
1

At the risk of just posting the same solution but shorter. Here's a cut down version based on @flexo's

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

And in 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
        }
    }
scottyab
  • 23,621
  • 16
  • 94
  • 105
0

this is my testing code:

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+",");
Tom
  • 1
  • 1