SQL删除一个表+一个连接表?

Stu*_*uck 5 java sql sqlite android

我有三个表:log,activity和jointable(many2many) log_activity(与log_idactivity_id+附加信息数据列).

我想删除loglog_activity.

我希望保留特定用户的所有日志,并且只保留其他用户的100行. 这意味着我想删除所有匹配a的行WHERE log.user_id != 1,但是最后的100(ORDER BY log.timestamp DESC).

我还想从连接log_activity表中删除与删除的日志相关的所有条目.该activity表应被感动.

我认为db.delete(TABLE_NAME, whereClause , whereArgs);在这种情况下没有帮助..

有人能够提出有效的解决方案吗?


UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE


受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
);
Run Code Online (Sandbox Code Playgroud)

现在为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());
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

这意味着它自己的DELETE操作很好(我还检查了正确的行被删除,这解决了第一个问题!),但ON DELETE CASCADE不起作用...为什么?

Stu*_*uck 0

通过在 log_activity 表上使用外键解决了该问题,如下所示:

FOREIGN KEY(log_id) REFERENCES log(_id) ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

和这样的删除语句:

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);
Run Code Online (Sandbox Code Playgroud)

不要忘记启用外键:

db.execSQL("PRAGMA foreign_keys = ON;");
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是模拟器没有级联 log_activities.. 但在设备上它可以工作。感谢其他回答者给了我一些提示。

再次查看我的问题以了解更多详细信息。