I need to handle an error when non-unique data is inserted into the database. I have this code:
try {
handler.addBookmark(new BookmarkModel(idBrand, brand, desc, types, detail, image));
Toast.makeText(this, "Success", Toast.LENGTH_LONG).show();
}catch (SQLiteException e){
e.printStackTrace();
Toast.makeText(this, "Failed", Toast.LENGTH_LONG).show();
}
I insert like this:
public long addBookmark(BookmarkModel bookmark) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_ID, bookmark._id); // Must Unique
values.put(KEY_BRAND, bookmark.brandName);
values.put(KEY_DESC, bookmark.descTerm);
values.put(KEY_TYPE, bookmark.type);
values.put(KEY_DETAIL, bookmark.detail);
values.put(KEY_IMAGE, bookmark.image);
return db.insert(TABLE_BOOKMARK, null, values);
//db.close();
}
Logcat of the error that occurs:
android.database.sqlite.SQLiteConstraintException: column id is not unique (code 19)
The data was not inserted, but I was unable to show the error message. How can I show the toast to let the user know the insert failed?
Do not set _id yourself. This line should be gone:
values.put(KEY_ID, bookmark._id); // Must Unique
If your table schema sets it up correctly (_id INTEGER PRIMARY KEY) then this is auto incremented long value. Nothing you should touch on insert.
You should look into the insertOrThrow() method which will throw an SQLiteConstraintException if this occurs.
Then, you can put your insert into a try/catch block:
try{
db.insertOrThrow(table, columnHack, values);
} catch (SQLiteConstraintException e){
Toast.makeText(context, "Unable to insert values.", Toast.LENGTH_SHORT).show();
}
I got a solution. just set an id to PRIMARY KEY AUTOINCREMENT and set 1 text UNIQUE . for methode that handle an error, i use insertOrThrow and use it with try-catch .
Related
How can i get the autoincrement value in thansaction body?
Code
public void insertAllStudents(List<Student> students) {
String sql = "INSERT INTO "+ StudentEntry.TABLE_NAME +" VALUES (?,?,?,?,?);";
SQLiteDatabase db = this.getWritableDatabase();
SQLiteStatement statement = db.compileStatement(sql);
db.beginTransaction();
for (Student student: students) {
statement.clearBindings();
statement.bindString(2, student.getId());
statement.bindString(3, student.getFirstName());
statement.bindString(4, student.getLastName());
statement.bindLong(5, student.getBirthday());
statement.execute();
}
db.setTransactionSuccessful();
db.endTransaction();
}
The first column (_ID) is autoincrement field. Is it opportunity to get this value?
student.getId() -that's not id from database, that's different id.
If you change your code to use db.insert(), this method returns the id of the inserted row - see Get generated id after insert.
There is also a specialised SQLite function to get the last inserted row if you'd prefer to keep compiling statements, see Best way to get the ID of the last inserted row on SQLite
edit: example using db.insert(). This isn't tested but should be pretty close to functional.
db.beginTransaction();
boolean success = true;
final ContentValues values = new ContentValues();
for (final Student student: students) {
values.put("student_id", student.getId());
values.put("first_name", student.getFirstName());
values.put("last_name", student.getLastName());
values.put("birthday", student.getBirthday());
final long id = db.insert("my_table", null, values);
if (id == -1) {
success = false;
break;
}
// TODO do your thing with id here.
}
if (success) {
db.setTransactionSuccessful();
}
db.endTransaction();
Instead of statement.execute(), you can do statement.executeInsert(). This returns the row ID of the inserted row. Or, as #Tom suggested, you can use db.insert() instead, and it will also return the inserted row ID. Using a compiled statement like you are doing now is faster though.
If you want to try the db.insert() approach, it would look something like this:
ContentValues values = new ContentValues();
for (Student student: students) {
// use whatever constants you have for column names instead of these:
values.put(COLUMN_STUDENT_ID, student.getId());
values.put(COLUMN_STUDENT_FIRSTNAME, student.getFirstName());
values.put(COLUMN_STUDENT_LASTNAME, student.getLastName());
values.put(COLUMN_STUDENT_BIRTHDAY, student.getBirthday());
db.insert(StudentEntry.TABLE_NAME, null, values);
}
I'm working with sqlite. I successfully created database and table. I also wrote code which can insert new values in my table. My code is working perfect, but now I want to show for example: toast message if inserted new value, else show error message in toast or something else.
This is a my insert to table source code:
public void InsertToPhysicalPersonTable(String FirstName, String LastName,
String FullName, String FatherName) {
try {
ContentValues newValues = new ContentValues();
newValues.put("FirstName", FirstName);
newValues.put("LastName", LastName);
newValues.put("FullName", FullName);
newValues.put("FatherName", FatherName);
db.insert(AddNewPhysicalPerson, null, newValues);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
Toast.makeText(myContext, "Something wrong", Toast.LENGTH_SHORT).show();
}
}
I called my function like this:
loginDataBaseAdapter.InsertToPhysicalPersonTable("FirstName",
"LastName",
"FullName",
"FatherName"
);
If anyone knows the solution, please help me.
Thanks
insert() method returns the row ID of the newly inserted row, or -1 if an error occurred.
Change
db.insert(AddNewPhysicalPerson, null, newValues);
like this
long rowInserted = db.insert(AddNewPhysicalPerson, null, newValues);
if(rowInserted != -1)
Toast.makeText(myContext, "New row added, row id: " + rowInserted, Toast.LENGTH_SHORT).show();
else
Toast.makeText(myContext, "Something wrong", Toast.LENGTH_SHORT).show();
long result = db.insert(table name, null, contentvalues);
if(result==-1)
return false;
else
return true;
this is good solution for it..
here is another way:-
I don't know if I am too late for your project but have you thought of .lastrowid?
Here is an example of what I did last_rec=self.cursor.lastrowid so lastrec would have the number of the last row inserted.
Here is the info from sqlite.org
Hope it helps, you , or anyone else who wonders about this.
Kind regards and all the best :¬)
joe
Hi guys i'have problem with this little block of code
// Insert a new contact in database
public void insertInSignature(String TITLE_SI) {
try {
// Open Android Database
db = databaseHelper.getWritableDatabase();
ContentValues initialValues = new ContentValues();
initialValues.put("TITLE_SI", TITLE_SI);
db.insert("DELIVERY_SLIP", null, initialValues);
} catch (SQLException sqle) {
Log.e(TAG, "insertUser Error");
Log.e(TAG, "Exception : " + sqle);
} finally {
// Close Android Database
databaseHelper.close();
}
}
I have unique constraint on my table "DELIVERY_SLIP
So , when i'm trying to insert some row which already exist , it return some error like "Oh shit , you're inserting the same , i'm sorry men , i can't do it"
http://cdn.imghack.se/images/3b51afd07d1f1a8bd021c9e9dfc57e98.png
Here my log
It's this line
databaseHelper.close();
When database helper close , this return the log.
I just want to avoid to log it, I already tested with a tryCatch on sqliteConstraintException
But, nothing worked.
Thanks by advance
Instead of insert(), use insertWithOnConflict() with some conflict resolution algorithm appropriate for your use, such as SQLiteDatabase.CONFLICT_IGNORE.
I have 2 columns in sqlite which are name and date,name is already set it to unique to avoid duplicate entry but my problem is I want to insert the same record for column 'name' but different record in column 'date'. I'm also using this to filter the duplicate record and it worked.
try {
dbOpenHelperss.insertOrThrow("table", values);
} catch (SQLiteConstraintException e)
//to detect if there is a duplicated item
}
For example in column_name='Peter Xavier' column_date='02/15/14 and i want to insert record of Peter Xavier with different date like column_name ='Peter Xavier' , column_date='02/16/14
What I tried so far is
if(!"column_date".equals(colum_name)) {
//to compare two columns are not the same then insert
ContentValues values = new ContentValues();
values.put("column_name",name );
values.put("column_date", date);
try {
dbOpenHelperss.insertOrThrow("table", values);
} catch (SQLiteConstraintException e) {
// to detect if there is a duplicate entry
}
}
Add Composite key.that means column_name and column_date together work as a key
Unique (column_name, column_date) ,
I am using transactions to insert record to my database. Can you please tell me whether this is the right way to get total inserted record (return by numrow)? Also, in the code below, if some insert fails, will it continue to next insertion or will exit (I didn't use endTransaction in Catch block)?
int numrow = 0;
try{
db.beginTransaction();
for(mylibman cn : insertlist){
ContentValues values = new ContentValues();
values.put(KEY_LIBID, cn.getLibid());
values.put(KEY_NAME, cn.getBookname());
db.insertWithOnConflict(TABLE_NAME, null, values,SQLiteDatabase.CONFLICT_IGNORE);
numrow++;
}
db.setTransactionSuccessful();
}catch (Exception e) {
} finally {
db.endTransaction();
}
return numrow;
you should check like this
int numrow = 0;
try{
db.beginTransaction();
for(mylibman cn : insertlist){
ContentValues values = new ContentValues();
values.put(KEY_LIBID, cn.getLibid());
values.put(KEY_NAME, cn.getBookname());
//do like this
long insertedId=db.insertWithOnConflict(TABLE_NAME, null, values,SQLiteDatabase.CONFLICT_IGNORE);
if(insertedId!=-1)
{
numrow++;
}
}
db.setTransactionSuccessful();
}catch (Exception e) {
} finally {
db.endTransaction();
}
return numrow;
Your code will also count records that were ignored.
insertWithOnConflict returns the rowid of the inserted record, or -1, so you have to check for that:
if (db.insertWithOnConflict(TABLE_NAME, null, values,
SQLiteDatabase.CONFLICT_IGNORE) != -1)
numrow++;
The insertWithOnConflict function does not throw an exception if a record is not inserted due to a conflict. However, it will throw if there is some other error, such as an unknown column name, or a read-only database.
You should not blindly ignore exceptions; just use try/finally:
db.beginTransaction();
try {
for (...) {
...
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
Non of the answers here reflect the documentation:
"returns:
the row ID of the newly inserted row OR the primary key of the existing row if the input param 'conflictAlgorithm' = CONFLICT_IGNORE OR -1 if any error"
Since the author wants to know the 'inserted' columns, both answers are wrong. The number inserted rows could be 0, as they already exist. However "CONFLICT_IGNORE" will make insert return the existing primary key, so the numrow will be the rows you 'tried' to insert and didn't fail, but not the rows 'inserted'.
You might have to use the flag "SQLiteDatabase.CONFLICT_ABORT" or "SQLiteDatabase.CONFLICT_FAIL" depending on what and how you insert.
Source: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insertWithOnConflict%28java.lang.String,%20java.lang.String,%20android.content.ContentValues,%20int%29