How should i get most recent added record from database, where COL_2 should == param that I pass into it.
I can get all records where COL_2 is equal to param with this code, but I need only recent one
public Cursor getRowsLast(String param) {
SQLiteDatabase db = helper.getWritableDatabase();
String[] COLS = new String[]{DatabaseHelper.COL_1,DatabaseHelper.COL_2, DatabaseHelper.COL_3,DatabaseHelper.COL_4};
String where = param;
Cursor c = db.query(true, DatabaseHelper.TABLE_NAME, COLS, DatabaseHelper.COL_2 + " = '" + where + "'", null, null, null, null, null);
if(c != null){
c.moveToFirst();
}
return c;
}
The most reliable way to get the most recent row in a table is to have a column defined in the table for the time of insert/update. Make sure this value is accurate at the time of insert/update, and create an index on it. You can then sort (descending) on this column to determine which one is the most recent - it will be the first row.
As the automatically generated ID values increase with every insert, the row with the highest ID will be the one that was inserted most recently. So add an 'order by _id desc' and the first row will be the most recently inserted one.
Note - this does not cover updates. If you need the row most recently inserted or updated, you'll have to use an additional timestamp column like Doug Stevenson suggested.
Related
I've a situation in sqlite that make you an example: My table has two fields,"_id" and "_score" . I have a record with _id=1, _score=10. I want to update this row to 5 number more than the current value(10). in SQL i can do it simple like:
Update my_table set _score = _score + 5 where _id = 1
but in sqlite I have these that I don't know how can fix it to what I want :
ContentValues values = new ContentValues();
values.put("_score", my_value);
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
int id = db.update(MY_TABLE,values,"_id = ?",new String[]{String.valueOf(my_id)});
and the Other problem is the returned value. I think in above example I give
id = 1
for 1 row effected. but I want to know that: Is there any way to retrieve the value of updated column(in my example I want to give "15"). Some thing like in SQL server that we fetch from
"##ROWCOUNT" or "##fetch_status"
Hope to describe it well. thanks.
Android's update() function can set only fixed values.
To execute your SQL statement, you have to use execSQL():
db.execSQL("Update my_table set _score = _score + 5 where _id = 1");
In SQLite, the UPDATE statement does not return any data (except the count of affected rows). To get the old or new data, you have to execute a SELECT separately.
For your first problem about updating the score value try this:
ContentValues values = new ContentValues();
values.put("_score", my_value);
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
int id = db.update(my_table, values, _id + " = ?",
new String[] { String.valueOf(my_id) });
}
I wont to update a single cell of a row in the database. However the row contains of 5 columns so and i would like to not passing all the other values as well as they should remain the same.
I have this code snippet:
Cursor cursor = db.query(STATION_TABLE, null, null, null, null, null, null);
//If the database already include some stations.
if(cursor.moveToFirst())
{
ContentValues stationValues = new ContentValues();
for(StopLocation station: stations)
{
stationValues.clear();
//The database already includes the station
if(cursor.getString(POS_STA_ID).equals(station.getId()))
{
values.put(KEY_STA_DISTANCE, "null");
db.update(STATION_TABLE, stationValues, KEY_STA_ID + "=?", new String[]{station.getId()});
}
The db.update method throws this exception:
java.lang.IllegalArgumentException: Empty values
Any ideas on how to solve this?
If I understand the question correctly and assuming you are always dealing with one row, there are two possible ways to approach this:
First:
Get the values of all fields in the entire row, and declare them as content values before updating:
ContentValues cv = new ContentValues();
cv.put("Field1","123");
cv.put("Field2","True")
Second:
Use execSQL() method:
String strSQL = "UPDATE your_table SET Field1 = foo WHERE POST_STA_ID = "+ station.getId();
myDataBase.execSQL(strSQL);
This is what i am using for insert:
public long insert(String content, Date startAt, Date endAt) {
if (content == null || startAt == null) {
return 0;
}
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_CONTENT, content);
contentValues.put(KEY_START_AT, startAt.getTime());
if (endAt == null) {
contentValues.putNull(KEY_END_AT);
} else {
contentValues.put(KEY_END_AT, endAt.getTime());
}
return sqLiteDatabase.insert(TABLE_NAME, null, contentValues);
}
now i want to create update method which will update last inserted row. How can i get last inserted row?
If you have an id attribute that works as a primary key, you can do a raw database query on SqlLite.
Cursor cc = this.mDb.rawQuery("SELECT *" + " FROM " + "<Your DATABASE_NAME> " +
"ORDER BY id " + "DESC LIMIT 1", null);
return cc;
Here,
1. It returns a cursor.
2. mDb is a SQLiteDatabase class instance.
3. ORDER BY id allows the query to sort by id number. As I said, if you have an id as primary key in your table, your latest entry will have the maximum id number.
4. DESC allows to sort by descending order.
5. LIMIT 1 allows to return only 1 row.
6. Always be careful when writing raw queries, white spaces inside the query can be a lot of pain when you do not handle them carefully.
For further queries you can see this tutorial. And obviously Divya's answer is also a good one.
You can use a cursor to retrieve rows and say :
cursor.moveToLast();
OR
cursor.moveToPosition(cursor.getCount() - 1);
When you insert a row in to your table the insert query returns the key of the last inserted row. You can now use this key to update this row.
for example
int newInsertedKey = sqLiteDatabase.insert(TABLE_NAME, null, contentValues);
update table_name set column_name = 'Change 2' where columnID = newInsertedKey
An efficient method would be to avoid anymore database queries to get the last updated row.
Maybe he should use something like this
public long getLastId() {
Cursor c = mDb.query(currentTableName, new String[] { "MAX(_id)" },
null, null, null, null, null, null);
try{
c.moveToFirst();
long id = c.getLong(0);
return id;
}catch(Exception e){
return 0;
}
}
where _id is column by which you identify rows
I have an issue with SQLite on android. Right now, I'm pulling a JSON object from a server, parsing it, and putting each sub-object in a Table with things such as the Name, Row_ID, unique ID, etc. using this code:
public void fillTable(Object[] detailedList){
for(int i=0;i<detailedList.length;++i){
Log.w("MyApp", "Creating Entry: " + Integer.toString(i));
String[] article = (String[]) detailedList[i];
createEntry(article[0], article[1], article[2], article[3], article[4], article[5]);
}
}
createEntry does what it sounds like. It takes 6 strings, and uses cv.put to make an entry. No problems.
When I try to order them however, via:
public String[] getAllTitles(int m){
Log.w("MyApp", "getTitle1");
String[] columns = new String[]{KEY_ROWID, KEY_URLID, KEY_URL, KEY_TITLE, KEY_TIME, KEY_TAGS, KEY_STATE};
Log.w("MyApp", "getTitle2");
Cursor c = ourDatabase.query(DATABASE_TABLENAME, columns, null, null, null, null, KEY_TIME);
Log.w("MyApp", "getTitle3");
String title[] = new String[m];
Log.w("MyApp", "getTitle4");
int i = 0;
int rowTitle = c.getColumnIndex(KEY_TITLE);
Log.w("MyApp", "getTitle5");
for(c.moveToFirst();i<m;c.moveToNext()){
title[i++] = c.getString(rowTitle);
Log.w("MyApp", "getTitle " + Integer.toString(i));
}
return title;
}
Each entry actually has many duplicates. I'm assuming as many duplicates as times I have synced. Is there any way to manually call the onUpgrade method, which drops the table and creates a new one, or a better way to clear out duplicates?
Secondary question, is there any way to order by reverse? I'm ordering by time now, and the oldest added entries are first (smallest number). Is there a reverse to that?
If you don't want duplicates in one column then create that column with the UNIQUE keyword. Your database will then check that you don't insert duplicates and you can even specify what should happen in that case. I guess this would be good for you:
CREATE TABLE mytable (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
theone TEXT UNIQUE ON CONFLICT REPLACE
)
If you insert something into that table that already exists it will delete the row that already has that item and inserts your new row then. That also means that the replaced row gets a new _id (because _id is set to automatically grow - you must not insert that id yourself or it will not work)
Your second question: you can specify the direction of the order of if you append ASC (ascending) or DESC (descending). You want DESC probably.
Cursor c = ourDatabase.query(DATABASE_TABLENAME, columns, null, null, null, null, KEY_TIME + " DESC");
I am upgrading my database to add another column. What I am trying to do is (after the column is added in onUpgrade) this method is called from the main activity for each table (3 were upgraded). The method is supposed to replace all of the blanks in the new column with "1".
The code runs fine, stepping through, boolean test is true every time but when I open the table to view the data, the entire column is blank. The weird part is, my rowId numbers are incrementing every time. It starts out with 3 rows with rowIds of 1,2,3 respectively. After my code runs once, they now have rowIds of 4,5,6 respectively.
Can anyone help me out? KEY_ROWID is just my auto rowId number. KEY_MODE is just "mode" for column title. If I run through debugging it, the three rows I have show up in the code (it runs through the while loop 3 times).
public void checkBlanks(String table) {
Cursor cursor = mDb.query(table, new String[] {KEY_ROWID, KEY_MODE}, null, null, null, null, null);
while (cursor.moveToNext()) {
int modeCol = cursor.getColumnIndexOrThrow(KEY_MODE);
if (cursor.isNull(modeCol)) {
int rowId = cursor.getInt(cursor.getColumnIndexOrThrow(KEY_ROWID));
ContentValues args = new ContentValues();
args.put(KEY_MODE, 1); // replace the blank space with a "1"
boolean test = mDb.update(table, args, KEY_ROWID + "=" + rowId, null) > 0;
}
}
cursor.close();
}
Instead of manually looping through the rows, why don't you just leverage the power of SQL and update ALL of the rows in one call? E.g.
mDb.execSQL("UPDATE " + table + " SET " + KEY_MODE + " = 1;");
Since it's so simple, you can do this right in your onUpgrade() method.
You could have done that much easier:
1.) During onUpgrade(): "add column newcolumn default 1". This would add a new column with all newcolumns containing 1.
2.) onUpgrade() is already run: update table set newcolumn=1: Without a WHERE clause the whole table is affected.
There's not need to walk thru all rows.
What you want to do requires an SELECT...FOR UPDATE OF/UPDATE...WHERE CURRENT OF. I didn't do that with SQLite, so I don't know if this is supported.
In your situation (onUpgrade is already run) use 2.)