I have my table in database
CREATE TABLE Opponent (
Opponent_ID integer PRIMARY KEY AUTOINCREMENT,
Opponent_Add_Date text,
Opponent_Name text UNIQUE
);
Then I'm trying to insert query to database
String query = "INSERT INTO Opponent (Add_Date, Opponent_Name) VALUES ('date' , 'name');"
The problem occurs, when I want to add existing opponent name, my app crushes. If I'm trying to catch my exception with SQLiteConstraintException, however then it allows adding two Opponents with the same name. For catching it I'm using:
try {
SQLiteStatement statement = mDataBase.compileStatement(query);
statement.execute();
} catch (SQLiteConstraintException e) {
Log.e("insert", "SQLException: " + e.getLocalizedMessage());
}
Could anyone tell me how to catch the moment, when two the same names are added?
If you just want to do nothing if the name already exists, then you can use INSERT OR IGNORE instead.
However, if you also need to retrieve the ID of the already-existing row, then you should just execute a SELECT first, and do the INSERT only if the row is not found.
Related
I wish to just delete one duplicate row in here (For example, Jim 21)
SQLiteDatabase myDataBase=this.openOrCreateDatabase("Users",MODE_PRIVATE,null);
myDataBase.execSQL("CREATE TABLE IF NOT EXISTS users (name VARCHAR,age INT(3))");
myDataBase.execSQL("INSERT INTO users(name,age) VALUES ('Rob', 34)");
myDataBase.execSQL("INSERT INTO users(name,age) VALUES ('Nat', 22)");
myDataBase.execSQL("INSERT INTO users(name,age) VALUES ('Jim', 21)");
myDataBase.execSQL("DELETE FROM users WHERE name='Jim'");
Cursor c=myDataBase.rawQuery(" SELECT * FROM users", null);
int nameIndex=c.getColumnIndex("name");
int ageIndex=c.getColumnIndex("age");
c.moveToFirst();
while (c!=null){
Log.i("name",c.getString(nameIndex));
Log.i("age",Integer.toString(c.getInt(ageIndex)));
c.moveToNext();
}
I have tried this
myDataBase.execSQL("DELETE FROM users WHERE name='Jim' LIMIT 1");
But it is throwing a syntax error. I know LIMIT is not syntactically allowed in android. So how do I just delete one record of Jim when there are duplicates?
Thank you.
Limit will not work with Delete query,it's only for Select number of record
Update the query
myDataBase.execSQL("DELETE FROM users WHERE name='Jim'");
you can add more condition for remove specific records
myDataBase.execSQL("DELETE FROM users WHERE name='Jim' AND age=21 ");
There are several ways to achieve this. However, I would suggest to put a unique constraint on your name field.
myDataBase.execSQL("CREATE TABLE IF NOT EXISTS users (name text unique not null, age INT(3))");
Now for creating new entries in your users table, get a function like the following.
public void createUser(List<User> userList) {
if (userList != null && !userList.isEmpty()) {
SQLiteDatabase db = this.openOrCreateDatabase("Users",MODE_PRIVATE,null);
db.beginTransaction();
try {
for (User user : userList) {
ContentValues values = new ContentValues();
values.put("name", user.getName());
values.put("age", user.getAge());
// Replace on conflict with the unique constraint
db.insertWithOnConflict("users", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
} catch (Exception e) {
e.printStackTrace();
}
db.setTransactionSuccessful();
db.endTransaction();
}
}
In this way, you do not have to delete any duplicate rows in your table as there will be no duplicate rows either.
However, if your implementation needs duplicate rows and then deleting only the first when you are trying to delete based on some condition then you might consider using the sqlite built-in column ROWID. You get all the rows that matches your condition and save the ROWID of them all. Then you delete the row that matches the ROWID you want to delete.
delete from users where ROWID = 9
Here's the developers documentation of using ROWID.
The approach I would take is to create a table where the duplicates are automatically resolved when data is inserted. Make the "name" field a primary key. Here's the CREATE statement:
CREATE TABLE users (name TEXT PRIMARY KEY ON CONFLICT IGNORE,age INTEGER);
"ON CONFLICT IGNORE" will always keep the first "name" record in the database. If you want to always keep the last record inserted, use "ON CONFLICT REPLACE". For example:
INSERT INTO users VALUES ('Jim','21');
INSERT INTO users VALUES ('Jim','23');
INSERT INTO users VALUES ('Jim','43');
If you use "ON CONFLICT IGNORE" Then "SELECT * FROM users" would produce "Jim|21". If you use "ON CONFLICT REPLACE" Then "SELECT * FROM users" would produce "Jim|43".
I have an upsert method in my Android app. It query a record by id, and if it does not exist INSERT anyway UPDATE is performed.
DB can be modified quite frequently. I do not know much about SQLite locking mechanism.
Is it possible that some lock is retained on a record and so query will not return it?
If exception occurs on an INSERT operation like:
android.database.sqlite.SQLiteConstraintException: column _id is not unique (code 19)
Can I perform an UPDATE in catch clause?
I tryed REPLACE INTO, but it has no effect. Not crashes, but has no effect:
String queryString = "REPLACE INTO " + recordType + " (" + keys + ") VALUES (" + values + ")";
statement.executeUpdateDelete(); // <-- tried all 3 option: execute, executeInsert, executeUpdateDelete
You can either use insertWithConflict() and specify SqliteDatabase.CONFLICT_REPLACE, or you can wrap your logic in a transaction:
db.beginTransaction();
try {
// query for record
// if found, update; otherwise, insert
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
I am newbie to android SQLite and i had a doubt about inserting records in sqlite.
How we can insert a record at the pirticular position into the sqlite
i,e. if i am inserting first record it will goes to the first position,Then i'll skip the second record and then insert the third record and it will store as record 3 with ID 3 as shown below
ID value
1 abc
2
3 def
4 ghi
5 jkl
6
Like this can anyone tell me how to achieve this
Create a method in your database helper class and pass the parameter . Giving you a code sample . Hope it will help you
public void updateTable(String catID, String data) {
try {
String sql = "UPDATE data_table SET column_data = " + data + " WHERE cat_id = " + catID;
mDb.execSQL(sql);
} catch (SQLException mSQLException) {
Log.e(TAG, "updateTable >>" + mSQLException.toString());
throw mSQLException;
}
}
Your best bet would be to create your table with 3 columns:
_id -> unique identifier of that entry
slot -> this is your 1 - 6 slot, you have to take care about overflow etc.
value -> your value "abc" etc.
e.g.:
CREATE TABLE
slots (_id INTEGER PRIMARY KEY AUTOINCREMENT, slot INTEGER NOT NULL, value TEXT);
Basically you could skip the _id column, but it is used in the CursorAdapter implementation, so you would run into trouble there and it doesn't hurt you.
As text can be null, you can create a scenario as the one you described above, only your slot's integer value has to be set.
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 run two transactions.
In first transaction the table test is created,
but then I say rollback for this transaction.
I think that then the table test should have been created or not,
but not something between.
Then I run the other transaction to test what has happened:
I insert one row in the table test.
That seems work in program but when I go to sqlite prompt,
I do not see the table test there when I say the command ".schema".
Can someone tell what is happening?
Output of my code is:
"Insert ok."
try
{
db.beginTransaction();
String s =
"CREATE TABLE test(id INTEGER PRIMARY KEY AUTOINCREMENT ,age INTEGER)";
db.execSQL(s);
}
catch (Exception e)
{
System.out.println("Exception 1:"+e);
}
finally
{
db.endTransaction();
}
try
{
db.beginTransaction();
db.execSQL("INSERT INTO test VALUES(NULL,22)");
db.setTransactionSuccessful();
System.out.println("Insert ok.");
}
catch (Exception e)
{
System.out.println("Exception 2:"+e);
}
finally
{
db.endTransaction();
}
Can someone tell what is happening?
It's normal behaviour. Your table wasn't created because you didn't commit TRANSACTION as well as your insert wasn't performed. Reason why you are getting result
System.out.println("Insert ok.");
is that execSQL() method throws SQLException only in the case if your query string is invalid / broken. And also you can't use execSQL() for inserting. You can use it only for altering tables.
Execute a single SQL statement that is NOT a
SELECT/INSERT/UPDATE/DELETE.
Solution:
Since execSQL() is void type you need to use API method insert() to test result.
long rowId = db.insert("test", <nullColumnHack>, values);
if (rowId < 0) {
// error
}