Anyone know of a way to limit the number of rows deleted when using an sql DELETE statement?I just need to delete a row that holds a certain value one time instead of deleting every instance of the value. It's my understanding that the LIMIT clause cannot be added to DELETE statements in SQLITE. Now, I can't see a way to limit the number of rows deleted just using _id because I don't know what row _id will be deleted ahead of time; the rows are being deleted based on a value held in a variable and they could be anywhere in the DB. I hope this makes sense. Here's the delete statement:
String sql = "DELETE FROM strategyTotal WHERE strategy_prices = (?)" ;
db.execSQL(sql, new Double[] {subtractedStrategyPrice });
Use a subquery:
String sql = "DELETE FROM strategyTotal WHERE _id IN (SELECT _id FROM strategyTotal WHERE strategy_prices = (?) LIMIT 1);" ;
db.execSQL(sql, new Double[] {subtractedStrategyPrice });
delete from tablename where rowid in (
select rowid from tablename condition LIMIT 1)
try above work around or you may need to enable SQLITE ENABLE UPDATE DELETE LIMIT
my query is just an example. replace it with your own query.
Related
Scenario is like
Before inserting into sqlite db I have to check whether is it reached a particular number, say 10. I know it can be done by using 2 queries for get and insert.
Can it be done in 1 query in android and sqlite
INSERT INTO Customers (name, age)
SELECT 'MM', 20 WHERE (SELECT count(*) from Customers) < 10;
By use this query, we only insert new customer to database when total customers in database < 10
Considering the documentation for INSERT you can also insert a result of a select statement. So instead of inserting the values directly, you could assemble a select statement to only return your default values with coalesce if and only if a condition for the count yields true.
This is mostly an idea and theoretical approach, but worth trying.
To check how many rows in database, you need to make
select * from
query and get the cursor object. Cursor object have getCount method which return you size of cursor, its simply means to show all your records in table.
Cheers!!!
I'm using sugar orm for a high scores database, and after a lot of searching(because the documentation is very pure and also some links are dead), I've managed to save and list the records from the database. Unfortunately I cannot find out how to delete the duplicated score records, or how to update a record instead of saving a new one in case the name and high score values are the same.
I found that this can be done with something like this:
getWritableDatabase().execSQL("delete from highscores where _id not in (SELECT MIN(_id ) FROM highscores GROUP BY highscores_id)");
}
but how can I do it with sugar orm in which I don't know if it even has a id field or its name ?
UPDATE:
Following #Juancortes' s advice I'm trying to check for the current player, if the current score exists in database, before add the record:
private void saveScore(){
int total;
total=checkList();
if(total>0) {
HighScoresDB highScores = new HighScoresDB(tvPlName.getText().toString(), total);
highScores.save();
}
}
private int checkList(){
String tempName=tvPlName.getText().toString();
List<HighScoresDB> check = HighScoresDB.find(HighScoresDB.class, "person = ?",tempName);
ArrayList<Integer> templist = new ArrayList<Integer>();
for(int i=0;i<check.size();i++){
templist.add(check.get(i).score);
}
int total = Integer.valueOf(totalPts.getText().toString());
if(templist.contains(total)) {
total = 0;
}else{
total=Integer.valueOf(totalPts.getText().toString());
}
return total;
}
I get a list with the existing records for current player using sugar orm. After I'm checking if the list contain the current score value, and if is true I set it to "0". Then in "saveScore()" method I save a record only if the score value is greater that "0". But this doesn't work and I keep getting double, triple etc records. What I'm doing wrong?
UPDATE 2:
Seems that "contains" doesn't work for the list with the database objects directly. So I created an ArrayList with only the scores(code updated too), and I used that list to check if the total exists. Now seems that works fine and don't created double records.
A little late, but you can use the executeQuery() method for a raw custom query. Here is an example of a query that will remove duplicates:
DELETE tableName FROM tableName LEFT OUTER JOIN(
SELECT MIN(table_primary_key) AS rowId, col1, col2, col3
FROM tableName
GROUP BY col1, col2, col3
) as KeepRows ON tableName.table_primary_key = KeepRows.rowId
WHERE KeepRows.rowId IS NULL
Compares all the rows, finds any duplicates, deletes them.
This will execute in SQL without having to pull back all the records, though you can modify it to a SELECT and then use the SugarORM delete functionality. That will increase memory usage though.
How can I create a insert trigger in sqlite? I should check if the number of rows is < 5 = ok. If the number of rows is 5 = delete first row.
Is this way of collecting garbage efficient?
The documentation is quite good: http://www.sqlite.org/lang_createtrigger.html
You should end up with something like
CREATE TRIGGER rowlimit5
AFTER INSERT ON table
BEGIN
DELETE FROM table WHERE ROWID NOT IN (
SELECT ROWID FROM table ORDER BY ROWID DESC LIMIT 5
);
END;
I have a table which has columns
_id = Primary Key Auto Increment
Title = String
timestamp = long
I have 35 entries in my table. My table can contain only 25 entries at any given time. So that means have of knock off 10 extra entries from my table.
Also 35 entries should be first sorted by timestamp and the last 10 entries should deleted so that i have just 25 recent entries.
Can some please help me with a delete query that first sorts the entries by timestamp and keeps only 25 entries, deleting the rest.
DELETE FROM MYTABLE WHERE _id NOT IN
(SELECT _id from MYTABLE ORDER BY timestamp DESC LIMIT 25)
Keeps the latest 25 entries.
It sounds like you need a FIFO queue in SQL. A table that only stores the most recent 25 (or any other number of) items.
If so, then here is a solution:
http://www.xaprb.com/blog/2007/01/11/how-to-implement-a-queue-in-sql/
Alternative to radashk method:
You can delete one (oldest) record every time you insert a new record, it can be done in DB table trigger on insert:
DELETE FROM MYTABLE WHERE timestamp = MIN(timestamp);
this statement can be wrapped in record count check or something else to make sure that you maintain your minimum record count.
I use this method to delete a row in my sqlite db:
db.execSQL("delete from "+TABLE_NUMS+" where _ID = '" + this.rowID + "'");
and then I update the rest of Ids to make my entries consecutive:
db.execSQL("UPDATE "+TABLE_NUMS+" set _ID = (_ID - 1) WHERE _ID > "+this.rowID);
And it works fine, but when I add new entries to my DB, the ID of the new entries still add as if the deleted entries existed, say I have 10 rows with IDs starting from 1 to 10, and then I delete number 5 and 6, the rows become 1 to 8, but the new entry's ID will be 11. So my IDs sequence would be 1 to 8 and 11. How can I fix this?
SQLite keeps track of the largest ROWID that a table has ever held using the special SQLITE_SEQUENCE table. You cam modify that sequence as:
UPDATE SQLITE_SEQUENCE SET seq = this.ID -1 WHERE name = TABLE_NUMS
The same functionality is asked in this question.
The normal ROWID selection algorithm described above will generate
monotonically increasing unique ROWIDs as long as you never use the
maximum ROWID value and you never delete the entry in the table with
the largest ROWID. If you ever delete rows or if you ever create a row
with the maximum possible ROWID, then ROWIDs from previously deleted
rows might be reused when creating new rows and newly created ROWIDs
might not be in strictly ascending order.
http://www.sqlite.org/autoinc.html
This is how SQLite works.
If you really need to have the Ids consecutive don't use autoincrement.
Insert the ids yourself.
You can select MAX(_ID) first to get the last id (greatest value).
This is because you have autoincrement set on _ID when you created the table. So, every row you add will be given a number automatically unless you explicitly set it. If it is absolutely necessary that you need the _IDs in consecutive order, I recommend that you set it yourself instead of using autoincrement.
Here is how to reset it:
delete from your_table;
delete from sqlite_sequence where name='your_table';
This will delete all your data and reset the sequence.
SQLite keeps the largest ROWID in the special SQLITE_SEQUENCE table. You can update that table as:
db.execSQL("UPDATE SQLITE_SEQUENCE SET seq = 0 WHERE NAME = '"+TABLE_NAME+"'");
OR
delete that table as:
db.delete("SQLITE_SEQUENCE","NAME = ?",new String[]{TABLE_NAME});