Foreign key constraints in Android using SQLite? on Delete cascade

JavaAndroidSqliteForeign Keys

Java Problem Overview


I have two tables: tracks and waypoints, a track can have many waypoints, but a waypoint is assigned to only 1 track.

In the way points table I have a column called "trackidfk" which inserts the track_ID once a track is made, however I have not setup Foreign Key constraints on this column.

When I delete a track I want to delete the assigned waypoints, is this possible?. I read about using Triggers but I don't think they are supported in Android.

To create the waypoints table:

public void onCreate(SQLiteDatabase db) {
	db.execSQL( "CREATE TABLE " + TABLE_NAME 
                + " (" 
                + _ID         + " INTEGER PRIMARY KEY AUTOINCREMENT, " 
                + LONGITUDE   + " INTEGER," 
                + LATITUDE    + " INTEGER," 
                + TIME        + " INTEGER,"
                + TRACK_ID_FK + " INTEGER"
                + " );"
              );
	
	...
}

Java Solutions


Solution 1 - Java

Foreign key constraints with on delete cascade are supported, but you need to enable them.
I just added the following to my SQLOpenHelper, which seems to do the trick.

@Override
public void onOpen(SQLiteDatabase db) {
	super.onOpen(db);
	if (!db.isReadOnly()) {
		// Enable foreign key constraints
		db.execSQL("PRAGMA foreign_keys=ON;");
	}
}

I declared my referencing column as follows.

mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE

Solution 2 - Java

Since Android 4.1 (API 16) SQLiteDatabase supports:

public void setForeignKeyConstraintsEnabled (boolean enable)

Solution 3 - Java

As the post from e.shishkin says from API 16 up you should enable foreign key constraints in the SqLiteOpenHelper.onConfigure(SqLiteDatabase) method using the db.setForeignKeyConstraintsEnabled(boolean)

@Override
public void onConfigure(SQLiteDatabase db){
    db.setForeignKeyConstraintsEnabled(true);
}

Solution 4 - Java

Never too old of a question to answer with a more complete answer.

@Override public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        setForeignKeyConstraintsEnabled(db);
    }
    mOpenHelperCallbacks.onOpen(mContext, db);
}

private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        setForeignKeyConstraintsEnabledPreJellyBean(db);
    } else {
        setForeignKeyConstraintsEnabledPostJellyBean(db);
    }
}

private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {
    db.execSQL("PRAGMA foreign_keys=ON;");
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {
    db.setForeignKeyConstraintsEnabled(true);
}

Solution 5 - Java

Whatever @phil mentioned is good. But you can use another default method available in Database itself to set the foreignkey. That is setForeignKeyConstraintsEnabled(true).

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        // Enable foreign key constraints
        db.execSQL("PRAGMA foreign_keys=ON;"); 
              //(OR)
        db.setForeignKeyConstraintsEnabled (true)
    }
}

For Docs refer [SQLiteDatabase.setForeignKeyConstraintsEnabled][1] [1]: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#setForeignKeyConstraintsEnabled(boolean)

Solution 6 - Java

I don't think SQLite supports this out of the box. What I'm doing in my apps is:

  1. Create transaction
  2. Delete detail data (waypoints in your example)
  3. Delete master data (tracks in your example)
  4. Commit transaction on success

That way I'm sure that either all the data is deleted or none.

Solution 7 - Java

Triggers are supported by android and that type of cascade delete is not supported by sqlite. An example of using triggers on android can be found here. Though using transactions as Thorsten stated is probably just as easy as a trigger.

Solution 8 - Java

SQLite version in android 1.6 is 3.5.9 so it doesn't support foreign keys...

http://www.sqlite.org/foreignkeys.html "This document describes the support for SQL foreign key constraints introduced in SQLite version 3.6.19."

In Froyo it's SQLite version 3.6.22, so ...

EDIT: to see sqlite version : adb shell sqlite3 -version

Solution 9 - Java

Foreign keys with "on delete cascade" are supported in SQLite in Android 2.2 and up. But be careful when using them: sometimes an error is reported when firing up one foreign key on one column, but the real problem lies in either another column foreign key constraint in the child table, or some other table thet references this table.

Looks like SQLite checks all constraints when firing up one of them. It is actually mentioned in the documentation. DDL versus DML constraint checks.

Solution 10 - Java

If you are using Android Room, do as shown below.

Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
	.addCallback(object : RoomDatabase.Callback() {
		// Called when the database has been opened.
		override fun onOpen(db: SupportSQLiteDatabase) {
			super.onOpen(db)
			//True to enable foreign key constraints
			db.setForeignKeyConstraintsEnabled(true)
		}

		// Called when the database is created for the first time. 
		override fun onCreate(db: SupportSQLiteDatabase) {
			super.onCreate(db)
		}
	}).build()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjcrowsonView Question on Stackoverflow
Solution 1 - JavaPhilView Answer on Stackoverflow
Solution 2 - Javae.shishkinView Answer on Stackoverflow
Solution 3 - JavamalcolmView Answer on Stackoverflow
Solution 4 - JavaCodeversedView Answer on Stackoverflow
Solution 5 - Javaanand krishView Answer on Stackoverflow
Solution 6 - JavaThorsten DittmarView Answer on Stackoverflow
Solution 7 - JavaDave.BView Answer on Stackoverflow
Solution 8 - JavaGBoueratView Answer on Stackoverflow
Solution 9 - JavaYarView Answer on Stackoverflow
Solution 10 - JavakrishnakumarpView Answer on Stackoverflow