您可以确保任何此类操作都需要确认。
您可以定期或在任何此类操作之前备份数据库。
您可以引入此类操作的日志记录,以允许操作回滚到某个时间点。
没有特定的最佳方法,因为最合适的方法将/可能取决于应用程序的复杂性/简单性/效率。
在所有情况下,都会有额外的代码和复杂性。
简而言之,这些考虑应该是设计的一部分。
补充评论:-
能否请您告诉我如何从原始值中复制一个值
table info 带有触发器的日志表?
考虑以下几点:-
DROP TRIGGER IF EXISTS logdelete;
DROP TABLE IF EXISTS main;
DROP TABLE IF EXISTS logtable;
CREATE TABLE IF NOT EXISTS logtable (timestamp TEXT DEFAULT CURRENT_TIMESTAMP, logaction TEXT, val1 TEXT, val2 TEXT, val3 TEXT);
CREATE TABLE IF NOT EXISTS main (id INTEGER PRIMARY KEY, val1 TEXT, val2 TEXT, val3 TEXT);
CREATE TRIGGER IF NOT EXISTS logdelete AFTER DELETE ON main
BEGIN
INSERT INTO logtable (logaction, val1, val2, val3) VALUES('DLT',old.val1,old.val2,old.val3);
END
;
INSERT INTO main (val1,val2,val3) VALUES
('A','B','C'),('D','E','F'),('G','H','I'),('J','K','L'),('M','N','O');
SELECT * FROM main;
SELECT * FROM logtable;
DELETE FROM main WHERE val1 IN ('D','J');
SELECT * FROM main;
SELECT * FROM logtable;
INSERT INTO main (val1,val2,val3) SELECT val1,val2,val3 FROM logtable WHERE logaction = 'DLT';
UPDATE logtable SET logaction = 'DLTDONE' WHERE logaction = 'DLT';
SELECT * FROM main;
SELECT * FROM logtable;
这个
- 删除所有表触发器(为了方便重新运行),然后
- 根据主表创建日志记录表 logtable,但附加两列用于删除日期和时间(时间戳)以及所采取的操作。
- 创建主表 main,具有 ID 列(rowid 列的别名)和 3 列值,即 val1,val2 和 val3
- 当从插入 logtable 条目的 main 表中删除行时创建触发器。
- 在主表中插入一些行。
- 从 main 表和 logtable(result1 和 result2)中选择所有行,以显示删除之前的数据。
- 删除一些行(根据 ID 列的第 2 和第 4 行)。
- 从 main 表和 logtable(result3 和 result4)中选择所有行,以显示删除后的数据。
- 根据 logtable 回滚对 main 所做的删除,根据 ALL(WHERE 子句可以使用日期回滚到某个时间或一段时间)
- 更新 日志表(可能是一个触发器,但根据与本示例中的 ROLL BACK 相同的标准完成)以反映回滚。
- 从 main 表和 logtable(result5 和 result6)中选择所有行,以显示回滚后的数据。
结果:-
1 个主要
2 日志表
3 主要
4 日志表
5 主要
- 回滚后(插入已删除的行。但请注意新的 id(可以按照原始设置 id))
6 日志表
- 请注意,被标记为 DONE 的日志表行实际上是根据注释:-
在相关表中添加另一列以跟踪项目是否
“删除”。然后,您实际上不会删除任何记录;你只是
通过修改该列的值软删除和取消删除
适当的
但可能允许日志表被取消删除。
上面的Android Demo:-
DatabasHelper DBHelper.java
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TBL_MAIN = "main";
public static final String TBL_LOGTABLE = "logtable";
public static final String TRG_MAINDELETE = "logdelete";
public static final String COL_MAIN_ID = BaseColumns._ID;
public static final String COl_MAIN_VAL1 = "val1";
public static final String COL_MAIN_VAL2 = "val2";
public static final String COL_MAIN_VAL3 = "val3";
public static final String COL_LOGTABLE_TIMESTAMP = "timestamp";
public static final String COl_LOGTABLE_LOGACTION = "logaction";
public static final String COL_LOGTABLE_VAL1 = COl_MAIN_VAL1;
public static final String COL_LOGTABLE_VAL2 = COL_MAIN_VAL2;
public static final String COL_LOGTABLE_VAL3 = COL_MAIN_VAL3;
public static final String LOGACTION_DLTDONE = "DLTDONE";
public static final String LOGACTION_DELETE = "DLT";
private String main_crtsql = "CREATE TABLE IF NOT EXISTS " + TBL_MAIN + "(" +
COL_MAIN_ID + " INTEGER PRIMARY KEY," +
COl_MAIN_VAL1 + " TEXT," +
COL_MAIN_VAL2 + " TEXT, " +
COL_MAIN_VAL3 + " TEXT" +
")";
private String logtable_crtsql = "CREATE TABLE IF NOT EXISTS " + TBL_LOGTABLE + "(" +
COL_LOGTABLE_TIMESTAMP + " TEXT DEFAULT CURRENT_TIMESTAMP, " +
COl_LOGTABLE_LOGACTION + " TEXT, " +
COL_LOGTABLE_VAL1 + " TEXT, " +
COL_LOGTABLE_VAL2 + " TEXT, " +
COL_LOGTABLE_VAL3 + " TEXT " +
")";
private String logdelete_crtsql = "CREATE TRIGGER IF NOT EXISTS " + TRG_MAINDELETE +
" AFTER DELETE ON " + TBL_MAIN +
" BEGIN " +
"INSERT INTO " + TBL_LOGTABLE + "(" +
COl_LOGTABLE_LOGACTION + "," +
COL_LOGTABLE_VAL1 + "," +
COL_LOGTABLE_VAL2 + "," +
COL_LOGTABLE_VAL3 +
")" +
" VALUES(" +
"'DLT'," +
"old." + COL_LOGTABLE_VAL1 + "," +
"old." + COL_LOGTABLE_VAL2 + "," +
"old." + COL_LOGTABLE_VAL3 +
")" +
";" +
" END";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(logtable_crtsql);
db.execSQL(main_crtsql);
db.execSQL(logdelete_crtsql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addMain(String val1, String val2, String val3) {
ContentValues cv = new ContentValues();
cv.put(COl_MAIN_VAL1,val1);
cv.put(COL_MAIN_VAL2,val2);
cv.put(COL_MAIN_VAL3,val3);
return mDB.insert(TBL_MAIN,null,cv);
}
public int deleteMain(String val) {
String whereclause = COl_MAIN_VAL1 + "=?";
String[] whereargs = new String[]{val};
return mDB.delete(TBL_MAIN,whereclause,whereargs);
}
//INSERT INTO main (val1,val2,val3) SELECT val1,val2,val3 FROM logtable WHERE logaction = 'DLT';
//UPDATE logtable SET logaction = 'DLTDONE' WHERE logaction = 'DLT';
public void rollbackMain() {
String columns = " (" + COl_MAIN_VAL1 + "," + COL_MAIN_VAL2 + "," +COL_LOGTABLE_VAL3 + ")";
String values = " SELECT " + COL_LOGTABLE_VAL1 + "," + COL_LOGTABLE_VAL2 + "," + COL_LOGTABLE_VAL3 +
" FROM " + TBL_LOGTABLE + " WHERE " + COl_LOGTABLE_LOGACTION + "='" + LOGACTION_DELETE + "'";
String insertsql = "INSERT INTO " + TBL_MAIN + columns + values;
mDB.beginTransaction();
mDB.execSQL(insertsql);
ContentValues cv = new ContentValues();
cv.put(COl_LOGTABLE_LOGACTION,LOGACTION_DLTDONE);
String wherecluase = COl_LOGTABLE_LOGACTION + "=?";
String[] whereargs = new String[]{LOGACTION_DELETE};
mDB.update(TBL_LOGTABLE,cv,wherecluase,whereargs);
mDB.setTransactionSuccessful();
mDB.endTransaction();
}
public void logtables() {
Cursor csr = mDB.query(TBL_MAIN,null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr = mDB.query(TBL_LOGTABLE,null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
一个活动 - MainActivity.java
public class MainActivity extends AppCompatActivity {
DBHelper mDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new DBHelper(this);
// Empty main and logtable
mDBHlpr.getWritableDatabase().delete(DBHelper.TBL_MAIN,null,null);
mDBHlpr.getWritableDatabase().delete(DBHelper.TBL_LOGTABLE,null,null);
// Add some data
mDBHlpr.addMain("Fred","Banana","Rock");
mDBHlpr.addMain("Mary","Orange","Scissors");
mDBHlpr.addMain("Sue","Apple","Paper");
mDBHlpr.logtables();
//Delete some data
mDBHlpr.deleteMain("Mary");
mDBHlpr.deleteMain("MrNobody");
mDBHlpr.deleteMain("Sue");
mDBHlpr.logtables();
//Rollback
mDBHlpr.rollbackMain();
mDBHlpr.logtables();
}
}
结果
(等同于之前的结果,尽管数据不同)
1.
2019-03-27 12:44:37.136 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@7f0608d
2019-03-27 12:44:37.137 I/System.out: 0 {
2019-03-27 12:44:37.137 I/System.out: _id=1
2019-03-27 12:44:37.137 I/System.out: val1=Fred
2019-03-27 12:44:37.137 I/System.out: val2=Banana
2019-03-27 12:44:37.137 I/System.out: val3=Rock
2019-03-27 12:44:37.137 I/System.out: }
2019-03-27 12:44:37.137 I/System.out: 1 {
2019-03-27 12:44:37.137 I/System.out: _id=2
2019-03-27 12:44:37.137 I/System.out: val1=Mary
2019-03-27 12:44:37.137 I/System.out: val2=Orange
2019-03-27 12:44:37.137 I/System.out: val3=Scissors
2019-03-27 12:44:37.137 I/System.out: }
2019-03-27 12:44:37.137 I/System.out: 2 {
2019-03-27 12:44:37.137 I/System.out: _id=3
2019-03-27 12:44:37.137 I/System.out: val1=Sue
2019-03-27 12:44:37.138 I/System.out: val2=Apple
2019-03-27 12:44:37.138 I/System.out: val3=Paper
2019-03-27 12:44:37.138 I/System.out: }
2019-03-27 12:44:37.138 I/System.out: <<<<<
2.
2019-03-27 12:44:37.138 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8d24242
2019-03-27 12:44:37.138 I/System.out: <<<<<
3.
2019-03-27 12:44:37.140 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2c28253
2019-03-27 12:44:37.140 I/System.out: 0 {
2019-03-27 12:44:37.140 I/System.out: _id=1
2019-03-27 12:44:37.141 I/System.out: val1=Fred
2019-03-27 12:44:37.141 I/System.out: val2=Banana
2019-03-27 12:44:37.141 I/System.out: val3=Rock
2019-03-27 12:44:37.141 I/System.out: }
2019-03-27 12:44:37.141 I/System.out: <<<<<
4.
2019-03-27 12:44:37.142 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@fb8f790
2019-03-27 12:44:37.142 I/System.out: 0 {
2019-03-27 12:44:37.142 I/System.out: timestamp=2019-03-27 01:44:37
2019-03-27 12:44:37.142 I/System.out: logaction=DLT
2019-03-27 12:44:37.142 I/System.out: val1=Mary
2019-03-27 12:44:37.142 I/System.out: val2=Orange
2019-03-27 12:44:37.142 I/System.out: val3=Scissors
2019-03-27 12:44:37.143 I/System.out: }
2019-03-27 12:44:37.143 I/System.out: 1 {
2019-03-27 12:44:37.143 I/System.out: timestamp=2019-03-27 01:44:37
2019-03-27 12:44:37.143 I/System.out: logaction=DLT
2019-03-27 12:44:37.143 I/System.out: val1=Sue
2019-03-27 12:44:37.143 I/System.out: val2=Apple
2019-03-27 12:44:37.143 I/System.out: val3=Paper
2019-03-27 12:44:37.143 I/System.out: }
2019-03-27 12:44:37.144 I/System.out: <<<<<
5.
2019-03-27 12:44:37.145 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@68f7889
2019-03-27 12:44:37.145 I/System.out: 0 {
2019-03-27 12:44:37.146 I/System.out: _id=1
2019-03-27 12:44:37.146 I/System.out: val1=Fred
2019-03-27 12:44:37.146 I/System.out: val2=Banana
2019-03-27 12:44:37.146 I/System.out: val3=Rock
2019-03-27 12:44:37.146 I/System.out: }
2019-03-27 12:44:37.146 I/System.out: 1 {
2019-03-27 12:44:37.146 I/System.out: _id=2
2019-03-27 12:44:37.146 I/System.out: val1=Mary
2019-03-27 12:44:37.146 I/System.out: val2=Orange
2019-03-27 12:44:37.146 I/System.out: val3=Scissors
2019-03-27 12:44:37.146 I/System.out: }
2019-03-27 12:44:37.146 I/System.out: 2 {
2019-03-27 12:44:37.146 I/System.out: _id=3
2019-03-27 12:44:37.146 I/System.out: val1=Sue
2019-03-27 12:44:37.146 I/System.out: val2=Apple
2019-03-27 12:44:37.146 I/System.out: val3=Paper
2019-03-27 12:44:37.146 I/System.out: }
2019-03-27 12:44:37.146 I/System.out: <<<<<
6.
2019-03-27 12:44:37.147 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@4c6408e
2019-03-27 12:44:37.147 I/System.out: 0 {
2019-03-27 12:44:37.147 I/System.out: timestamp=2019-03-27 01:44:37
2019-03-27 12:44:37.147 I/System.out: logaction=DLTDONE
2019-03-27 12:44:37.147 I/System.out: val1=Mary
2019-03-27 12:44:37.147 I/System.out: val2=Orange
2019-03-27 12:44:37.147 I/System.out: val3=Scissors
2019-03-27 12:44:37.147 I/System.out: }
2019-03-27 12:44:37.147 I/System.out: 1 {
2019-03-27 12:44:37.147 I/System.out: timestamp=2019-03-27 01:44:37
2019-03-27 12:44:37.148 I/System.out: logaction=DLTDONE
2019-03-27 12:44:37.148 I/System.out: val1=Sue
2019-03-27 12:44:37.148 I/System.out: val2=Apple
2019-03-27 12:44:37.148 I/System.out: val3=Paper
2019-03-27 12:44:37.148 I/System.out: }
2019-03-27 12:44:37.148 I/System.out: <<<<<