Insert or update in SQlite and Android using the database.query(); - android

is there a way to change my function:
public categorie createCategoria(String categoria) {
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_NOME, categoria);
values.put(MySQLiteHelper.COLUMN_PREF, 0);
long insertId = database.insert(MySQLiteHelper.TABLE_CATEGORIE, null,
values);
Cursor cursor = database.query(MySQLiteHelper.TABLE_CATEGORIE,
allCategorieColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
categorie newCategoria = cursorToCategorie(cursor);
cursor.close();
return newCategoria;
}
this is a raw insert, i would like to change this function to make it update or insert accordingly. i would like to change this becouse i'm already using this function in some places, but now i need to choose if insert a row or update (or ignoring the insert) a row with the same COLUMN_NOME. can someone help me doing this?
i mean i would like to insert a new row ONLY if there isn't another with the same name (as usual you know).

You can use insertWithOnConflict() if you want to insert or update, depending in whether the record exists or not:
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_ID, id);
contentValues.put(COLUMN_VALUE, value);
// this will insert if record is new, update otherwise
db.insertWithOnConflict(TABLE, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);

you could call int nRowsEffected = database.update(...); if there are no rows effected by the update either the row doesn't exist (or you hosed your update()!) therefore you need to call database.insert(...). of course if nRowsEffected > 0 then you are done.

You can use execSQL and use INSERT OR REPLACE
String[] args = {"1", "newOrOldCategory"}; // where 1 is the category id
getWritableDatabase().execSQL("INSERT OR REPLACE INTO table_name (idColoumn, categoryColumn) VALUES (?, ?)", args);

First of all you have write function which is check whether id is exists in particular Table like:
/**
* #param table_name
* #param server_id
* #return
*/
public boolean isServerIdExist(String table_name, int server_id) {
long line = DatabaseUtils.longForQuery(mDB, "SELECT COUNT(*) FROM " + table_name + " WHERE id=?",
new String[]{Integer.toString(server_id)});
return line > 0;
}
You have to pass table_name and id in that like
/**
* INSERT in TABLE_ACCOUNT_DEVICE
**/
public long insertOrUpdateAccountDevice(int server_id, int account_id,
String device_name, String device_id,
String last_active, String itp,
String utp, int status) {
ContentValues values = new ContentValues();
values.put(ACCOUNT_DEVICE_ACCOUNT_ID, account_id);
values.put(ACCOUNT_DEVICE_DEVICE_NAME, device_name);
values.put(ACCOUNT_DEVICE_DEVICE_ID, device_id);
values.put(ACCOUNT_DEVICE_LAST_ACTIVE, last_active);
values.put(ACCOUNT_DEVICE_ITP, itp);
values.put(ACCOUNT_DEVICE_UTP, utp);
values.put(ACCOUNT_DEVICE_STATUS, status); // 0=pending, 1=active, 2=Inactive, -1=not_found
/**
* isServerIdExists
*/
if (isServerIdExists(TABLE_ACCOUNT_DEVICE, server_id)) {
values.put(ACCOUNT_DEVICE_SERVER_ID, server_id);
return mDB.insert(TABLE_ACCOUNT_DEVICE, null, values);
} else {
return mDB.update(TABLE_ACCOUNT_DEVICE, values, ACCOUNT_DEVICE_SERVER_ID + " =? ",
new String[]{Integer.toString(server_id)});
}
}
Hope it will helps you.

Related

Get a specific value from a specific column from specific row?

i have a table names "highscore"
In the table there is:
id (int) ,
name (string) ,
win(int) ,
draw(int),
loss(int).
I want to make a query that i can get the specific value win from the row , only the integer.. how can i do that? i want to handle sql injection to.
I have a method that update the win, but i need to get the win, increment the value with 1 and then update. My update method is this and it works:
public void updateWin(String playerName, int win) {
SQLiteDatabase db = this.getReadableDatabase();
ContentValues values = new ContentValues();
values.put(Constants.KEY_WIN, win);
db.update(Constants.TABLE_NAME, values, Constants.KEY_PLAYER_NAME + "= ?", new String[]{playerName});
db.close();
}
Anyone can help me please? thanx
Option 1 - Increment according to arithmetic calculation within SQL
You could base the this on the SQL (assuming the table is mytable001 and the player's name is FRED) :-
UPDATE mytable001 SET win = win +1 WHERE playername = 'FRED';
This would do away with the need to query the playername to get the current number of wins as it directly increments the value.
However, this cannot be done via the convenience update method nor a rawQuery you have utilise execSQL.
So the following could be used :-
public boolean incrementWin(String playerName) {
SQLiteDatabase db = this.getWritableDatabase();
String esc_playername = DatabaseUtils.sqlEscapeString(playerName);
String qrysql = "UPDATE " +
Constants.TABLE_NAME +
" SET " +
Constants.KEY_WIN + " = " +
Constants.KEY_WIN + " + 1" +
" WHERE " +
Constants.KEY_PLAYER_NAME + "=" + esc_playername;
db.execSQL(qrysql);
long changes = DatabaseUtils.longForQuery(db,"SELECT changes()",null);
db.close();
return changes > 0;
}
Note if the update couldn't be/ wasn't performed then it would return false.
The use of sqlEscapeString, will escape the playername and I believe offer some protection against SQL Injection.
Option 2 - Retrieve current value, calculate new, update using new :-
public boolean incWin(String playername) {
SQLiteDatabase db = this.getWritableDatabase();
String whereclause = Constants.KEY_PLAYER_NAME + "=?";
String[] wherargs = new String[]{playername};
int win = -1; // default to not update
Cursor csr = db.query(
Constants.TABLE_NAME,
null,
whereclause,
wherargs,
null,
null,
null
);
if (csr.moveToFirst()) {
win = csr.getInt(csr.getColumnIndex(Constants.KEY_WIN)) + 1;
}
csr.close();
if (win < 1) {
db.close();
return false;
}
ContentValues cv = new ContentValues();
cv.put(Constants.KEY_WIN,win);
if (db.update(Constants.TABLE_NAME,cv,whereclause,wherargs) > 0) {
db.close();
return true;
}
db.close();
return false;
}
Note if the update couldn't be/ wasn't performed then it would return false.

Content provider updating all rows

working on a content provider and I'm having an issue with it. When I try to update a certain row in the SQLite database through the content provider, it updates the column in all the rows, not just the row I specify. I know the CP is working because I can access it, populate a listview with it, and change the content of column, but never just one column.
Here is the relevant update method
public int update(Uri url, ContentValues values, String where,
String[] whereArgs) {
SQLiteDatabase mDB = dbHelper.getWritableDatabase();
int count;
String segment = "";
switch (URL_MATCHER.match(url)) {
case ITEM:
count = mDB.update(TABLE_NAME, values, where, whereArgs);
break;
case ITEM__ID:
segment = url.getPathSegments().get(1);
count = mDB.update(TABLE_NAME, values,
"_id="
+ segment
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
getContext().getContentResolver().notifyChange(url, null);
return count;
}
and here is the code I use to (try to) update it.
ContentValues mUpdateValues = new ContentValues();
mUpdateValues.put(ContentProvider.HAS, "true");
mUpdateValues.put(ContentProvider.WANT, "false");
mRowsUpdated = getContentResolver().update(Uri.parse(ContentProvider._ID_FIELD_CONTENT_URI
+ rowId), mUpdateValues, null, null);
and here is the URI
URL_MATCHER.addURI(AUTHORITY, TABLE_NAME + "/#", ITEM__ID);
Thanks, any help would be appreciated.
EDIT I have also tried
mRowsUpdated = getContentResolver().update(
ContentProvider._ID_FIELD_CONTENT_URI, mUpdateValues,
null, null);
and
mRowsUpdated = getContentResolver().update(
ContentProvider.CONTENT_URI, mUpdateValues,
null, null);
You are not specifying a WHERE clause, which is what is used to update only specific rows. The default behavior of content providers is to update all the rows, unless you specify conditions.
From the docs:
developer.android.com/reference/android/content/ContentResolver.html
Parameters
uri The URI to modify.
values The new field values. The key is the column name for the field. A null value will remove an existing field value.
where A filter to apply to rows before updating, formatted as an SQL WHERE clause (excluding the WHERE itself).

Cannot update last row on SQLite

public public udpateNoteInfo(String text){
ContentValues val = new ContentValues();
val.put(KEY_CONTENT5, text);
sqLiteDatabase.update(MYDATABASE_TABLE, val,"ORDER_BY("+KEY_ID+") DESC LIMIT 0,1", new String[]{text});
}
I try to update the last row of the KEY_CONTENT5 column in my SQLite, but it's error.
I guess its mistake at "ORDER_BY("+KEY_ID+") DESC LIMIT 0,1" but I don't know how to make it correct. Please tell me if you know that. Thank you.
ERROR:
09-05 11:47:54.769 E/Database( 4386): Error updating note=Test using UPDATE PERSONAL_TABLE SET note=? WHERE _id = (SELECT max(_id) FROM PERSONAL_TABLE)
Activity class:
public void updateNote(String txt) {
mySQLiteAdapter = new PersonalSQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
cursor = mySQLiteAdapter.queueAll();
if (cursor != null) {
mySQLiteAdapter.udpateNoteInfo(txt);
}
mySQLiteAdapter.close();
}
SQLiteAdapter class (not activity):
public void udpateNoteInfo(String text) {
ContentValues val = new ContentValues();
val.put(KEY_CONTENT5, text);
sqLiteDatabase.update(MYDATABASE_TABLE, val, KEY_ID + " = (SELECT max("
+ KEY_ID + ") FROM " + MYDATABASE_TABLE + ")",
new String[] { text });
}
You can't put an order by in an update.
You can try something like this:
WHERE id=(SELECT max(id) FROM TABLE) if you want to update the last id, assuming your sequences aren't modified.
public void udpateNoteInfo(String text) {
ContentValues val = new ContentValues();
val.put(KEY_CONTENT5, text);
sqLiteDatabase.update(MYDATABASE_TABLE, val, KEY_ID+" = (SELECT max("+KEY_ID+") FROM "+MYDATABASE_TABLE+")", null);
}
My final answer.
You can query the ID, and then, update this row... if your key_id values are not unique, you'll need to use your primary key column(s) instead of this one...
Cursor cLast = db.query(MYDATABASE_TABLE, [KEY_ID], null, null, null, "ORDER_BY("+KEY_ID+") DESC", "LIMIT 0,1");
if (cLast.moveToFirst()) {
long lastKey = cLast.getLong(0); // if it's not a long, use the appropriate getter
sqLiteDatabase.update(MYDATABASE_TABLE, val, "WHERE KEY_ID=?", lastKey);
}
UPDATE table set col = 1 WHERE id = (SELECT MAX(id) FROM table)

Getting the next AUTO_INCREMENT value of a SQLite database

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();
}

Get last inserted value from sqlite database Android

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();
}

Categories

Resources