取消删除和基于SQL的应用程序

问题描述 投票:-1回答:1

我想知道实现取消删除的最佳方法是使用SQL作为存储数据的底层结构的应用程序。我问,因为在SQL中一旦发出删除语句,就无法再恢复数据。但是,想象一个应用程序用于将仓库物品客户和供应商数据以及更多内容保存在列表中您的移动应用程序可能在您的口袋中并意外删除数据,或者您可能只是在使用用户界面时出错。

处理这个问题的最佳方法是什么?您可以废除SQL,但随后应用程序将变得缓慢,代码行和代码复杂性肯定会增加。

谢谢。

android sql sqlite user-experience mobile-application
1个回答
2
投票

您可以确保任何此类操作都需要确认。

您可以定期备份数据库,也可以在执行任何此类操作之前备份数据库。

您可以引入此类操作的日志记录,以允许将操作回滚到某个时间点。

没有特定的最佳方式,因为最合适的方式/可能取决于App的复杂性/简单性/效率。

在所有情况下,都会有额外的代码和复杂性。

简而言之,这些考虑因素应该是设计的一部分。

Additional re comment :-

您能告诉我如何使用触发器从原始表信息中复制日志表中的值吗?

考虑以下 :-

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;

这个

  1. DROPS所有表触发器(为了方便重新运行),然后
  2. 根据主表BUT创建日志记录表logtable,并为删除的日期和时间(时间戳)以及所采取的操作添加两个附加列。
  3. 创建主表main,带有ID列(rowid列的别名)和3列值,即val1,val2和val3
  4. 从插入可记录条目的主表中删除行时创建TRIGGER。
  5. 将一些行插入主表中。
  6. 选择主表中的所有行,然后选择logtable(result1和result2),以显示任何删除之前的数据。
  7. 删除一些行(根据ID列的第2和第4行)。
  8. 选择主表中的所有行,然后选择logtable(result3和result4),以显示删除后的数据。
  9. ROLLS根据ALL(WHERE子句可以使用日期回滚到一段时间或一段时间内)根据logtable返回对main的删除
  10. 更新logtable(可以是触发器,但根据与此示例中的ROLL BACK相同的条件完成)以反映回滚。
  11. 选择主表中的所有行,然后选择logtable(result5和result6),以显示回滚后的数据。

Results :-

1主要

  • 插入数据后

enter image description here

2日志表

  • (空无删除)(图片不必)

3主要

  • 删除后(3或原来的5行仍然存在)

enter image description here

4个logtable

  • 现在有2个日志条目,包含删除操作和删除的数据

enter image description here

5主要

  • 回滚后(已删除的行插入。注意新的ID虽然(可以根据原始设置ID))

enter image description here

6个logtable

  • 回滚后(日志条目现在标记为已完成)

enter image description here

  • 请注意,标记为DONE的logtable行实际上符合以下注释: -

在相关表中添加另一列以跟踪项目是否“已删除”。那么,你实际上不会删除任何记录;你只需要通过适当修改该列的值来软删除和取消删除

但可能允许logtable被删除。

Android Demo of the above:-

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: <<<<<
© www.soinside.com 2019 - 2024. All rights reserved.