I write app on android which will use android SQLite database. I have table which will contain data rows with unique Id. From time to time I need to add new row or update old row. For now I when I want to add/update data I must check if I have row with specified Id in table. If I have I update suitable row. If I dont I create new row with new unique key. My question is: is there something in Android what can automagically check if in database is row with specified id and then just update it and if there isnt such row add new?
Check out the SQLite documentation for the insert statement. You can use a insert or replace statement (or just replace, which is a shortcut).
You use it just like you would a traditional insert statement. This is probably useful in your case since you already have the key known.
Related
I have table that for the specified rows with specified ids need to change the value, while for previously selected rows should be reset.
Do I need to reset the whole table and then update for specified rows. is there any option to update table with only one query.
I'm using room persistence on android
Like any database standard, Room Update and Delete are separate operation types.
Then maybe you can try to execute Trigger if you need mixed operation (thread about trigger).
But for what reason do you have to execute this two operations in a same query ?
I have been struggling with the update of only 1 row in an SQlite databasetable.
Although I provided the _id value of the row that I wanted to update in the ContentUris.withAppendedId Uri, I still have to check in the 'WHERE'-part of the update statement whether the id of the record is the same.
When I leave the 'WHERE'-part of the update statement to 'null', the update statement tries to update ALL rows of the table instead of only the row with the id that was provided.
URIs define a resource. They do not define what operations can be made on that resource.
With regards to a ContentProvider (since you've included that in the tags for your question), you need to consider that the app with the ContentProvider and the app that wishes to access or modify its data may not be the same app. If you are implementing a ContentProvider, you would need to recognize URI of the kind you mentioned and adjust the WHERE clause accordingly, assuming you support that operation on that resource.
The other use for this is with insert operations, where the typical thing to return is a URI for the item that was just inserted. E.g. a successful insert on the URI content://authority/directory would return something like content://authority/directory/_id, where _id is the ID of the newly inserted row.
I am working on an android application using android:minSdkVersion="14". The application receives data as JSON from a server. The data received need to be added to an sqlite table. If a row exists, all fields except for two have to be updated. If a row does not already exist in the table, it has to be inserted. I am looking for the most efficient way as regards performance.
The function insertwithonCoflict() has been considered but it is not an option since in case of update, it updates all the fields including the two that should not be updated.
The function replace() is also not suitable.
I would opt for a SELECT to check if the row exists and then an INSERT or UPDATE but I was wondering if I could optimize the procedure somehow .
Two approaches:
Change the database structure so that the table has only the server data. Put local data (the two columns) in another table that references the server data table. When updating, just insert to the server data table with "replace" conflict resolution.
Do the select-insert/update logic.
For performance in any case, use database transactions to reduce I/O. That is, wrap the database update loop in a transaction and only commit it when you've done with everything. (In case the transaction becomes too large, split the loop into transaction chunks of maybe a few thousand rows.)
A nice solution I use is as follows:
long id = db.insertWithOnConflict(TABLE, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE);
if(id!=-1) db.update(TABLE, contentValues, "_id=?", new String[]{String.valueOf(id)});
This ensures the row exists and has the latest values.
I've got two SQLite databases, each with a table that I need to keep synchronized by merging rows that have the same key. The tables are laid out like this:
CREATE TABLE titles ( name TEXT PRIMARY KEY,
chapter TEXT ,
page INTEGER DEFAULT 1 ,
updated INTEGER DEFAULT 0 );
I want to be able to run the same commands on each of the two tables, with the result that for pairs of rows with the same name, whichever row has the greater value in updated will overwrite the other row completely, and rows which do not have a match are copied across, so both tables are identical when finished.
This is for an Android app, so I could feasibly do the comparisons in Java, but I'd prefer an SQLite solution if possible. I'm not very experienced with SQL, so the more explanation you can give, the more it'll help.
EDIT
To clarify: I need something I can execute at an arbitrary time, to be invoked by other code. One of the two databases is not always present, and may not be completely intact when operations on the other occur, so I don't think a trigger will work.
Assuming that you have attached the other database to your main database:
ATTACH '/some/where/.../the/other/db-file' AS other;
you can first delete all records that are to be overwritten because their updated field is smaller than the corresponding updated field in the other table:
DELETE FROM main.titles
WHERE updated < (SELECT updated
FROM other.titles
WHERE other.titles.name = main.titles.name);
and then copy all newer and missing records:
INSERT INTO main.titles
SELECT * FROM other.titles
WHERE name NOT IN (SELECT name
FROM main.titles);
To update in the other direction, exchange the main/other database names.
For this, you can use a trigger.
i.e.
CREATE TRIGGER sync_trigger
AFTER INSERT OR UPDATE OF updated ON titles
REFERENCING NEW AS n
FOR EACH ROW
DECLARE updated_match;
DECLARE prime_name;
DECLARE max_updated;
BEGIN
SET prime_name = n.name;
ATTACH database2name AS db2;
SELECT updated
INTO updated_match
FROM db2.titles t
WHERE t.name=prime_name)
IF updated_match is not null THEN
IF n.updated > updated_match THEN
SET max_updated=n.updated;
ELSE
SET max_updated=updated_match;
END IF;
UPDATE titles
SET updated=max_updated
WHERE name=prime_name;
UPDATE db2.titles
SET updated=max_updated
WHERE name=prime_name;
END IF;
END sync_trigger;
The syntax may be a little off. I don't use triggers all that often and this is a fairly complex one, but it should give you an idea of where to start at least. You will need to assign this to one database, exchanging "database2name" for the other database's name and then assign it again to the other database, swapping the "database2name" out for the other database.
Hope this helps.
I made SQLite database table that stores records, is it possible to change some values
that stored inside the table without deleting and entering updated values with older one.
e.g.
Lets say I want to change the wage of row ID = 0 to from 23$ to 40$ without deleting
the first row and reinserting making the auto incremented ID change to 1,
is to possible?!
Yes, you should use an UPDATE statement.
Yes, check out the UPDATE syntax of SQLite.