272

How can I delete all entries on specific table using Room Persistence Library? I need to drop table, but I cannot to find any information how to do this.

Only when database is migrating or to load all entries and delete them :)

Sirelon
  • 6,446
  • 5
  • 26
  • 30
  • 21
    As of Room 1.1.0 you can use `clearAllTables()` which "deletes all rows from all the tables that are registered to this database as entities()." I've included this as an answer below, but am reproducing here for visibility. – Dick Lucas Apr 12 '18 at 15:42
  • 3
    Because multiple people seem to be suggesting `clearAllTables()`, I can't help but point out that OP quite clearly says "How can I delete all entries on specific table". – Chucky Mar 28 '22 at 15:52

9 Answers9

615

You can create a DAO method to do this.

@Dao 
interface MyDao {
    @Query("DELETE FROM myTableName")
    public void nukeTable();
}
yigit
  • 37,683
  • 13
  • 72
  • 58
  • 4
    Ah, I hadn't thought of that. I assumed that `@Query` was limited to things that return result sets (akin to `rawQuery()`). Very cool! – CommonsWare May 29 '17 at 20:08
  • 1
    @yigit can I request that `@Delete` takes no parameter and delete all from the table? I'm trying to find Room's tracker to file that ... – Felipe Duarte Jun 05 '17 at 21:44
  • it looks very misleading so no. + @Delete does not have a table annotation so we would not even know which table to clear. – yigit Jun 09 '17 at 02:49
  • 4
    Watch out! as for room alpha4 version, this technique will lead to a gradle build fail: https://issuetracker.google.com/issues/63608092 – yshahak Jul 13 '17 at 05:45
  • 2
    How about `Ids`? I did like this but Table Ids continue to increment. In real table drop Ids are also dropped to start from 0 again. – Ioane Sharvadze Jul 18 '17 at 08:18
  • 8
    @yigit Is there a way to find out if the query ran successfully or if there was an error? – Aditya Ladwa Sep 19 '17 at 06:27
  • Couldn't thought of this at all. – hqzxzwb Nov 09 '17 at 15:07
  • Deletion methods must either return void or return int (the number of deleted rows). @IoaneSharvadze – jknair0 Feb 15 '18 at 09:39
  • 1
    After clearAllTables(), how to create back all tables ?? Like in greenDao supports DAOMaster.dropAllTables() and Daomaster.createAllTables(). Something similar to this is supported in RoomDB ?? – K Pradeep Kumar Reddy Jun 16 '20 at 08:19
  • I get a "Cannot access database on the main thread since it may potentially lock the UI for a long period of time." Is suspend require for this function? – Chucky Mar 28 '22 at 15:54
145

As of Room 1.1.0 you can use clearAllTables() which:

Deletes all rows from all the tables that are registered to this database as entities().

Parag Pawar
  • 827
  • 3
  • 12
  • 23
Dick Lucas
  • 12,289
  • 14
  • 49
  • 76
  • 66
    Be careful: clearAllTables() is asynchronous and there is no way to tell when it completes. – Alexey Jul 10 '18 at 15:14
  • 2
    @Alexey but could there be any trouble trying to save something after clearAllTables? As in, will it only attempt to insert AFTER clearing? Because I'm fine with that. – FirstOne Aug 31 '18 at 14:27
  • 3
    @FirstOne clearAllTables basically just starts a transaction on a new background thread. It deletes all data from tables and then commits that transaction. If you start your transaction later than clearAllTables starts its, youre fine. That being said, If you try to insert some data right after calling clearAllTable your insert might start before clearAllTable starts transaction and you'll loose all your data. If you need to insert new data right after calling clearAllTable, at least add some delay. – Alexey Aug 31 '18 at 15:39
  • 2
    @Alexey Is there any way to use a callback method or similar to determine the state of the delete transaction? In other words, if the delete transaction state is complete, then proceed with the insert data method. – AJW Feb 26 '19 at 19:14
  • 1
    @AJW No, as of now, there is still no way to tell when the operation is complete. If you really need this functionality, you might want to try something like `SELECT name FROM sqlite_master WHERE type='table'` and then manually `DELETE FROM {TABLE}`. Haven't tested this though. – Alexey Feb 27 '19 at 08:10
  • if you want to make sure you're waiting the appropriate amount of time, the best would be to set up a semaphore lock on your database object that is only released when an asynchronous process on a timer can confirm all tables are empty and decrements the semaphore. But to do this, all of your room operations have to respect the lock, which may not be trivial depending on your app's size. – Kirk Jul 28 '19 at 14:34
  • After clearAllTables(), how to create back all tables ?? Like in greenDao supports DAOMaster.dropAllTables() and Daomaster.createAllTables(). Something similar to this is supported in RoomDB ?? – K Pradeep Kumar Reddy Jun 16 '20 at 08:15
  • Actually my use case is to support multiple users login to my app. When the user tries to change login number, i clear the old data and allow the user to login with new number. To achieve this, i need dropAllTables() and createAllTables in RoomDB. – K Pradeep Kumar Reddy Jun 16 '20 at 08:17
  • 2
    `clearAllTables()` does NOT operates asynchronously, while it forces you to not call it from main thread. – Demigod Jul 24 '20 at 09:32
  • It's throwing java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. – Kuvonchbek Yakubov Nov 24 '20 at 09:11
  • 1
    @Dick, it's not the answer about deleting all rows from specific table. – Gary Chen Dec 08 '20 at 08:40
43

If want to delete an entry from the the table in Room simply call this function,

@Dao
public interface myDao{
    @Delete
    void delete(MyModel model);
}

Update: And if you want to delete complete table, call below function,

  @Query("DELETE FROM MyModel")
  void delete();

Note: Here MyModel is a Table Name.

Aman Gupta - ΔMΔN
  • 2,971
  • 2
  • 19
  • 39
  • i got this error after use your update code error: An abstract DAO method must be annotated with one and only one of the following annotations: Insert,Delete,Query,Update,RawQuery void delete(); – bramastaVic Nov 16 '19 at 07:30
15

Use clearAllTables() with RXJava like below inorder to avoid java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

Completable.fromAction(new Action() {
        @Override
        public void run() throws Exception {
            getRoomDatabase().clearAllTables();
        }
    }).subscribeOn(getSchedulerProvider().io())
            .observeOn(getSchedulerProvider().ui())
            .subscribe(new Action() {
                @Override
                public void run() throws Exception {
                    Log.d(TAG, "--- clearAllTables(): run() ---");
                    getInteractor().setUserAsLoggedOut();
                    getMvpView().openLoginActivity();
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.d(TAG, "--- clearAllTables(): accept(Throwable throwable) ----");
                    Log.d(TAG, "throwable.getMessage(): "+throwable.getMessage());


                }
            });
Adewale Balogun
  • 677
  • 7
  • 12
9

I had issues with delete all method when using RxJava to execute this task on background. This is how I finally solved it:

@Dao
interface UserDao {
    @Query("DELETE FROM User")
    fun deleteAll()
}

and

fun deleteAllUsers() {
    return Maybe.fromAction(userDao::deleteAll)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe ({
            d("database rows cleared: $it")
        }, {
            e(it)
        }).addTo(compositeDisposable)
}
Micer
  • 8,731
  • 3
  • 79
  • 73
  • 6
    When you are using Kotlin, you can just wrap it in `thread {}` instead of futzing with RxJava – Erik Dec 20 '18 at 20:01
8

This is how we do it from a Fragment.

fun Fragment.emptyDatabase() {
    viewLifecycleOwner.lifecycleScope.launchWhenCreated {
        withContext(Dispatchers.IO) {
            Database.getInstance(requireActivity()).clearAllTables()
        }
    }
}

If you are emptying the database from an activity use this:

fun Activity.emptyDatabase() {
    // create a scope to access the database from a thread other than the main thread
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
        SitukaDatabase.getInstance(this@emptyDatabase).clearAllTables()
    }
}

It could also be possible to call the clearAllTables method from the main thread. I haven't tried it out but I noticed that Android Studio does not recognize the call as a suspend function.

Gilbert
  • 2,699
  • 28
  • 29
3

Combining what Dick Lucas says and adding a reset autoincremental from other StackOverFlow posts, i think this can work:

fun clearAndResetAllTables(): Boolean {
    val db = db ?: return false

    // reset all auto-incrementalValues
    val query = SimpleSQLiteQuery("DELETE FROM sqlite_sequence")

    db.beginTransaction()
    return try {
        db.clearAllTables()
        db.query(query)
        db.setTransactionSuccessful()
        true
    } catch (e: Exception){
        false
    } finally {
        db.endTransaction()
    }
}
Gary Chen
  • 248
  • 2
  • 14
Hamlet Leon
  • 427
  • 3
  • 9
  • For what it’s worth, I’ve found it easiest to do this via context.deleteDatabase(“name”) and then simply reinstantiating and repopulating the database via the Room.databaseBuilder().addCallback upon first access. – Bink Oct 22 '18 at 22:40
  • What is sqlite_sequence? – RoyalGriffin Apr 15 '20 at 12:51
2

Here is how I have done it in Kotlin.

  1. Inject room db in the activity using DI (Koin).

     private val appDB: AppDB by inject()
    
  2. Then you can simply call clearAllTables()

private fun clearRoomDB() {
    GlobalScope.launch {
        appDB.clearAllTables()
        preferences.put(PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false)
        preferences.put(PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO_DB, false)
    }
}
Boken
  • 4,825
  • 10
  • 32
  • 42
VIVEK CHOUDHARY
  • 468
  • 5
  • 8
1

To make use of the Room without abuse of the @Query annotation first use @Query to select all rows and put them in a list, for example:

@Query("SELECT * FROM your_class_table")

List`<`your_class`>` load_all_your_class();

Put his list into the delete annotation, for example:

@Delete

void deleteAllOfYourTable(List`<`your_class`>` your_class_list);
Thelouras
  • 852
  • 1
  • 10
  • 30