Why does the row id (_id) for Instances table change? - android

I'm building an app for Android where I'm reading the instances table to get all events.
I've used the "unique" row id as a way to reference to different instances, however I've now found that the row id changes over time, it actually seems to increment by 2 every now and then. Is there a reason for this behaviour? What is the recommended way to handle instances and how to uniquely reference each instance?
This is the only code I use when creating the meeting objects in the app.
int columnID = cursor.getColumnIndex(CalendarContract.Instances._ID);
String uniqueid = cursor.getString(columnID);
meeting.setUniqueId(uniqueid);

I think you should be using CalendarContract.Instances.EVENT_ID instead as the documentation describes that as the unique ID for events: EVENT_ID
_ID might be changing because they are adding/removing rows under the hood without caring for the changes.

Related

SQLite (Android) : UPDATE query with ORDER BY

Android, SQLite : I want to insert rows in between other rows in myTable using SQLite in android. For this, I am trying to increment ids of the all rows starting say row 3. So that I can insert a new row at position 3.
The primary key of myTable is column id. There are no other constraints in the table.
I have tried using the query mentioned in https://stackoverflow.com/a/9177264/6671004. This query does work in mySQL but not in Android (SQLite)
Here's the line of code :
database.execSQL("UPDATE myTable SET id = (id + 1) where id > 2 ORDER BY id desc");
Here's the error I'm getting on Android Studio (Compile time) :
https://imgur.com/a/9r0iyAa
This is the exception I'm getting if I remove 'ORDER BY id DESC' from the query :
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: myTable.id (code 1555)
Is this the correct way to do this? Or is there a better way?
As pointed out by many, this is definitely not the correct way to go.
But I found workaround in case someone else is looking for a similar implementation.
Here it is :
UPDATE myTable SET id = - (id + 1) WHERE id > 1;
UPDATE myTable SET id = - id WHERE id < 0;
This is a hack which I found here.
Again, this is not the correct way to go. But just posting a working solution I found.
I have tried using the query mentioned in
https://stackoverflow.com/a/9177264/6671004. This query does work in
mySQL but not in Android (SQLite)
That question is tagged MYSQL. MYSQL has many differences from SQLite.
Here's the line of code :
database.execSQL("UPDATE myTable SET id = (id + 1) where id > 2 ORDER
BY id desc");
The SQLite UPDATE SQL takes the form of :-
i.e. there is no ORDER BY clause and hence the error saying that if you're going to use any KEYWORD then it must be a BETWEEN or IN or a ; (of course you could also extend the condition using AND OR and so on).
This is the exception I'm getting if I remove 'ORDER BY id DESC' from
the query :
The reason being is that the rowid (id being an alias of rowid) has an implied UNIQUE constraint and that the rows will be updated according to the id column in order. So if there are more than 3 rows (or have been and the last row has never been deleted) then when the id is 3, a row with 4 will exist and 3 + 1 = 4 so the row already exists and hence the UNIQUE constraint being encountered.
I want to insert rows in between other rows in myTable using SQLite in
android. For this, I am trying to increment ids of the all rows
starting say row 3. So that I can insert a new row at position 3.
In short that is not a good idea and is virtually definitely not needed.
Is this the correct way to do this? Or is there a better way?
Definitely no
At a guess you want a nice humanly understandable value so you can know what's going on. For example you may present a list with the sequence so you can then say delete the row that has a sequence of 3 and thus equate that to the id column. Fine until you present the list in a different order which may be more user friendly. Suddenly your sequence becomes complicated or even useless and if displayed confusing.
identifiers are intended to identify a row and allow fast access to that row as a numerical index will be more efficient (than a human easily readable non-numeric index) to process. They also cater for reducing unnecessary additional processing (shifting data).
An efficient methodology is presenting the list with tying the id to the position in the list (so position could be the nth element of an array that holds the respective id, regenerating the list (the underlying array) according to a different order so the nth element will still have the respective id).
Embarking on a process of shifting rows will impose additional resource usage for example extra disk IO whose cost is relatively expense. This will be compounded by the fact that you will have to process the rows in reverse order to get around the UNIQUE constraint, that in itself is going to require using even costlier methods because SQLite will by default try to perform the updates efficiently rather than cater for the efficiencies required to digress from recognised/accepted techniques that utilise the underlying efficiencies.
I found this one working. And remove autoincrement from id
String strSQL1 = "UPDATE people_table SET id = (id +1) WHERE id < 0";
String strSQL = "UPDATE people_table SET id = (id -1) WHERE id > 1";
db.execSQL(strSQL);
db.execSQL(strSQL1);

how can I get the id of the last inserted event

First of all I am using SQLite-Net-Pcl on Xamarin.Android
My question is this, I need to create an event that is recursive,
and I need to connect all those recursive events (in case of someone edditing them or delleting them).
And I need to use the original Event's Id to connect it to the others
-> creates new recursive event
-> gets the id of inserted event
-> uses that id to connect all recursive events together on a "NumDocConnection"
My Id is auto-incremented, and is the primary key.
So, how can I get the id of the last inserted event? or is this even a good way do to deal with the situation?
how can I get the id of the last inserted event?
The int-based primary/auto-inc value is obtained via the object that you inserted (the object instance is updated during the Insert with the new value).
var newRecord = new Record { SomeString = "StackOverflow" };
var numofRecordsInserted = conn.Insert(newRecord);
Console.WriteLine($"Newly inserted id = {newRecord.Key}");
is this even a good way do to deal with the situation
That depends upon your application. A pri-key/auto-inc field does prevent the reuse of the generated IDs, that is until the database is reset (via deletion/re-creation or a reset via the the sqlite_sequence table).
Should you use it as a "foreign" key, lots of opinions here, some yes, some no.... Personally if you never use it externally to your app (i.e. it is not transmitted/sync'd via a remote API) it works well/fast as a foreign key if you understand how SQLite creates it and when it can/could be reset, see the linked docs.
If the AUTOINCREMENT keyword appears after INTEGER PRIMARY KEY, that changes the automatic ROWID assignment algorithm to prevent the reuse of ROWIDs over the lifetime of the database. In other words, the purpose of AUTOINCREMENT is to prevent the reuse of ROWIDs from previously deleted rows.
re: https://sqlite.org/autoinc.html

Saving a changing amount of Values in a SQL-Database

i am really stuck at this point of my android app development.
What i need is a way to save a changing amount of int or string-values (in a sql database). Yet im not even sure if this is the right approach, but let me explain:
In the app i am currently working on, you are able to create certain "events". Users should be able to apply for such events.
I have an external database with 2 tables:
first one for users - every user has a unique ID
second one for events - every event has a unique ID
I need each event to know what users applied for it. And i need each user to know what events they applied for.
I was thinking to save the Event-IDs in the User-Table and vice versa.
I just dont know how to do that since the amount of applicants/ID's can change. Is there a way to save Arrays in the database which can easily be edited (e.g. +/- one ID) and read?
Is this even the right way? I am very happy for any advise!
Thanks in advance!
What you seem to want is a many-to-many relationship. A user can be part of many events, and an event can have many users. That requires an additional table though:
Table: User Columns: UserId, Name, ...
Table: Event Columns: EventId, Name, ...
Table: UserEvents Columns: UserId, EventId, ...
In the new table, UserEvents, you would store the UserId's and EventId's like this:
UserEvents
UserId EventId
1 1
2 1
1 2
This means that if you selected UserId 1, the query would return EventId 1 & 2. If you selected EventId 1 the query would return that UserId 1 & 2 would be attending.
This is the standard and recommended way to deal with many-to-many. It's very flexible and can easily be scaled.
You could either use a Compound key (Composite Key) for this table, or create a column specifically as a Primary Key. The code below can be used, and manipulated, to create both your table and Compound/Composite key (I'm guessing on data types).
CREATE TABLE UserEvents
(
[UserId] INT NOT NULL,
[EventId] INT NOT NULL
CONSTRAINT PK_UserEvents PRIMARY KEY NONCLUSTERED ([UserId], [EventId])
)
I would add a third table (e.g. UserEvents) to store which events a user has applied for, along with other relevant attributes (e.g. ApplicationTime, ApplicationStatus). This association would have a foreign key relationship back to the related tables and resolve the many-to-many relationship between users and events.
What you have there is called a "many-to-many" relationship between to tables which can only be resolved by the introduction of a third table between your two tables that stores the associations.
This table would contain the User-ID and the Event-ID as foreign keys (and maybe additional information).

UniqueID and ID

this is my first time working with DB in android. So I figured I would follow this tutorial http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/
As you can see, it makes you create a DB which as both an ID and something called UNIQUE_ID
(there's even a function in PHP which creates a unique identifier)
ID is the primary key
UNIQUE_ID is set as UNIQUE
my question is. why do I need both? which one do I use for foreign keys?. Which is the point of having such a long a complicated ID?
Thanks In advance
The first ID it is the primary key for the table which is mainly a unique counter that updates every time a new row is created. It will keep increasing even if the row gets deleted.
UNIQUE_ID is an identifier created to keep track of users; think of it as if it were a unique username field

Safe number range for my own IDs in dynamic layout?

I am developing an Activity with a fixed and a dynamic layout part. The dynamic part (and thus the number and type of created widgets) is based on database values this way:
For every database row, I will have a group of widgets. And the components of each group depend on the object type (determined from one of the columns) of that database row.
For saving / restoring instance state, all widgets need to have IDs. I would like to ensure that my own IDs will never conflict with IDs that from the generated R class.
For better handling within the app (finding which widget maps to which field in which data object), a numbering scheme like ID = row * 100 + fieldindex would be helpful. Fieldindex is not exactly a colum number. Every object type should have its own fieldindices.
As the ID values in generated R seem not to have consecutive numbers, I can not just predefine a pool of IDs in R and used these without the need of an additional mapping.
Second reason against a predefined pool: The big number of fieldindices would result in a large ID pool. Third, the size of the ID pool would limit the row count that can be displayed.
Is there a safe number range I can use for my own layout component's IDs ?
Looking at R.java in the gen/ folder, I have the impression that generated IDs are all greater than 0x7f000000. Is that guaranteed ?
And if yes, is the range from 0x00000000 up to 0x7f000000 free to use or is it reserved for android's internal purposes ?
Why do you want to avoid the same id? Only thing that necessary is:
An ID need not be unique throughout the entire tree, but it should be unique within the part of the tree you are searching. So, you can use your formula
ID = row * 100 + fieldindex
I will work fine, even if it is not unique in project.

Categories

Resources