I want to get the last inserted row's primary key value which is set automatically(AUTO INCREMENT). I searched over the S/O and found answers for last row_id. But I need the last inserted row's values. Please help me.
Thanks
Try this code
String selectQuery = "SELECT * FROM " + "sqlite_sequence";
Cursor cursor = db.rawQuery(selectQuery, null);
cursor.moveToLast();
or
SELECT *
FROM TABLE
WHERE ID = (SELECT MAX(ID) FROM TABLE);
or
SELECT * FROM table ORDER BY column DESC LIMIT 1;
try this :
select * from <TABLE> where row_id = (select max(row_id) from <TABLE>);
or
SELECT * FROM tablename ORDER BY row_id DESC LIMIT 1;
Use moveToLast() in Cursor interface.
From android.googlesource.com
/**
* Move the cursor to the last row.
*
* <p>This method will return false if the cursor is empty.
*
* #return whether the move succeeded.
*/
boolean moveToLast();
Simple example:
final static String TABLE_NAME = "table_name";
String name;
//....
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
if(cursor.moveToLast()){
name = cursor.getString(column_index);
//--get other cols values
}
If you want to get data when insert, you can use insert() in SQLiteDatabase class.
private static final String TABLE_NAME = "table_name";
private static final String COLUMN_ONE = "ID";
private static final String COLUMN_TWO = "NAME";
long row = 0;//to get last row
//.....
SQLiteDatabase db= this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_TWO, name);//name is a variable for data value
row = db.insert(TABLE_NAME, null, contentValues);
//insert() returns the row ID of the newly inserted row, or -1 if an error occurred
Cursor res = db.rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE ID = ?", new String[] { row+"" });
while (res.moveToNext()) {//there is no need to use while, if condition is good.
System.out.println(res.getString(0));//I just sout to avoid more code.
System.out.println(res.getString(1));
}
This is post is about autoincrement, if you want to read.
Related
I have a recyclerview cardholder that inflates using the values of 'NAME' from the table 'ORDERTABLE'. The cardholder also have an EditText which displays the values of column 'QUANTITY' in my SQLite database.
I also have a button to update the database for every changes in EditText.
I have this table ORDERTABLE
id NAME QUANTITY
1 Order1 1
2 Order2 1
3 Order3 1
4 Order4 1
Being more specific, how can i update the QUANTITY of Order2 on onButtonPressed with the new values of my EditText.
EDIT...
I have tried this code but nothing happened
Button to update values
public void addButtonClick(TextView tv_cardrowName_atc, TextView tv_currentPrice_atc, EditText et_quantity_atc, int position) {
int thisQuantity = Integer.parseInt(et_quantity_atc.getText().toString());
thisQuantity++;
String orderName = tv_cardrowName_atc.getText().toString();
String oldQuantity = et_quantity_atc.getText().toString();
String newQuantity = String.valueOf(thisQuantity);
sqliteCBLCAdapter.selectUpdateItem(orderName, oldQuantity, newQuantity);
et_quantity_atc.setText(String.valueOf(thisQuantity));
}
Update Method
public String selectUpdateItem(String orderName, String oldQuantity, String newQuantity) {
SQLiteDatabase sqLiteDatabase = sqLiteCBLC.getWritableDatabase();
String[] columns = {SQLiteCBLC.COL_ORDNAME, SQLiteCBLC.COL_QUANTITY};
Cursor cursor = sqLiteDatabase.query(SQLiteCBLC.TABLE_NAME, columns, SQLiteCBLC.COL_ORDNAME + " = '" + orderName + "'", null, null, null, null);
StringBuffer stringBuffer = new StringBuffer();
while (cursor.moveToNext()) {
int index1 = cursor.getColumnIndex(SQLiteCBLC.COL_ORDNAME);
int index2 = cursor.getColumnIndex(SQLiteCBLC.COL_QUANTITY);
String order = cursor.getString(index1);
String quantity = cursor.getString(index2);
ContentValues contentValues = new ContentValues();
contentValues.put(SQLiteCBLC.COL_QUANTITY, newQuantity);
String[] whereArgs = {quantity};
sqLiteDatabase.update(SQLiteCBLC.TABLE_NAME, contentValues, SQLiteCBLC.COL_QUANTITY + " =? ", whereArgs);
stringBuffer.append(order);
}
return stringBuffer.toString();
}
The easiest way for you to achieve this would be to use a SQL update query as follows:
From the SQLite Web Site:
The SQLite UPDATE Query is used to modify the existing records in a table. You can use a WHERE clause with UPDATE query to update selected rows, otherwise all the rows would be updated.
The syntax for the update query is as follows:
UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];
So in your case your sql update query would look some thing like this:
UPDATE ORDERTABLE SET QUANTITY = (INSERT VALUE OF YOUR EDIT TEXT) WHERE NAME = 'Order2'
You can then execute your query by using the execSQL() method of your SQLiteDatabase object that you have and passing in the sql query above as the string parameter.
You can try like this below code, In your case you while updating you are updating based on quantity, multiple order will have the same quantity. just check the order name and update it.
public void selectUpdateItem(String orderName, String oldQuantity, String newQuantity) {
if (TextUtils.isEmpty(order)) {
return;
}
ContentValues contentValues = new ContentValues();
final String whereClause = SQLiteCBLC.COL_ORDNAME + " =?";
final String[] whereArgs = {
orderName
};
// if you want to update with respect of quantity too. try this where and whereArgs below
//final String whereClause = SQLiteCBLC.COL_ORDNAME + " =? AND " + SQLiteCBLC.COL_QUANTITY + " =?";
//final String[] whereArgs = {
//orderName, String.valueOf(oldQuantity)
//};
contentValues.put(SQLiteCBLC.COL_QUANTITY, newQuantity);
SQLiteDatabase sqLiteDatabase = sqLiteCBLC.getWritableDatabase();
sqLiteDatabase.update(SQLiteCBLC.TABLE_NAME, contentValues,
whereClause, whereArgs);
}
I am developing an application where the user inputs title and the date. I want to prevent the duplicated titles being inputted on the same day in to database. I am checking if the title exists on the selected date. However my query seems not to work and i don't know why, the application just crashes.Is this query correct? Can someone help?
public boolean checkExist(String title, String date) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
boolean exists = c.moveToFirst();
c.close();
return exists;
}
One issue that you have is that c.moveToFirst will always fail if a match does not exist as you are trying to move to a row in an empty cursor.
The resolution is to not use c.moveToFirst and instead get the count of the rows and then set the return value accordingly.
e.g.
public boolean checkExist(String title, String date) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
boolean exists = c.getCount() > 0;
c.close();
return exists;
}
The second issue is that the query itself is wrong as you do not have spaces either side of the AND keyword. That is instead of
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +"AND" + DATE+"=?", new String[] {title,date});
You should have
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+TITLE+"=?" +" AND " + DATE+"=?", new String[] {title,date});
Personally, I setup constants for SQL keywords that include the space and then use these. So I'd have something along the lines of +TITLE+"=?" + SQLAND + DATE+"=?". Where SQLAND would be defined along the lines of String SQLAND=" AND ";
PS look at Cricket_007's answer, the code is neater/better it's easier to read.
Your spacing is off. TITLE+"=?" +"AND" + DATE becomes TITLE=?ANDDATE=?
I would suggest this. See DatabaseUtils.queryNumEntries
public boolean checkExist(String title, String date) {
SQLiteDatabase db = getReadableDatabase();
String[] args = new String[] {title,date};
String filter = String.format("%s=? AND %s=?", TITLE, DATE);
return DatabaseUtils.queryNumEntries(db, TABLE_NAME, filter, args) > 0;
}
you should be using c.getCount() instead of c.moveToFirst()
if the value is greater than 0, then it exists
I have the following code in a bigger project:
final class DBlifetimeStatisticsHandler{ //implements DBvalueHandler<Cyclist, Double>{
private final String TAG = getClass().getName();
private static final boolean debug = true;
private final DBminMaxAvgHandler dbMinMaxAvgHandler = new DBminMaxAvgHandler();
// table name
private static final String TABLE_LIFETIME_STATISTICS = "lifetime_statistics";
// column names
private static final String KEY_LIFETIME_STATISTICS_ID = "lifetime_statistics_id";
private static final String KEY_MIN_MAX_AVG = "min_max_avg";
// table create statement
private static final String CREATE_TABLE = "CREATE TABLE "
+ TABLE_LIFETIME_STATISTICS + "("
+ KEY_LIFETIME_STATISTICS_ID + " LONG PRIMARY KEY NOT NULL,"
+ KEY_MIN_MAX_AVG + " LONG"
+ ")";
public void onCreateTable(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
public void onUpgrade(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LIFETIME_STATISTICS);
onCreateTable(db);
}
public long addValue(SQLiteDatabase db, Statistics Statistics ) {
ContentValues values = new ContentValues();
long ID = getLatestID(db)+1;
values.put(KEY_STATISTICS_ID, ID);
... //not important to the question
}
private long getLatestID(SQLiteDatabase db){
String selectQuery = "SELECT MAX(" + KEY_STATISTICS_ID +") FROM " + TABLE_STATISTICS;
Cursor c = db.rawQuery(selectQuery, null);
c.moveToFirst();
int id = 0;
Log.e("count", String.valueOf(c.getCount()));
if (c.moveToFirst()){
...
}
return id;
}
}
After I updated the table it is created again. So when I try to add a new value I had problems cause it always jumped into the if clause because c.moveToFirst() always returned true.
So I tried to tried to check if c.getCount() would return true but sadly it does always return 1. So the question is: Why would it return 1 on an empty table? (I do use Questoid SQLite Browser and the table is really empty)
You use aggregate function MAX, so read documentation:
There are two types of simple SELECT statement - aggregate and non-aggregate queries. A simple SELECT statement is an aggregate query if it contains either a GROUP BY clause or one or more aggregate functions in the result-set.
An aggregate query without a GROUP BY clause always returns exactly one row of data, even if there are zero rows of input data.
It might be some kind of a buggy behavior when using MAX. Check this link too Android database (SQLite) returns a non-empty cursor from an empty table
this is my solution
public Boolean isNotEmpty(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_STATISTICS, null);
while (cursor.moveToNext() ) {
return true;
}
return false;
}
You are getting a result with one row in your Cursor because that is what you requested.
The result is a single column called MAX with a value that will be the max id of all the rows in your table. In your case of an empty table, this value is null.
I am using group by to resolve this. Please check my example :
SELECT COUNT(*) FROM " + TABLE_NAME + " WHERE isSynced=0 group by isSynced
I resolve this probme this way:
SELECT COUNT(*) AS numero, MAX(tagua_lagps) as tmp_max_lagps, MAX(tagua_logps) as tmp_max_logps, MIN(tagua_lagps) as tmp_min_lagps, MIN(tagua_logps) as tmp_min_logps FROM TAB_AGUA
On empty table, c.getCount(); gives 1 but values are NULL. But numero (c.getString(c.getColumnIndex("numero")) has a value of 0.
So rather than checking c.getCount() you must check the result of count(*).
Using the typical SQLiteDatabase object in Android's API, what can I do to get the next AUTO_INCREMENT value of a particular column (ie. id) without affecting the value itself. Is there a method for that? Or what query should I execute to get that result. Keep in mind that SQLiteDatabase.query() returns a Cursor object, so I'm not too sure how to deal with that directly if I just want to get a value out of it.
You're right. The first answer (still below) only works without an AUTOINCREMENT for id. With AUTOINCREMENT, the values are stored in a separate table and used for the increment. Here's an example of finding the value:
public void printAutoIncrements(){
String query = "SELECT * FROM SQLITE_SEQUENCE";
Cursor cursor = mDb.rawQuery(query, null);
if (cursor.moveToFirst()){
do{
System.out.println("tableName: " +cursor.getString(cursor.getColumnIndex("name")));
System.out.println("autoInc: " + cursor.getString(cursor.getColumnIndex("seq")));
}while (cursor.moveToNext());
}
cursor.close();
}
See: http://www.sqlite.org/autoinc.html
First Answer:
You can query for the max of the _id column, such as:
String query = "SELECT MAX(id) AS max_id FROM mytable";
Cursor cursor = db.rawQuery(query, null);
int id = 0;
if (cursor.moveToFirst())
{
do
{
id = cursor.getInt(0);
} while(cursor.moveToNext());
}
return id;
This works for row ids that haven't been specified as "INTEGER PRIMARY KEY AUTOINCREMENT" (all tables have a row id column).
This is the best way to get the last ID on auto increment PRIMARY KEY with SQLITE
String query = "select seq from sqlite_sequence WHERE name = 'Table_Name'"
An important remark about the SQLITE_SEQUENCE table.
The documentation says
The SQLITE_SEQUENCE table is created and initialized automatically whenever a normal table that contains an AUTOINCREMENT column is created.
So the SQLITE_SEQUENCE table is created, but NOT the row associated with the table that contains the AUTOINCREMENT column. That row is created with the first insert query (with "seq" value of 1).
That means that you must doing at least one insert operation before looking for the next autoincrement value of a specific table. It could be done for example just after the creation of the table, performing an insert and a delete of a dummy row.
Here is what I use to get the next AUTOINCREMENT value for a specific table:
/**
* Query sqlite_sequence table and search for the AUTOINCREMENT value for <code>tableName</code>
* #param tableName The table name with which the AUTOINCREMENT value is associated.
*
* #return The next AUTOINCREMENT value for <code>tableName</code>
* If an INSERT call was not previously executed on <code>tableName</code>, the value 1 will
* be returned. Otherwise, the returned value will be the next AUTOINCREMENT.
*/
private long getNextAutoIncrement(String tableName) {
/*
* From the docs:
* SQLite keeps track of the largest ROWID using an internal table named "sqlite_sequence".
* The sqlite_sequence table is created and initialized automatically
* whenever a normal table that contains an AUTOINCREMENT column is created.
*/
String sqliteSequenceTableName = "sqlite_sequence";
/*
* Relevant columns to retrieve from <code>sqliteSequenceTableName</code>
*/
String[] columns = {"seq"};
String selection = "name=?";
String[] selectionArgs = { tableName };
Cursor cursor = mWritableDB.query(sqliteSequenceTableName,
columns, selection, selectionArgs, null, null, null);
long autoIncrement = 0;
if (cursor.moveToFirst()) {
int indexSeq = cursor.getColumnIndex(columns[0]);
autoIncrement = cursor.getLong(indexSeq);
}
cursor.close();
return autoIncrement + 1;
}
Inside the SQLiteOpenHelper you use, start a transaction. Insert some data and then rollback.
Such a way, you 'll be able to get the next row id, like this:
public long nextId() {
long rowId = -1;
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
// fill values ...
// insert a valid row into your table
rowId = db.insert(TABLE_NAME, null, values);
// NOTE: we don't call db.setTransactionSuccessful()
// so as to rollback and cancel the last changes
} finally {
db.endTransaction();
}
return rowId;
}
It's work.
public static long getNextId(SQLiteDatabase db, String tableName) {
Cursor c = null;
long seq = 0;
try {
String sql = "select seq from sqlite_sequence where name=?";
c = db.rawQuery(sql, new String[] {tableName});
if (c.moveToFirst()) {
seq = c.getLong(0);
}
} finally {
if (c != null) {
c.close();
}
}
return seq + 1;
}
You can use cursor.getInt(i); method
i here is index of the id column
Cursor c = db.rawQuery("Select * From mSignUp", null);
String mail = null;
try {
while (c.moveToNext()) {
mail = c.getString(0);
String pas = c.getString(1);
Toast.makeText(getApplicationContext(), "Name = " + mail + " Pass = " + pas, Toast.LENGTH_SHORT).show();
}
}catch (CursorIndexOutOfBoundsException e){
Log.e("OutOfBound", Log.getStackTraceString(e));
}
finally {
c.close();
}
I am trying to get the last inserted rowid from a sqlite database in Android. I have read a lot of posts about it, but can't get one to work.
This is my method:
public Cursor getLastId() {
return mDb.query(DATABASE_TABLE, new String[] {KEY_WID}, KEY_WID + "=" + MAX(_id), null, null, null, null, null);}
I have tried with MAX, but I must be using it wrong. Is there another way?
Well actually the SQLiteDatabase class has its own insert method which returns the id of the newly created row. I think this is the best way to get the new ID.
You can check its documentation here.
I hope this helps.
Use
SELECT last_insert_rowid();
to get the last inserted rowid.
If you are using AUTOINCREMENT keyword then
SELECT * from SQLITE_SEQUENCE;
will tell you the values for every table.
To get the last row from the table..
Cursor cursor = theDatabase.query(DATABASE_TABLE, columns,null, null, null, null, null);
cursor.moveToLast();
Use moveToLast() in Cursor interface.
From android.googlesource.com
/**
* Move the cursor to the last row.
*
* <p>This method will return false if the cursor is empty.
*
* #return whether the move succeeded.
*/
boolean moveToLast();
Simple example:
final static String TABLE_NAME = "table_name";
String name;
int id;
//....
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
if(cursor.moveToLast()){
//name = cursor.getString(column_index);//to get other values
id = cursor.getInt(0);//to get id, 0 is the column index
}
Or you can get the last row when insertion(Which is #GorgiRankovski have mentioned):
long row = 0;//to get last row
//.....
SQLiteDatabase db= this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_NAME, name);
row = db.insert(TABLE_NAME, null, contentValues);
//insert() returns the row ID of the newly inserted row, or -1 if an error occurred
Also their is a multiple ways you can do this using query:
One is expressed by #DiegoTorresMilano
SELECT MAX(id) FROM table_name. or to get all columns values SELECT * FROM table_name WHERE id = (SELECT MAX(id) FROM table_name).
If your PRiMARY KEY have sat to AUTOINCREMENT, you can SELECT vaules occording to max to min and limit the rows to 1 using SELECT id FROM table ORDER BY column DESC LIMIT 1
(If you want each and every value, use * instead of id)
If you want the last_insert_id just afert a insert you can use that :
public long insert(String table, String[] fields, String[] vals )
{
String nullColumnHack = null;
ContentValues values = new ContentValues();
for (int i = 0; i < fields.length; i++)
{
values.put(fields[i], vals[i]);
}
return myDataBase.insert(table, nullColumnHack, values);
}
The insert method returns the id of row just inserted or -1 if there was an error during insertion.
long id = db.insert("your insertion statement");
db is an instance of your SQLiteDatabase.
Try this:
public Cursor getLastId() {
return mDb.query(DATABASE_TABLE, new String[] { **MAX(id)** }, null, null, null, null, null, null);}
/**
* #return
*/
public long getLastInsertId() {
long index = 0;
SQLiteDatabase sdb = getReadableDatabase();
Cursor cursor = sdb.query(
"sqlite_sequence",
new String[]{"seq"},
"name = ?",
new String[]{TABLENAME},
null,
null,
null,
null
);
if (cursor.moveToFirst()) {
index = cursor.getLong(cursor.getColumnIndex("seq"));
}
cursor.close();
return index;
}
I use this
public int lastId(){
SQLiteDatabase db =
this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from resep", null );
res.moveToLast();
return res.getInt(0);
}
In your DbHelper class,
public long getLastIdFromMyTable()
{
SQLiteDatabase db = this.getReadableDatabase();
SQLiteStatement st = db.compileStatement("SELECT last_insert_rowid() from " + MY_TABLE);
return st.simpleQueryForLong();
}