【发布时间】:2011-06-15 22:53:43
【问题描述】:
我有三个表: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); 在这种情况下没有帮助..
那么有人能想出一个高效的解决方案吗?
更新更新更新更新更新更新更新更新更新更新
受到 Jacob Eggers 和 plafond 的回答以及进一步研究的启发,我现在正在尝试这样,但它还不起作用:
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
);
现在是安卓部分:
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 不起作用...为什么?
【问题讨论】:
-
您需要启用外键约束。 See this
-
我不是用 db.execSQL("PRAGMA foreign_keys = ON;"); ??
-
是的。抱歉错过了。你能检查一下,ON DELETE RESTRICT 有什么作用吗? (另外,您是否将记录添加到某处的活动中?那里的外键可能会阻止插入。)
-
是的,我将它添加到之前插入的活动中。使用 RESTRICT,我在执行 'DELETE FROM WHERE user_id != 1 AND log._id NOT IN (...
-
OK 不知道为什么,但是在我的手机设备上调试它确实会输出正确的值。而模拟器没有...