SQLite 删除一行并将所有其他行向上移动

SQLite delete a row and move all other rows up

这可能是不可能的,但我似乎找不到明确的答案。当我删除数据库中的一行时,我希望其他行的 ID 基本上向上移动,所以如果我删除第 2 行,那么第 3 行的 ID 将变为 2。这可能吗?我正在使用 AUTOINCREMENT,所以不知道是否有几乎相反的情况?

这是我的完整 SQLite 代码。

public class ProfileDatabaseHelper extends SQLiteOpenHelper {

    public static final String PROFILE_TABLE = "PROFILE_TABLE";
    public static final String PROFILE_ID = "ID";
    public static final String PROFILE_IMAGE = "PROFILE_IMAGE";
    public static final String RADAR_DATA_ONE = "DATA_ONE";
    public static final String RADAR_DATA_TWO = "DATA_TWO";
    public static final String RADAR_DATA_THREE = "DATA_THREE";
    public static final String RADAR_DATA_FOUR = "DATA_FOUR";
    public static final String RADAR_DATA_FIVE = "DATA_FIVE";
    public static final String RADAR_DATA_SIX = "DATA_SIX";

    public ProfileDatabaseHelper(@Nullable Context context) {
        super(context, "profiles.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTableStatement = "CREATE TABLE " + PROFILE_TABLE + " (" + PROFILE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + PROFILE_IMAGE + " TEXT, "
                + RADAR_DATA_ONE + " INT, " +  RADAR_DATA_TWO + " INT, " + RADAR_DATA_THREE + " INT, " + RADAR_DATA_FOUR + " INT, " + RADAR_DATA_FIVE
                + " INT, " + RADAR_DATA_SIX + " INT)";

        db.execSQL(createTableStatement);


    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public boolean updateData(Integer id,String profilePhoto,Integer dataOne, Integer dataTwo, Integer dataThree, Integer dataFour, Integer dataFive, Integer dataSix){
        SQLiteDatabase db=this.getWritableDatabase();
        ContentValues contentValues=new ContentValues();
        contentValues.put(PROFILE_ID,id);
        contentValues.put(PROFILE_IMAGE,profilePhoto);
        contentValues.put(RADAR_DATA_ONE,dataOne);
        contentValues.put(RADAR_DATA_TWO,dataTwo);
        contentValues.put(RADAR_DATA_THREE,dataThree);
        contentValues.put(RADAR_DATA_FOUR,dataFour);
        contentValues.put(RADAR_DATA_FIVE,dataFive);
        contentValues.put(RADAR_DATA_SIX,dataSix);
        db.update(PROFILE_TABLE,contentValues,"ID = ?",new String[] {id.toString()});
        return true;

    }


    public boolean addOne(ProfileModel profileModel){

        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();

        cv.put(PROFILE_IMAGE, profileModel.getProfilePhoto());
        cv.put(RADAR_DATA_ONE, profileModel.getDataOne());
        cv.put(RADAR_DATA_TWO, profileModel.getDataTwo());
        cv.put(RADAR_DATA_THREE, profileModel.getDataThree());
        cv.put(RADAR_DATA_FOUR, profileModel.getDataFour());
        cv.put(RADAR_DATA_FIVE, profileModel.getDataFive());
        cv.put(RADAR_DATA_SIX, profileModel.getDataSix());

        long insert = db.insert(PROFILE_TABLE, null, cv);
        if (insert == -1){
            return false;
        }
        else{
            return true;
        }
    }

    public Cursor alldata(){
        SQLiteDatabase dataBaseHelper = this.getWritableDatabase();
        Cursor cursor = dataBaseHelper.rawQuery("select * from PROFILE_TABLE ", null);
        return cursor;
    }

    public boolean delete(int id) {
        SQLiteDatabase db = this.getWritableDatabase();
        String queryString = "DELETE FROM " + PROFILE_TABLE + " WHERE " + PROFILE_ID + " = " + id;
        //deleting row
        Cursor cursor = db.rawQuery(queryString, null);
        if(cursor.moveToFirst()){
            return true;
        }
        else {
            return false;
        }
    }

}

I am using AUTOINCREMENT so didn't know if there was almost a reverse of that?

首先 AUTOINCREMENT 不会增加 rowid(或其别名)值,而是一个约束(规则),表示 rowid 必须大于任何已分配的值 (如果 sqlite_sequence 没有在 SQLite 对 table 的管理之外进行修改).

它使用 INTEGER PRIMARY KEY 允许自动分配一个值,通常比当前最高的 rowid 值大 1。但是,如果值 + 1 大于最大可能值 (9223372036854775807),则:-

  • 使用 AUTOINCREMENT 会出现 SQLITE_FULL 错误。
  • 没有 AUTOINCREMENT 会尝试查找未使用的数字。

(9223372036854775807) 极不可能成为 reached/used。

AUTOINCREMENT 效率较低,因为它必须记录有史以来分配的最高 rowid,并通过使用 sqlite_sequence table 来实现。在 SQLite 文档中它说:-

The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.

将 rowid 或其别名用于除预期用途之外的任何其他用途(例如在形成关系、更新或删除行时从另一行中唯一标识一行)是一个非常糟糕的主意。

  • 例如如果您按 ID 列以外的另一列或多列对数据进行排序 (ORDER BY) 会怎样?该 ID 对应用程序的用户有任何意义吗?

但是,尽管不推荐这样做,但以下内容可以满足您的要求:-

private void rationaliseCol1Values() {
    ContentValues cv = new ContentValues();
    Cursor csr = mDB.query(PROFILE_TABLE,null,null,null,null,null,PROFILE_ID + " ASC");

    int rowcount = csr.getCount();
    long expected_id = 1;
    long current_id;
    String where_clause = PROFILE_ID + "=?";
    String[] args = new String[1];

    while (csr.moveToNext()) {
        current_id = csr.getLong(csr.getColumnIndex(PROFILE_ID));
        if (current_id != expected_id) {
            cv.clear();
            cv.put(PROFILE_ID,expected_id);
            args[0] = String.valueOf(current_id);
            mDB.update(PROFILE_TABLE,cv,where_clause,args);
        }
        expected_id++;
    }
    csr.close();
    // Now adjust sqlite_sequence
    where_clause = "name=?";
    args[0] = PROFILE_TABLE;
    cv.clear();
    cv.put("seq",String.valueOf(rowcount));
    mDB.update("sqlite_sequence",cv,where_clause,args);
}
  • 请注意,代码取自此处的答案 并且已经过修改以适应但尚未编译或 运行 因此可能包含一些错误。