I have two tables, SyncedComments and QueuedComments, the latter holds local comments until they are synced with a webserver, when they are synced succesfully they get placed in the synced table, my application should be indifferent to each type. I load in the comments through a CursorLoader, and they may be moved to the synced table while users are reading them. Let's say the user can also edit comments, perhaps while they are being moved, so the application should know where the comment is, regardless of it's table.
To support this, I've thought of having a table with 3 columns, local_id, synced_id and queued_id, the local_id is persistent and simply serves as a reference to either one of the two other id's. When a comment is created a new row is inserted with it's sync_id set to NULL and the queue id it's been given, when a comment is moved then the queue_id is set to NULL and the sync_id is set. This way my application only needs to reference the local id at all times.
How does this solution look? Any flaws? Could it be done smarter?
I would in the first place put all the comments in one table, with flag for whether the comment is synchronized (actually it would probably be ID on server, set to NULL until synchronized and the value obtained from server afterwards). That will take you down to 1 table instead of 3, make it easier to show all comments (because you won't need to do union) and above all avoid problems when the comment is synchronized while being shown, because the comment will not be moving anywhere. And it does less writes to the database file, so it causes less fragmentation and fewer writes to the flash device.
Related
I'm trying to write to a database, in my spec I had to ensure that there are no duplicates for a specific field. Great! I can just make the column unique.
But I have no idea how to deal with that after. If I use the application and accidentally insert a new value which happens to already exist, the app will just crash. How do I check that the value already exists before I try to update the database?
I feel like an if command would work, Buuuuut, How do you scan every value for that column on android anyway?
I assume you propose that we can read all rows in a table, and for each row, check whether the value already exists. If not exist, insert, else, handle conflict.
Another way of doing it is using insertWithOnConflict() method. You can set various conflict resolution strategy such as:
CONFLICT_ABORT
CONFLICT_FAIL
CONFLICT_IGNORE
CONFLICT_NONE
CONFLICT_REPLACE
CONFLICT_ROLLBACK
I don't have any idea on the complexity of this method, but probably it is much better than reading all rows manually and check manually.
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insertWithOnConflict(java.lang.String,%20java.lang.String,%20android.content.ContentValues,%20int)
I currently successfully use a SQLite database which is populated with data from the web. I create an array of values and add these as a row to the database.
Currently to update the database, on starting the activity I clear the database and repopulate it using the data from the web.
Is there an easy method to do one of the following?
A: Only update a row in the table if data has changed (I'm not sure how I could do this unless there was a consistent primary key - what would happen is a new row would be added with the changed data, however there would be no way to know which of the old rows to remove)
B: get all of the rows of data from the web, then empty and fill the database in one go rather than after getting each row
I hope this makes sense. I can provide my code but I don't think it's especially useful for this example.
Context:
On starting the activity, the database is scanned to retrieve values for a different task. However, this takes longer than it needs to because the database is emptied and refilled slowly. Therefore the task can only complete when the database is fully repopulated.
In an ideal world, the database would be scanned and values used for the task, and that database would only be replaced when the complete set of updated data is available.
Your main concern with approach (b) - clearing out all data and slowly repopulating - seems to be that any query between the empty and completion of the refill would need to be refused.
You could simply put the empty/repopulate process in a transaction. Thereby the database will always have data to offer for reading.
Alternatively, if that's not a viable solution, how about appending newer results to the existing ones, but inserted as with an 'active' key set to 0. Then, once the process of adding entries is complete, use a transaction to find and remove currently active entries, and (in the same transaction) update the inactive entries to active.
I am fetching my data with id which is Integer primary key or integer.
But after deleting any row...
After that if we make select query to show all.
But it will give force close because one id is missing.
I want that id can itself take auto increment & decrement.
when i delete a record at the end(i.g. id=7) after this i add a row then id must be 7 not 8. as same when i delete a row in middle(i.g. id=3) then all the row auto specify by acceding.
your idea can help me.
Most systems with auto-incrementing columns keep track of the last value inserted (or the next one to be inserted) and do not ever reissue a number (give the same number twice), even if the last number issued has been removed from the table.
Judging from what you are asking, SQLite is another such system.
If there is any concurrency in the system, then this is risky, but for a single-user, single-app-at-a-time system, you might get away with:
SELECT MAX(id_column) + 1 FROM YourTable
to find the next available value. Depending on how SQLite behaves, you might be able to embed that in the VALUES list of an INSERT statement:
INSERT INTO YourTable(id_column, ...)
VALUES((SELECT MAX(id_column) + 1 FROM YourTable), ...);
That may not work; you may have to do this as two operations. Note that if there is any concurrency, the two statement form is a bad ideaTM. The primary key unique constraint normally prevents disaster, but one of two concurrent statements fails because it tries to insert a value that the other just inserted - so it has to retry and hope for the best. Clearly, a cell phone has less concurrency than, say, a web server so the problem is correspondingly less severe. But be careful.
On the whole, though, it is best to let gaps appear in the sequence without worrying about it. It is usually not necessary to worry about them. If you must worry about gaps, don't let people make them in the first place. Or move an existing row to fill in the gap when you do a delete that creates one. That still leaves deletes at the end creating gaps when new rows are added, which is why it is best to get over the "it must be a contiguous sequence of numbers" mentality. Auto-increment guarantees uniqueness; it does not guarantee contiguity.
So my fundamentals of creating and manipulating databases are a bit messed up. My aim here is that whenever the app is launched, the user is allowed to specify a table name, and whatever data is then collected is put into that table.
However, I'm confused as to how to do this. Do I simply pass the value of a user entered variable as the table name in my contentprovider class and execute sqlite statements to create it?
I've read/reading the documentation already, so if anyone has any insight or clarity, or even better, code snippets, it would be great.
Why not simply use one table, and create a value that stands for the current app-session, and insert that value with each row. This would make your code simpler, and would still allow you to segregate/filter out the values from a particular app-session. If you want to give the user the ability to enter the value (as you are giving them the ability to choose the table name) you'd just want to check to see if that value had already been used, just as you would have to see if the table-name had already been used.
I have a widget that currently takes a random string from an array and sets it to text view on update. The issue here is that the same item can be re-used multiple times in a row due to the string being 'random'
In order to solve this I was going to create a table that held String text, and int viewednum and increment the viewed number each time 'get text' was called. (on update in the widget).
My Question: If I put the insert statements in the widget, won't the data be inserted every time 'on update' is called?
Would it be better for it to go in the DBadapter class somewhere? I'm just unsure about the best way to make sure I don't enter duplicate data. If there is a better alternative like saving a csv file somewhere and using that I'm open to it, it seemed like a sqlite database was the way to go.
Thank you for your time.
That depends on what your onUpdate method does. If each time onUpdate is called it gets a random String from the database, then that would be the place to put it. However, if you are not getting the String during onUpdate, then you should put it in the method where you are accessing your database. I think your confusion is about the purpose of onUpdate. onUpdate doesn't get called every time the user scrolls by the homepage and sees your widget; it gets called regularly on a timescale you specify, and the whole purpose of it is, in a case like yours, to get a new String from the database.
As for your second question, yes, SQlite databases are the way to do it :) I haven't tried saving a csv file or something like that, but I imagine that would be a lot more complex than just using a database.
Declare your database with a UNIQUE constraint on the columns you want to keep unique, then set the desired behaviour via ON CONFLICT in the INSERT statement. ON CONFLICT REPLACE... means the most recent INSERT overwrites. ON CONFLICT IGNORE... keeps the older version.