Deleting primary key in Room - android

I'm trying to set my primary key to one after deleting all items in table:
#Query("DELETE FROM myTable")
fun deleteTable()
#Query("DELETE FROM sqlite_sequence WHERE name = 'myTable'")
fun clearPrimaryKey()
but it doesn't work and after adding items again, their number don't start from 1. Any idea how to clear primary key in Room library?

Let us say your table name is myTable. Then just do this:
#Query("ALTER TABLE myTable AUTO_INCREMENT = 1")
fun clearPrimaryKey()
It resets the number of auto-generated primary key.
UPDATE:
Another way to do both deleting and resetting is this:
#Query("TRUNCATE TABLE myTable;")
fun deleteAndResetPrimaryKey()

Related

How do I correct a wrong Room migration?

I added a column to a table, then added the following migration (version 56 to 57):
private val MIGRATION_56_57 = object : Migration(56, 57) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE `app_stage` ADD COLUMN hasSeenBusinessOwnerQuestion INTEGER DEFAULT 0 NOT NULL")
}
}
After building and releasing the app to our existing users, they get a migration error and the app crashes. To correct the error, I just need to change:hasSeenBusinessOwnerQuestion INTEGER DEFAULT 0 NOT NULL
to:hasSeenBusinessOwnerQuestion INTEGER DEFAULT 0 .
Should I just add another migration from version 57 to 58 as:
private val MIGRATION_57_58 = object : Migration(57, 58) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE `app_stage` ADD COLUMN hasSeenBusinessOwnerQuestion INTEGER DEFAULT 0 ")
}
}
?
Will existing users upgrading from version 56 all the way to 58 get that same migration error? How do I add another migration to version 58 to avoid migration errors?
? Will existing users upgrading from version 56 all the way to 58 get that same migration error?
No Room will invoke all the migrations in sequence (56-57 and then 57-58) and then after all the migrations have been performed continue with the database build.
However you cannot use the ALTER command to ADD an already existing column, which would be the case going from 57-58. So the migration would fail.
Although later versions of SQLite (3.35.0) support ALTER TABLE .... DROP COLUMN ...., this version is not available at present on Android devices and that there is no ALTER COLUMN. You will have to use an alternative means to alter the column.
The DROP COLUMN is also quite restrictive
You could do the following (where ? represents the table in question):-
DROP TABLE IF EXISTS ?_old
this is just in-case it exists (it should not)
Use the ALTER TABLE ? RENAME TO ?_old (_old just a suggested name for what is to be a temporary version of the table)
Use CREATE TABLE IF NOT EXISTS ....
Room demands that the create table SQL creates the table according to how it interprets the class annotated with #Entity.
It is suggested that you retrieve the create table SQL from the generated java that is available after compiling the project. The SQL will be in the createAllTables method of the class that is the same as the class that is annotated with #Database but suffixed with _Impl
Use INSERT INTO ? SELECT * FROM ?_old to copy existing data into the newly created version of the table
Use DROP TABLE IF EXISTS ?
So apart from the CREATE TABLE .... (which would have to be altered, see points above) the following would cater for all scenarios (new users, users on 57 and users on 56) :-
private val MIGRATION_57_58 = object : Migration(57, 58) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS `app_stage_old`")
database.execSQL("ALTER TABLE `app_stage` RENAME TO `app_stage_old`")
/* NOTE the CREATE TABLE IF NOT EXISTS .... SHOULD BE ALTERED ACCORDINGLY */
database.execSQL("CREATE TABLE IF NOT EXISTS `app_stage` (`id` INTEGER, `name` TEXT NOT NULL,`hasSeenBusinessOwnerQuestion` INTEGER DEFAULT 0, PRIMARY KEY(`id`))")
database.execSQL("INSERT INTO `app_stage` SELECT * FROM `app_stage_old`")
database.execSQL("DROP TABLE IF EXISTS `app_stage_old`")
}
}

Android Room how to auto generate a sequence count

My current Android application employs Room/SQLite database
One of my Room Entities requires a sequence column that increments each time I insert a new row.
I would like this sequence to be auto generated, however it seems autoGenerate is only available for PrimaryKey(s)
Is there any way I can have a Int column in Room auto increment when it is not a primary key?
In most cases, a column is autogenerated containing a unique value (which I believe is an integer). This is known as the rowid. This rowid column automatically increments every time you insert a row (more information about rowid here).
rowid isn't usually included in SELECT *, so you will need to manually include it in your DAO #Query. See below:
#Query("SELECT *, rowid FROM my_table")
fun get(): MyEntity
or in java:
#Query("SELECT *, rowid FROM my_table")
public MyEntity get();
Note that if your primary key is a integer, it will actually be an alias to the rowid column. Again, see the link I provided above for more info.
Hope this helps!

Android SQLite onUpgrade add a new table without touching the old ones

I have a database setup in android right now. the database and tables work fine. However, when I want to add a new table and use onUpgrade - the database is created, but doesn't properly work. As in the table looks created but I can't add data to it. when I try the app crashes. All the version 1 tables still look fine.
here is what my onUpgrade looks like:
private val newDatabase = listOf<String>(
"Database1"
)
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
newDatabase.forEach{
val table2 = "CREATE TABLE $it ($ID INTEGER PRIMARY KEY, $AVERAGETIME TEXT DEFAULT \"0\",$DATE TEXT DEFAULT \"0\")"
db?.execSQL(table2)
}
}
my oncreate looks exactly the same, just uses a different array of strings:
override fun onCreate(db: SQLiteDatabase?) {
originalDatabase.forEach {
val table1 =
"CREATE TABLE $it ($ID INTEGER PRIMARY KEY, $AVERAGETIME TEXT DEFAULT \"0\",$DATE TEXT DEFAULT \"0\")"
db?.execSQL(table1)
}
}
Is this the best way to add a new table? once the table is made, it seems to be blank and not work right. even though I have default values set to it.
I tried looking through other posts but can't seem to find one concrete answer
Here is a working example Delivery Droid Database Class

Reset INTEGER PRIMARY KEY AUTOINCREMENT in Android

I created a table called DRINK. I inserted two rows in to it initially. When upgraded, I would like to delete both rows and reset my Primary Key to 1. I am getting the rows to delete but am not having any luck resetting the primary key. Does anybody know the syntax on how to do that or if it's even possible? Here's the function which is called from my onUpdate function:
private void updateMyDatabase(SQLiteDatabase db, int olderVersion, int newVersion){
Log.v("DatabaseHelper","UPDATE MY DATABASE");
if (olderVersion<1){
db.execSQL("CREATE TABLE DRINK (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "NAME TEXT, "
+ "DESCRIPTION TEXT, "
+ "IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db,"latte","Espresso and Steamed Milk",R.drawable.latte);
insertDrink(db, "cappuccino", "This a Cappuccino", R.drawable.cap);
}
if (olderVersion < 2){
db.execSQL("delete from DRINK");
db.execSQL("alter table AUTO_INCREMENT =1"); //*** NEED HELP HERE***
insertDrink(db, "coff", "Espresso and Steamed Milk", R.drawable.latte);
}
}
I found this piece of code online but it's not working. Thank you.
db.execSQL("alter table AUTO_INCREMENT =1");
Deleteing the rows won't reset ROWID.
SQLite documentation states:
SQLite keeps track of the largest ROWID that a table has ever held
using the special SQLITE_SEQUENCE table. The SQLITE_SEQUENCE table is
created and initialized automatically whenever a normal table that
contains an AUTOINCREMENT column is created. The content of the
SQLITE_SEQUENCE table can be modified using ordinary UPDATE, INSERT,
and DELETE statements. But making modifications to this table will
likely perturb the AUTOINCREMENT key generation algorithm.
This sql should do what you need:
UPDATE SQLITE_SEQUENCE SET seq = <n> WHERE name = <table>
Where n is the sequence you wish to set and table is your table name

Problem with inserting into android sqlite3 table that has composite primary key

I have a table with a composite primary key and I am having trouble inserting. The code used to create the table is:
CREATE TABLE ClassEvent (
EventName varchar(10) NOT NULL,
CourseId varchar(10) NOT NULL,
EventType varchar(20),
EventWeight number(3),
DueDate DATE NOT NULL,
FOREIGN KEY (CourseId) REFERENCES Courses(CourseId),
PRIMARY KEY (CourseId, EventName));
The problem I am having is when I want to insert records that have values that may not be unique for the columns CourseId or EventName, but are a unique combination of the 2.
for example, if I try to run the following 2 inserts:
INSERT INTO ClassEvent VALUES('Assignment 1','60-415','Assignment',10,'12/10/2010');
INSERT INTO ClassEvent VALUES('Project 1','60-415','Project',15,'5/12/2010');
I get the following error:
Error: columns CourseId, EventName are not unique.
and the second insert does not make it into the DB. Why does this error out? I thought that a composite primary key requires that the combination of both values are unique. In my above inserts, the values for the EventName column are different even though the values for CourseId are the same. Shouldn't this be seen as 2 unique combinations and thus 2 different primary keys?
My table needs to be able to hold several different events for each CourseId, but each Event must be unique for each Course. I need to be able to insert values into the table like:
EventName CourseId
Assignment 1 60-415
Project 1 60-415
Assignment2 60-415
Project 2 60-415
Assignment 1 60-367
Project 1 60-367
and so on. Can anyone tell me how I can get this to work? Why are these composite PK's not being seen as unique entries? Any help would be much appreciated.
Here is the java function I am using for the insert:
public void addNewClassEvent(ContentValues values) {
SQLiteDatabase db = openConnection();
db.insert("ClassEvent", null, values);
db.close();
}
Could this be causing the problem?
You can have a composite primary key in SQLite, but you
have to create the key when you create the table:
CREATE TABLE example1(
field1 FLOAT,
field2 TEXT,
PRIMARY KEY(field1, field2)
);
You cannot create the primary key after the fact using ALTER TABLE.
On the other hand, you can create a UNIQUE INDEX after the fact
which has essentially the same effect as a PRIMARY KEY:
CREATE UNIQUE INDEX pk_index ON "table1"("field1","field2");
I am not sure how you have created, the tables, and if you have added the primary index later, but grab the database to your desktop, and check out how works in a desktop environment.
You can't make combinations like that, but you don't need them. What is stopping you from just having a truly id column ?

Categories

Resources