如何在Room的数据库迁移中正确添加索引?

时间:2019-01-19 16:26:37

标签: android

我在迁移会议室数据库时遇到问题。在更新的数据库中,我必须将一个字段从整数更改为双精度值。我读起来并不像听起来那么容易,为了做到这一点,我必须使用更改后的属性创建新的临时表,复制上一个表中的所有值,删除旧表,最后重命名临时表。

我的实体有2个索引,这会引起问题。这是我目前最好的解决方案,没有通过自动生成的房间迁移验证。

oceny是原始表的名称,oceny_temp是临时名称。即使我将这些索引显式地添加到create index中,验证仍然没有通过,因为它说在预期表中有2个索引,并且发现有0。

static final Migration MIGRATION_25_26 = new Migration(25,26) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {

        database.execSQL("CREATE TABLE IF NOT EXISTS oceny_temp" +
                        "(`idOceny` TEXT NOT NULL, " +
                        "`idUcznia` TEXT, " +
                        "`idPrzedmiotu` TEXT, " +
                        "`semestr` INTEGER NOT NULL, " +
                        "`typOceny` INTEGER NOT NULL, " +
                        "`wartosc` TEXT, " +
                        "`wartoscDoSredniej` REAL, " +
                        "`czyProponowana` INTEGER NOT NULL, " +
                        "`kategoria` TEXT, " +
                        "`waga` REAL NOT NULL, " +
                        "`maxPunktow` REAL NOT NULL, " +
                        "`odczytana` INTEGER NOT NULL, " +
                        "`dataWystawienia` TEXT, " +
                        "`wystawiajacy` TEXT, " +
                        "`typOczekiwania` INTEGER NOT NULL, " +
                        "`wersjaRekordu` TEXT, " +
                        "`rekordUsuniety` INTEGER NOT NULL, " +
                        "PRIMARY KEY(`idOceny`), " +
                        "FOREIGN KEY(`idUcznia`) REFERENCES `uczniowie`(`idUcznia`) ON UPDATE NO ACTION ON DELETE CASCADE )");

        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny_temp (idPrzedmiotu)");
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny_temp (idUcznia)");


        // Copy the data
        database.execSQL(
                "INSERT INTO oceny_temp (idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety) " +
                                "SELECT idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety FROM oceny");

        // Remove the old table
        database.execSQL("DROP TABLE oceny");

        // Change the table name to the correct one
        database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");
    }
};

错误消息:

Migration didn't properly handle 

oceny(de.wolterskluwer.idziennik.model.grades.Grade).
 Expected:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[Index{name='index_oceny_idPrzedmiotu', unique=false, columns=[idPrzedmiotu]}, Index{name='index_oceny_idUcznia', unique=false, columns=[idUcznia]}]}
 Found:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[]}

其他信息:我将IF NOT EXISTS添加到创建索引中,因为它崩溃了,表明该索引已存在,这对我来说没有意义

2 个答案:

答案 0 :(得分:1)

问题是您发送的是“CREATE INDEX IF NOT EXISTS”命令,但同名索引已经存在,因此没有创建新索引。

您可以通过在尝试创建新索引之前删除现有索引或在流程末尾移动 create index 命令来解决此问题。

这是应该可以工作的完整代码:

static final Migration MIGRATION_25_26 = new Migration(25,26) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {

        database.execSQL("CREATE TABLE IF NOT EXISTS oceny_temp" +
                        "(`idOceny` TEXT NOT NULL, " +
                        "`idUcznia` TEXT, " +
                        "`idPrzedmiotu` TEXT, " +
                        "`semestr` INTEGER NOT NULL, " +
                        "`typOceny` INTEGER NOT NULL, " +
                        "`wartosc` TEXT, " +
                        "`wartoscDoSredniej` REAL, " +
                        "`czyProponowana` INTEGER NOT NULL, " +
                        "`kategoria` TEXT, " +
                        "`waga` REAL NOT NULL, " +
                        "`maxPunktow` REAL NOT NULL, " +
                        "`odczytana` INTEGER NOT NULL, " +
                        "`dataWystawienia` TEXT, " +
                        "`wystawiajacy` TEXT, " +
                        "`typOczekiwania` INTEGER NOT NULL, " +
                        "`wersjaRekordu` TEXT, " +
                        "`rekordUsuniety` INTEGER NOT NULL, " +
                        "PRIMARY KEY(`idOceny`), " +
                        "FOREIGN KEY(`idUcznia`) REFERENCES `uczniowie`(`idUcznia`) ON UPDATE NO ACTION ON DELETE CASCADE )");


        // Copy the data
        database.execSQL(
                "INSERT INTO oceny_temp (idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety) " +
                                "SELECT idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety FROM oceny");

        // Remove the old table
        database.execSQL("DROP TABLE oceny");

        // Change the table name to the correct one
        database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");

        // Recreate the indices
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny (idPrzedmiotu)");
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny (idUcznia)");
    }
};

请注意,由于我们已经在流程结束时重命名了该表,因此我们会在该迁移表上创建索引。

答案 1 :(得分:0)

重命名表时似乎丢失了索引。因此,通过将时间表重命名为正确的行后再添加一行来解决此问题。这将在重命名的表上创建索引。对于您来说,就是这样...

    // Change the table name to the correct one
    database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");

    // Create the indices on the table
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny ON oceny (idPrzedmiotu)");
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny (idUcznia)");