SQLite
 sql >> Teknologi Basis Data >  >> RDS >> SQLite

Ruang Android - Cara mengatur ulang kunci utama tabel yang dibuat secara otomatis pada setiap aplikasi yang dijalankan

Untuk menghapus tabel saat keluar tetapi, ini tidak mereset indeks keystarting, melainkan dimulai dari posisi terakhir dijalankan.

....

"delete from sqlite_sequence where name='Sequence Action'" Tidak ada kesalahantetapi, indeks juga tidak disetel ulang.

Anda harus menghapus semua baris di SequenceAction tabel DAN hapus masing-masing baris dari sqlite_sequence.

Yaitu ketika kata kunci AUTOINCREMENT digunakan maka algoritma yang berbeda digunakan. Ini sejalan dengan:-

Temukan nilai tertinggi dari salah satu- a) penyimpanan nilai untuk tabel dalam sqlite_sequence number dan- b) nilai rowid tertinggi

Alternatifnya adalah tidak menggunakan AUTOINCREMENT kata kunci, bukan hanya memiliki ?? INTEGER PRIMARY KEY (di mana ?? mewakili nama kolom).

Anda masih akan memiliki id unik yang merupakan alias dari rowid coulmn, tetapi tidak ada jaminan bahwa itu akan selalu meningkat. AUTOINCREMENT memang menjamin id unik yang meningkat, tetapi tidak menjamin rowid unik yang meningkat secara monoton.

Pada setiap aplikasi yang dijalankan, saya memerlukan kunci ini untuk memulai dari 0.

Namun, SQLite akan menyetel nilai pertama menjadi 1 bukan 0.

Berikut ini berfungsi, dan seperti yang Anda lihat dengan AUTOINCREMENT (walaupun sedikit peretasan):-

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
  • 2 pernyataan DROP hanya diperlukan untuk pengujian untuk menghapus dan mendefinisikan ulang.

Ini menghasilkan :-

Permintaan pertama kembali :-

dan yang ke-2 kembali :-

Jadi intinya Anda mau :-

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

Dan juga Pemicu jika Anda ingin penomoran dimulai dari 0 daripada 1.

Bergantian jika Anda menghapus AUTOINCREMENT maka Anda dapat menggunakan Pemicu yang sedikit diubah :-

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
;
  • Ini hanya menomori ulang baris pertama yang disisipkan (algoritme kemudian menambahkan 1 untuk sisipan berikutnya)

Kemudian cukup hapus semua baris dari tabel SequenceAction saja, untuk mengatur ulang penomoran.

Contoh menggunakan Kamar :-

Berdasarkan kode Anda bersama dengan contoh di atas, metode berikut tampaknya berfungsi :-

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();
}

Hasil dari proses awal (yaitu tidak ada DB):-

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

Dari proses berikutnya (setelah 40 baris ditambahkan):-

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

Menambahkan metode untuk mendaftar semua baris, sesuai :-

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

Bersama dengan :-

@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());
    }
}

Hasil di (baris pertama adalah ID=0 AT=X0 EI=Y0 yaitu ID kolom dari baris pertama adalah 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
  • Catatan hasil mungkin aneh karena beberapa utas berjalan tanpa kontrol/pengurutan.

addSomeData metode yang digunakan adalah :-

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();
}

Penambahan komentar :-

"Saya yakin Anda harus masuk sebelum Room..." - maksud Anda menjalankan SQL yang menghapus indeks yang berjalan sebelum membuat database Room? - astaga

belum tentu tetapi sebelum Roommembuka database yang sebelum Anda mencoba melakukan apa pun dengannya. Telah menambahkan kode pemanggilan (dalam metode Overidden aktivitas onStart() ) dengan beberapa akses Room Db ke addSomeData dipanggil segera setelahnya. –MikeT

Berikut adalah contoh pemanggilan metode resetSequenceAction setelah RoomDatabase di-instantiate, tetapi sebelum digunakan untuk mengakses/membuka database (addSomeData membuka Database yang sudah di-instantiated dan menyisipkan 10 baris):-

@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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PENINGKATAN OTOMATIS SQLite

  2. Bagaimana cara mengambil gambar dari database SQLite?

  3. Inisialisasi SQLite dan database

  4. Peringatan waktu kompilasi Ruang Android tentang kolom dalam kunci asing bukan bagian dari indeks. Apa artinya?

  5. SQLite JSON_GROUP_ARRAY()