android sqlite have gap after delete row? - android

I have 4 EditTexts in dataBase
I delete the second one
The database is numbered 1,3,4
I now want it to be renumbered as 1,2,3.
I looked at many solutions
But I could not find a complete answer..
I do not know what should be in writing
I tried the following code .
But it did not happen
db.delete("SQLITE_SEQUENCE","NAME = ?",new String[]{TABLE_NAME});
Does anyone have the full answer ?

In general, this is poor design for a database. An ID should be consistent for a piece of data, regardless of its peers--it should not fluctuate just because another row was deleted.
That being said, you could always use an UPDATE statement to SET ID = ID-1 WHERE ID > (the ID of the row you deleted). This would work. I don't recommend this approach, but you can.

You can recover this space by executing the SQLite VACUUM command.
Call db.execSQL("VACUUM") after delete

Related

Android-SQLite: How to deal with unique values?

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)

Android database search data on EditText TextChange

I am building an android application with a database that contains more than 20,000 entries.
When i retrieve data from the database, especially when searching for data, it seems to be working slow.
Especially, when i search data based on an editText. Every time editText TextChange(), i query :
Select * from mytable where data='mydata'
And it runs slowly.
I really don't know how to make it work faster.
Hope anyone can help me!
You can create an index on just that column to make selection work faster. If your column is the second one in an existing index, this index cannot be used most efficiently.
CREATE INDEX idx_mytable_word ON mytable(word)
May be you initialize db connection every time?
Try to add pagination. it's make your app faster.

SQLite in Android: is there a way to use a limited number of rows in my application, or should I remove them by hand?

I am currently building a database recording events on the phone, but as I don't want to make this a huge database, 100 events are more than enough.
This will keep my database light en efficient.
Unfortunately, I don't see a way to limit the number of rows other than
String sql = "DELETE FROM myTable WHERE _id <= "+limitId;
and I could run this code when the user launch/leaver the app, but I am expecting a better way to achieve this
Is there a more convenient way to achieve this?
If you are using a ContentProvider, you can implement your DELETE in onInsert, deleting a single row on every insert of a single row:
String sql = "DELETE FROM myTable WHERE _id IN (SELECT min(_id) FROM myTable)";
I guess you mean limit to the 100 newest events ?
if so, there is no better way to do it as you did: checking for entries on every insert and delete old entries if necessary.
It's just a matter of taste how or where you do your check, as flx mentioned you could do it in the ContentProvider or as you probably did in the BroadcastReceiver or Service where you actually add the new row. You could also set up a Trigger on your table, but the main idea remains the same. Here a link if you're interested in triggers:
http://www.tutorialspoint.com/sqlite/sqlite_triggers.htm

SQLite, merging two tables based on higher value in a column

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.

Android SQLite ON CONFLICT UPDATE is possible?

I need to solve this problem.
I started my project from the wrong concept that ON CONFLICT REPLACE will do an update of the row content when it finds a conflict. Also I was thinking that in that insert (with the conflict) if I don't put a value for a column it wont do the replace but keep the old value. Instead I just discovered that the ON CONFLICT REPLACE if it finds a conflict it will do a delete->insert and if it can't find a value for a column (where I put null for not updating the field) it will replace the null value with the default column value in order to make successfully the insert.
So know I have this big root problem :D
As you understand what I want to reach is this:
I always do the insert, if it finds already a row with the same unique keys (conflict) it will only update the values. If for a field it wont find the values ( I don't put it in the ContentValues ) it wont update those field but keep the old one (like a normal update query where you don't put a column for update it).
To solve my problem I tought these solutions:
ON CONFLICT UPDATE (this will only work when you have only 1 unique
fields, if you have 2 or more unique fields that throw the conflict
it will crash)
UPDATE ON FAIL INSERT where it always try to do an update. If it fails because it can't find the row related to the record (it's not yet present in the db) it will try to do an insert
Some one has already thought about this problem and has a solution?
Or maybe we can just try to find a solution :)
I think that the best way is to keep things on low level (db level) in order to keep a good level of performance.
Following SQLite3 official Documentation is not possible to automatically do a ON CONFLICT UPDATE but only a REPLACE that is like DELETE -> INSERT (new values).

Categories

Resources