SQLite
 sql >> डेटाबेस >  >> RDS >> SQLite

एंड्रॉइड रूम - प्रत्येक ऐप रन पर ऑटो जेनरेटेड टेबल प्राथमिक कुंजी को कैसे रीसेट करें

<ब्लॉकक्वॉट>

बाहर निकलने पर तालिकाओं को साफ़ करने के लिए, लेकिन यह कीस्टार्टिंग इंडेक्स को रीसेट नहीं करता है, इसके बजाय यह वहीं से शुरू होता है जहां इसे पिछले रन पर छोड़ा था।

....

<ब्लॉकक्वॉट>

"sqlite_sequence से हटाएं जहां नाम ='अनुक्रम क्रिया'" कोई त्रुटि नहीं है, लेकिन सूचकांक भी रीसेट नहीं किया गया है।

आपको दोनों को अनुक्रम कार्रवाई . में सभी पंक्तियों को हटाना होगा तालिका और संबंधित पंक्ति को sqlite_sequence से हटा दें।

यानी जब AUTOINCREMENT कीवर्ड का उपयोग किया जाता है तो एक अलग एल्गोरिदम का उपयोग किया जाता है। यह निम्न की तर्ज पर है:-

या तो का उच्चतम मान ज्ञात करें- a) sqlite_sequence संख्या में तालिका के लिए मान स्टोर और- b) उच्चतम पंक्तिबद्ध मान

एक विकल्प यह होगा कि AUTOINCREMENT . का उपयोग न किया जाए कीवर्ड, बल्कि सिर्फ ?? INTEGER PRIMARY KEY (कहां ?? कॉलम नाम का प्रतिनिधित्व करता है)।

आपके पास अभी भी एक अद्वितीय आईडी होगी जो rowid . का उपनाम है coulmn, लेकिन इस बात की कोई गारंटी नहीं है कि यह हमेशा बढ़ेगा। AUTOINCREMENT एक बढ़ती हुई अद्वितीय आईडी की गारंटी देता है, लेकिन यह एक नीरस रूप से बढ़ती हुई अद्वितीय पंक्ति की गारंटी नहीं देता है।

<ब्लॉकक्वॉट>

प्रत्येक एप्लिकेशन चलाने पर मुझे 0 से प्रारंभ करने के लिए इस कुंजी की आवश्यकता होती है।

हालांकि, SQLite पहले मान को 1 नहीं 0 पर सेट करेगा।

निम्नलिखित काम करता है, और जैसा कि आप ऑटोइनक्रिमेंट के साथ देखते हैं (यद्यपि एक हैक का थोड़ा सा) :-

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
  • दो DROP कथन केवल हटाने और फिर से परिभाषित करने के लिए परीक्षण के लिए आवश्यक हैं।

इसका परिणाम :-

लौटने वाली पहली क्वेरी :-

और दूसरा रिटर्निंग :-

तो संक्षेप में आप चाहते हैं :-

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

और अगर आप चाहते हैं कि नंबरिंग 1 के बजाय 0 से शुरू हो तो ट्रिगर भी।

वैकल्पिक रूप से यदि आपने ऑटोइनक्रिमेंट को समाप्त कर दिया है तो आप थोड़े बदले हुए ट्रिगर का उपयोग कर सकते हैं :-

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
;
  • यह केवल पहली सम्मिलित पंक्ति को फिर से क्रमांकित करता है (एल्गोरिदम फिर बाद के सम्मिलन में 1 जोड़ता है)

और फिर क्रमांकन को रीसेट करने के लिए, केवल SequenceAction तालिका से सभी पंक्तियों को हटा दें।

कक्ष का उपयोग करने का उदाहरण:-

उपरोक्त उदाहरण के साथ आपके कोड के आधार पर, निम्न विधि काम करती प्रतीत होती है :-

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

प्रारंभिक रन से परिणाम (यानी कोई डीबी मौजूद नहीं है) :-

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

बाद के रन से (40 पंक्तियों को जोड़ने के बाद) :-

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

सभी पंक्तियों को सूचीबद्ध करने के लिए एक विधि जोड़ना :-

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

साथ में :-

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

में परिणाम (पहली पंक्ति है ID=0 AT=X0 EI=Y0 यानी आईडी पहली पंक्ति का कॉलम 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
  • बिना नियंत्रण/अनुक्रमण के चल रहे कई थ्रेड्स के कारण नोट परिणाम अजीब हो सकते हैं।

addSomeData इस्तेमाल की जाने वाली विधि :-

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

अतिरिक्त टिप्पणियां :-

<ब्लॉकक्वॉट>

"मेरा मानना ​​​​है कि आपको कमरे से पहले अंदर जाना होगा ..." - क्या आपका मतलब एसक्यूएल निष्पादित करना है जो रूमडेटाबेस को तुरंत चालू करने से पहले चल रहे इंडेक्स को साफ़ करता है? - घोष

जरूरी नहीं है, लेकिन इससे पहले कि आप इसके साथ कुछ भी करने की कोशिश करने से पहले रूम डेटाबेस को खोलें। कुछ रूम डीबी एक्सेस के साथ इनवोकिंग कोड (ओवरराइड गतिविधियों में स्टार्ट() विधि) जोड़ा है, कुछ डेटा जोड़ने के तुरंत बाद कॉल किया जाता है। -माइकटी

यहां रूमडेटाबेस को इंस्टेंट करने के बाद रिसेटसेक्वेंसएक्शन मेथड को कॉल करने का एक उदाहरण दिया गया है, लेकिन इससे पहले कि इसका उपयोग डेटाबेस तक पहुंचने/खोलने के लिए किया जाता है (ऐडसोमडाटा पहले से इंस्टेंट किए गए डेटाबेस को खोलता है और 10 पंक्तियों को सम्मिलित करता है) :-

@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. Uncaught TypeError कॉर्डोवा 3.5 के साथ अपरिभाषित-SQLite प्लगइन की विधि 'ओपनडेटाबेस' को कॉल नहीं कर सकता है

  2. SQLite में विदेशी कुंजी समर्थन कैसे सक्षम करें

  3. रूम माइग्रेशन ऑल्टर टेबल नया कॉलम नहीं जोड़ रहा है और बार-बार कॉल करने पर माइग्रेट हो रहा है

  4. SQLite डेटाबेस को XML फ़ाइल में निर्यात करें

  5. SQLite में महीने का अंत लौटाएं