sql >> Database teknologi >  >> RDS >> SQLite

Android Room - Sådan nulstiller du automatisk genereret tabel primær nøgle ved hver appkørsel

For at rydde tabellerne ved afslutning, men dette nulstiller ikke nøglestartindekset, i stedet starter det, hvor det slap ved sidste kørsel.

....

"delete from sqlite_sequence where name='Sequence Action'" Ingen fejl, men indekset er heller ikke nulstillet.

Du skal begge slette alle rækker i SequenceAction tabel OG slet den respektive række fra sqlite_sequence.

Det er, når AUTOINCREMENT søgeordet bruges, så bruges en anden algoritme. Dette er i stil med:-

Find den højeste værdi af enten- a) værdilageret for tabellen i sqlite_sequence-nummeret og- b) den højeste rowid-værdi

Et alternativ ville være ikke at bruge AUTOINCREMENT søgeord, i stedet for bare at have ?? INTEGER PRIMARY KEY (hvor ?? repræsenterer kolonnenavnet).

Du vil stadig have et unikt id, der er et alias for rowid coulmn, men der er ingen garanti for, at den altid vil stige. AUTOINCREMENT garanterer et stigende unikt id, men det garanterer ikke en monotont stigende unik rowid.

Ved hvert program, der kører, skal jeg bruge denne nøgle til at starte fra 0.

Men SQLite vil sætte den første værdi til 1 ikke 0.

Følgende virker, og som du ser med AUTOINCREMENT (omend lidt af et hack) :-

DROP TABLE IF EXISTS SequenceAction;
DROP TRIGGER IF EXISTS use_zero_as_first_sequence;
CREATE TABLE IF NOT EXISTS SequenceAction (id INTEGER PRIMARY KEY AUTOINCREMENT, otherdata TEXT);
CREATE TRIGGER IF NOT EXISTS use_zero_as_first_sequence AFTER INSERT ON SequenceAction
    BEGIN 
        UPDATE SequenceAction SET id = id - 1 WHERE id = new.id;
    END
;
INSERT INTO SequenceAction VALUES(null,'TEST1'),(null,'TEST2'),(null,'TEST3');
SELECT * FROM SequenceAction;
-- RESET and RESTART FROM 0
DELETE FROM SequenceAction;
DELETE FROM sqlite_sequence WHERE name = 'SequenceAction';
INSERT INTO SequenceAction VALUES(null,'TEST4'),(null,'TEST5'),(null,'TEST6');
SELECT * FROM SequenceAction
  • De 2 DROP-sætninger kræves kun for at teste kan slette og omdefinere.

Dette resulterer i:-

Den første forespørgsel, der returnerer :-

og den 2. tilbagevendende :-

Så i bund og grund vil du have :-

DELETE FROM SequenceAction;
DELETE FROM sqlite_sequence WHERE name = 'SequenceAction';

Og også triggeren, hvis du ønsker, at nummerering skal starte fra 0 i stedet for 1.

Alternativt, hvis du gjorde op med AUTOINCREMENT, kunne du bruge en lidt ændret trigger :-

CREATE TRIGGER IF NOT EXISTS use_zero_as_first_sequence 
    AFTER INSERT ON SequenceAction 
    WHEN (SELECT count() FROM SequenceAction) = 1
    BEGIN 
        UPDATE SequenceAction SET id = 0;
    END
;
  • Dette omnummererer blot den allerførste indsatte række (algoritmen tilføjer derefter 1 fra efterfølgende indsættelser)

Og slet så blot alle rækker fra kun SequenceAction-tabellen for at nulstille nummereringen.

Eksempel ved brug af værelse :-

Baseret på din kode sammen med eksemplet ovenfor ser den følgende metode ud til at virke:-

private void resetSequenceAction() {
    SQLiteDatabase dbx;
    String sqlite_sequence_table = "sqlite_sequence";
    long initial_sacount;
    long post_sacount;
    long initial_ssn =0;
    long post_ssn = 0;
    Cursor csr;

    /*
        Need to Create Database and table if it doesn't exist
     */
    File f = this.getDatabasePath(TestDatabase.DBNAME);
    if (!f.exists()) {
        File d = new File(this.getDatabasePath(TestDatabase.DBNAME).getParent());
        d.mkdirs();
        dbx = SQLiteDatabase.openOrCreateDatabase(f,null);
        String crtsql = "CREATE TABLE IF NOT EXISTS " + SequenceAction.tablename + "(" +
                SequenceAction.id_column + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                SequenceAction.actionType_column + " TEXT," +
                SequenceAction.extraInfo_column + " TEXT" +
                ")";
        dbx.execSQL(crtsql);
        /*
           Might as well create the Trigger as well
         */
        String triggerSql = "CREATE TRIGGER IF NOT EXISTS user_zero_as_first_rowid AFTER INSERT ON " +
                SequenceAction.tablename +
                " BEGIN " +
                " UPDATE " + SequenceAction.tablename +
                " SET " +
                SequenceAction.id_column + " = " + SequenceAction.id_column + " - 1 " +
                " WHERE " + SequenceAction.id_column + " = new." + SequenceAction.id_column + ";" +
                " END ";
        dbx.execSQL(triggerSql);

    } else {
        dbx = SQLiteDatabase.openDatabase(this.getDatabasePath(TestDatabase.DBNAME).getPath(),null, Context.MODE_PRIVATE);
    }

    /*
        Add trigger to set id's to 1 less than they were set to
     */
    initial_sacount = DatabaseUtils.queryNumEntries(dbx,SequenceAction.tablename);
    /*
        Delete all the rows at startup
     */
    String deleteAllSequenceIdRowsSql = "DELETE FROM " + SequenceAction.tablename;
    dbx.execSQL(deleteAllSequenceIdRowsSql);
    post_sacount = DatabaseUtils.queryNumEntries(dbx,SequenceAction.tablename);
    /*
        delete the sequence row from the sqlite_sequence table
     */
    csr = dbx.query(sqlite_sequence_table,
            new String[]{"seq"},"name=?",
            new String[]{SequenceAction.tablename},
            null,null,null
    );
    if (csr.moveToFirst()) {
        initial_ssn = csr.getLong(csr.getColumnIndex("seq"));
    }
    String deleteSqlLiteSequenceRow = "DELETE FROM " +
            sqlite_sequence_table +
            " WHERE name = '" + SequenceAction.tablename + "'";
    dbx.execSQL(deleteSqlLiteSequenceRow);
    csr = dbx.query(
            sqlite_sequence_table,
            new String[]{"seq"},
            "name=?",
            new String[]{SequenceAction.tablename},
            null,null,null
    );
    if (csr.moveToFirst()) {
        post_ssn = csr.getLong(csr.getColumnIndex("seq"));
    }
    csr.close();
    Log.d("SEQACTSTATS",
            "Initial Rowcount=" + String.valueOf(initial_sacount) +
                    " Initial Seq#=" + String.valueOf(initial_ssn) +
                    " Post Delete Rowcount =" + String.valueOf(post_sacount) +
                    " Post Delete Seq#=" + String.valueOf(post_ssn)
    );
    dbx.close();
}

Resultat fra en indledende kørsel (dvs. der findes ingen DB) :-

D/SEQACTSTATS: Initial Rowcount=0 Initial Seq#=0 Post Delete Rowcount =0 Post Delete Seq#=0

Fra en efterfølgende kørsel (efter 40 rækker er tilføjet) :-

D/SEQACTSTATS: Initial Rowcount=40 Initial Seq#=40 Post Delete Rowcount =0 Post Delete Seq#=0

Tilføjelse af en metode til at liste alle rækkerne, som pr. :-

private void listAllRows() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            salist = mTestDB.SequenceActionDaoAccess().getAll();
            getSequenceActionList(salist);
        }
    }).start();
}

Sammen med :-

@Override
public void getSequenceActionList(List<SequenceAction> sequenceActionList) {
    for (SequenceAction sa: sequenceActionList) {
        Log.d("SA","ID=" + String.valueOf(sa.getSequenceId()) + " AT=" + sa.getActionType() + " EI=" + sa.getExtraInfo());
    }
}

Resultater i (første række er ID=0 AT=X0 EI=Y0 dvs. ID'et kolonnen i den første række er 0 ):-

06-17 02:56:47.867 5526-5554/rt_mjt.roomtest D/SA: ID=0 AT=X0 EI=Y0
    ID=1 AT=X0 EI=Y0
    ID=2 AT=X0 EI=Y0
    ID=3 AT=X0 EI=Y0
    ID=4 AT=X1 EI=Y1
    ID=5 AT=X1 EI=Y1
    ID=6 AT=X1 EI=Y1
    ID=7 AT=X1 EI=Y1
06-17 02:56:47.868 5526-5554/rt_mjt.roomtest D/SA: ID=8 AT=X2 EI=Y2
    ID=9 AT=X2 EI=Y2
    ID=10 AT=X2 EI=Y2
    ID=11 AT=X2 EI=Y2
    ID=12 AT=X3 EI=Y3
    ID=13 AT=X3 EI=Y3
    ID=14 AT=X3 EI=Y3
    ID=15 AT=X3 EI=Y3
    ID=16 AT=X4 EI=Y4
06-17 02:56:47.869 5526-5554/rt_mjt.roomtest D/SA: ID=17 AT=X4 EI=Y4
    ID=18 AT=X4 EI=Y4
    ID=19 AT=X4 EI=Y4
    ID=20 AT=X5 EI=Y5
    ID=21 AT=X5 EI=Y5
    ID=22 AT=X5 EI=Y5
    ID=23 AT=X5 EI=Y5
    ID=24 AT=X6 EI=Y6
    ID=25 AT=X6 EI=Y6
    ID=26 AT=X6 EI=Y6
    ID=27 AT=X6 EI=Y6
06-17 02:56:47.870 5526-5554/rt_mjt.roomtest D/SA: ID=28 AT=X7 EI=Y7
    ID=29 AT=X7 EI=Y7
    ID=30 AT=X7 EI=Y7
    ID=31 AT=X7 EI=Y7
    ID=32 AT=X8 EI=Y8
    ID=33 AT=X8 EI=Y8
    ID=34 AT=X8 EI=Y8
    ID=35 AT=X8 EI=Y8
    ID=36 AT=X9 EI=Y9
    ID=37 AT=X9 EI=Y9
    ID=38 AT=X9 EI=Y9
    ID=39 AT=X9 EI=Y9
  • Bemærkningsresultater kan være mærkelige på grund af flere tråde, der kører uden kontrol/sekventering.

addSomeData den anvendte metode er :-

private void addSomeData() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            SequenceAction sa = new SequenceAction();
            for (int i=0; i < 10; i++) {
                sa.setSequenceId(0);
                sa.setActionType("X" + String.valueOf(i));
                sa.setExtraInfo("Y" + String.valueOf(i));
                mTestDB.SequenceActionDaoAccess().insertSingleRow(sa);
            }
        }
    }) .start();
}

Tilføjelse af kommentarer :-

"Jeg tror, ​​du skal komme ind før Room..." - mener du at udføre SQL'en, der rydder det kørende indeks, før Roomdatabasen instansieres? - pyt

ikke nødvendigvis, men før Roomåbner databasen, som er før du forsøger at gøre noget med den. Har tilføjet påkaldelseskode (i Overidden aktiviteter påStart()-metoden )med nogle Room Db-adgang til addSomeData kaldes umiddelbart efter. –MikeT

Her er et eksempel på at kalde resetSequenceAction-metoden efter RoomDatabasen er blevet instansieret, men før den bruges til at få adgang til/åbne databasen (addSomeData åbner den allerede instansierede database og indsætter 10 rækker) :-

@Override
protected void onStart() {
    super.onStart();
    mTestDB = Room.databaseBuilder(this,TestDatabase.class,TestDatabase.DBNAME).build(); //<<<< Room DB instantiated
    resetSequenceAction(); //<<<< reset the sequence (adding trigger if needed)
    addSomeData(); // This will be the first access open
    addSomeData();
    addSomeData();
    addSomeData();
    listAllRows();


  1. Den nemme guide til, hvordan du bruger underforespørgsler i SQL Server

  2. Fire måder at bruge Microsoft Access på

  3. Postgres er den fedeste database – Årsag #2:Licensen

  4. Er det vigtigt at lukke mysql-forbindelsen?