Inserting data to SQLite table with constraint failure
I'm trying to insert data into SQLite table on Android. _id is primary key of the table and I am inserting a row using this method:
public void addSomeData(int id, String datetime) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_ID, id);
contentValues.put(KEY_DATETIME, datetime);
mDb.insert(TABLE, null, contentValues);
}
The problem I get is that sometimes primary key constraint is validated and I would like to use something like INSERT IF NOT EXISTS, but preferably something that would work with ContentValues. What are my options? I understand that insertOrThrow() and insertWithOnConflict() methods only return different values, or should I use one of these methods?
Use insertWithOnConflict() with CONFLICT_IGNORE.
Will return ROWID/primary key of new or existing row, -1 on any error.
In my case "constraint failure" happened because of I had some tables which are depended on each other. As for the "insert if not exist", you can query with this id and you check if the cursor's count is bigger than zero. Check the method I'm already using in my app.
public boolean isRowExists(long rowId) {
Cursor cursor = database.query(this.tableName, this.columns, DBSQLiteHelper.COLUMN_ID + " = ? ", new String[] { "" + rowId }, null, null, null);
int numOfRows = cursor.getCount();
cursor.close();
return (numOfRows > 0) ? true : false;
}
to do so you could simply query the db to see if a row with that key exists and insert the new row only if the query returns no data.
Related
I'd like to do something like this:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
// what should i do here to determine if the db contains the primaryKey?
}
What is the most efficient way to check if the db contains the specified value?
You could try to read the row with that PK value:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query("TableName", null, "IDColumn = " + primaryKey,
null, null, null, null);
return cursor.moveToFirst();
}
However, it would be a better idea to use a helper function that allows you to avoid having to muck around with a cursor:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
return DatabaseUtils.queryNumEntries(db, "TableName", "IDColumn = " + primaryKey) > 0;
}
You should inspect sqlite scheme. You may try
"SELECT name FROM sqlite_master WHERE type='table'"
Second variant:
PRAGMA table_info(table-name);
If You are looking for getting the column names for a table:
PRAGMA table_info(your_table_name);
Example :
PRAGMA table_info(Login);
you will get pk value 1 if you have primary key in login table.
Check this tutorial on PRAGMA
This pragma returns one row for each column in the named table.
Columns in the result set include the column name, data type, whether
or not the column can be NULL, and the default value for the column.
The "pk" column in the result set is zero for columns that are not
part of the primary key, and is the index of the column in the primary
key for columns that are part of the primary key.
I have the following code to update or insert database, where q_id is my primary key
public long updateResponse(int response, int q_id) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
long id = 0;
contentValues.put(VivzHelper.Q_ID, q_id);
contentValues.put(VivzHelper.QUESTION_RESPONSE, response);
id = db.insertWithOnConflict(VivzHelper.TABLE_QUESTION_TEXT, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);
if(id==-1)
Log.d("failed", "failed"+response);
else
Log.d("success","success"+response);
return id;
}
Above code is updating/inserting QUESTION_RESPONSE but making all other column in that row as null in table.. Help
Above code is updating/inserting QUESTION_RESPONSE but making all other column in that row as null in table
That's what the "replace" conflict resolution does. If the insert would result in a conflict, the conflicting rows are first deleted and only then is the new row inserted. NULL is the default default value for a column.
If you need to retain other column data in the row, use an UPDATE query. For example, to update the response column to the row with the specified id:
contentValues.put(VivzHelper.QUESTION_RESPONSE, response);
db.update(VivzHelper.TABLE_QUESTION_TEXT, contentValues,
VivzHelper.Q_ID + "=?", new String[] { String.valueOf(q_id) });
I had created two table in my database, In both table I am inserting value at the same time, now what I want to do is that, I want to insert record in second table, but the condition is that, if there is two same record then I want insert only one record not duplicate value, In second table there is two field one is id and second is category, when user insert two same category that time I want to insert only one entry, below is my code which is not working properly, It insert all record accept duplicate value..
public long InsertCat(String idd, String cat)
{
try
{
SQLiteDatabase db;
long rows = 0;
db = this.getWritableDatabase();
ContentValues Val = new ContentValues();
Val.put("IDD", idd);
Val.put("Category", cat);
Cursor c = db.rawQuery("SELECT * FROM " + TABLE_CATEGER + " WHERE Category='"+cat+"'",null);
while(c.moveToNext())
{
if(c.getString(0).equals(cat))
{
flag=true;
}
}
if(flag==true)
{
rows=db.update(TABLE_CATEGER, Val, "Category='"+cat+"'" , null);
System.out.print(rows);
db.close();
}
if(flag==false)
{
rows = db.insert(TABLE_CATEGER, null, Val);
System.out.print(rows);
db.close();
}
return rows; // return rows inserted.
} catch (Exception e) {
return -1;
}
}
Put all your values inside ContentValues and then call this on writableDatabase
db.insertWithOnConflict(tableName, null, contentValues,SQLiteDatabase.CONFLICT_REPLACE);
EDIT:
Well all you need is only this part of code
SQLiteDatabase db;
long rows = 0;
db = this.getWritableDatabase();
ContentValues Val = new ContentValues();
Val.put("IDD", idd);
Val.put("Category", cat);
rows = db.insertWithOnConflict(tableName, null, contentValues,SQLiteDatabase.CONFLICT_REPLACE);
insertWithOnConflict methods follows the last parameter as the reaction algorithm when an duplicate row is Found. And for a duplicate row to be found, the primary keys has to clash. If all this satisfys the row would surely get Replaced :-/ If not something else is going wrong..
While creating your table, put constraint on your column(Primary key or Unique key).This will not only the duplicate value to be inserted into your database.
This is working for me,and i also created Category as a primary key..
ContentValues Val = new ContentValues();
Val.put("IDD", idd);
Val.put("Category", cat);
long rows=db.insertWithOnConflict(TABLE_CATEGER, null, Val,SQLiteDatabase.CONFLICT_REPLACE);
System.out.print(rows);
Log.d("kkkkkkkkkk",""+ rows);
db.close();
return rows; // return rows inserted.
Check with the primary key of which you want assign then while inserting check with on duplicate key..
if you want you update the row
on duplicate key update
As mentioned i am writing the code on duplicate key
INSERT OR REPLACE INTO TABLE_CATEGER(value1,value2,value3)
Use the following query
INSERT OR REPLACE INTO table_name (idColoumn, categoryColumn) VALUES (?, ?)
It will add new row if it does not exist or update row if it exists.
hope this will help you.
use insertWithOnConflict() method instead of insert()
response = sqLiteDatabase.insertWithOnConflict(TABLE_TRACKER_LOGS_LINES, null, contentValues,SQLiteDatabase.CONFLICT_REPLACE);
I am using sqlite
i want to print the query executed in db to insert
here is my code
// for SAving Ocean/Air sales
public int saveOrder(Order odr) throws SQLException {
SQLiteDatabase db = con.getWritableDatabase();
int ordrId = 0;
ContentValues values = new ContentValues();
values.put("cr_usr", odr.getCrUsr());
values.put("cr_ts", odr.getCrTs().toString());
values.put("eat_mst_cust_id", odr.getEatMstCustId());
values.put("ordr_dt", odr.getOrdrDt().toString());
String selectQuery = "SELECT last_insert_rowid()";
try {
// Inserting Row
db.insertOrThrow("eat_ordr", null, values);---getting error here for constraint failed
Cursor cursor = db.rawQuery(selectQuery, null);
cursor.moveToFirst();
ordrId = cursor.getInt(0);
db.close();
} finally {
db.close();
}
return ordrId;
}
I am not getting any error but row is failed to insert bcz it returns 0 for idvalue
so i want to see executed query how to get that query?
here is my table structure
CREATE TABLE "eat_ordr" ("eat_ordr_id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
"eat_mst_cust_id" VARCHAR NOT NULL REFERENCES "eat_mst_cust"("eat_mst_cust_id"),
"ordr_no" VARCHAR NOT NULL UNIQUE ,
"ordr_dt" DATETIME NOT NULL ,
"ordr_stat" VARCHAR NOT NULL ,
"last_sync_ts" DATETIME,
"cr_ts" DATETIME DEFAULT CURRENT_TIMESTAMP, "md_ts" DATETIME, "cr_usr" VARCHAR, "md_usr" VARCHAR)
The insertOrThrow documentation says:
Returns
the row ID of the newly inserted row
So this can be done much easier:
ordrId = db.insertOrThrow("eat_ordr", null, values);
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