У меня есть три таблицы: log
, activity
и объединяемая таблица (many2many) log_activity
(с log_id
и activity_id
+ дополнительные данные в виде столбцов).
Я хочу удалить из log
и log_activity
.
Я хочу сохранить все журналы от определенного пользователя и сохранить только 100 строк от других пользователей.
Это означает, что я хочу удалить все строки, которые соответствуют WHERE log.user_id != 1
, но последние 100 (ORDER BY log.timestamp DESC
).
Я также хочу удалить из объединяемой таблицы log_activity
все записи, относящиеся к журналам, которые удаляются. Стол activity
должен не быть затронутым.
Я думаю, что db.delete(TABLE_NAME, whereClause , whereArgs);
не поможет в этом случае ..
Так может ли кто-нибудь придумать эффективное решение?
ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ
Вдохновленный ответами Джейкоба Эггерса и плафона, и дальнейшими исследованиями я сейчас пытаюсь вот так, но пока это не работает:
CREATE TABLE IF NOT EXISTS log (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
timestamp LONG NOT NULL
);
CREATE TABLE IF NOT EXISTS log_activity (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
log_id INTEGER NOT NULL,
activity_id INTEGER NOT NULL,
points INTEGER NOT NULL,
FOREIGN KEY(log_id) REFERENCES log(_id) ON DELETE CASCADE,
FOREIGN KEY(activity_id) REFERENCES activity(_id) ON DELETE CASCADE
);
Теперь для android части:
SQLiteDatabase db = openHelper.getWritableDatabase();
db.execSQL("PRAGMA foreign_keys = ON;");
db.execSQL(CREATE_LOG); // see sql above
db.execSQL(CREATE_ACTIVITY); // not shown here, but like the sql-creates above
db.execSQL(CREATE_LOG_ACTIVITY); // see sql above
// ... insert some data ...
INSERT INTO "log" VALUES(1,1,1307797289000);
INSERT INTO "log" VALUES(2,1,1307710289000);
INSERT INTO "log" VALUES(3,2,1308089465000);
INSERT INTO "log" VALUES(4,2,1308079465000);
INSERT INTO "log_activity" VALUES(1,1,1,1);
INSERT INTO "log_activity" VALUES(2,1,2,2);
INSERT INTO "log_activity" VALUES(3,2,1,1);
INSERT INTO "log_activity" VALUES(4,2,2,2);
INSERT INTO "log_activity" VALUES(5,3,1,1);
INSERT INTO "log_activity" VALUES(6,3,2,2);
INSERT INTO "log_activity" VALUES(7,4,1,1);
INSERT INTO "log_activity" VALUES(8,4,2,2);
// check count of logs
Cursor c = db.query(false, "log", null, null, null, null, null, "_id asc", null);
android.util.Log.d("TEST", "log count before: "+c.getCount());
// check count of log_activities
Cursor c2 = db.query(false, "log_activity", null, null, null, null, null, "_id asc", null);
android.util.Log.d("TEST", "la count before: "+c2.getCount());
// delete some log-rows
long userId = 1;
int keepXLogsOfOthers = 1;
String del = "DELETE FROM log" +
" WHERE user_id != " + userId +
" AND log._id NOT IN (" +
" SELECT _id" +
" FROM (" +
" SELECT _id" +
" FROM log" +
" WHERE user_id != " + userId +
" ORDER BY timestamp DESC" +
" LIMIT " + keepXLogsOfOthers +
" ) logs_of_others_to_keep" +
");";
db.execSql(del);
// check count of logs
Cursor c3 = db.query(false, "log", null, null, null, null, null, "_id asc", null);
android.util.Log.d("TEST", "log count after: "+c3.getCount());
// check count of log_activities
Cursor c4 = db.query(false, "log_activity", null, null, null, null, null, "_id asc", null);
android.util.Log.d("TEST", "la count after: "+c4.getCount());
выход:
06-16 10:40:01.748: DEBUG/TEST(451): log count before: 4
06-16 10:40:01.748: DEBUG/TEST(451): la count before: 8
06-16 10:40:01.828: DEBUG/TEST(451): log count after: 3
06-16 10:40:01.838: DEBUG/TEST(451): la count after: 8
Это означает, что операция DELETE сама по себе хороша (я также проверил, что правильные строки удалены, что решает первую проблему !!), но ON DELETE CASCADE не работает ... почему?