My Create table Query is:--
String CREATE_LOGIN_TABLE ="CREATE TABLE IF NOT EXIST "+ TABLE_FORWARDMSG +"("+KEY_ID+ " INTEGER PRIMARY KEY AUTOINCREMENT,"+KEY_MSG_BODY+ " TEXT UNIQUE,"+KEY_MSG_ADDRESS+" TEXT UNIQUE,"+KEY_MSG_DATE+" TEXT UNIQUE" +")";
and I am access values From This Code:---
String selectQuery="SELECT * FROM "+TABLE_FORWARDMSG;
SQLiteDatabase db=this.getReadableDatabase();
Cursor cursor=db.rawQuery(selectQuery, null);
if( cursor.moveToFirst()){
for(int i=0;i<cursor.getCount();i++){
map.put("msgBody", cursor.getString(1));
map.put("msgAddress", cursor.getString(2));
map.put("msgDate", cursor.getString(3));
user.add(map);
cursor.moveToNext();
}
}
cursor.close();
db.close();
Now My Problem is that:----
If I remove UNIQUE from the CREATE TABLE Then I get all duplicate values means if I insert same value it create new row, and if I am using UNIQUE in CREATE TABLE, then every time cur.getCount() value is 1. I am new in SQLite. Please tell me whats the problem.
Your code looks like Ok. Maybe you shouldn't make KEY_MSG_DATE like UNIQUE. Try to get more info about what you want to do.
What you have implemented is that in every entry in every column has to be unique within the column but I assume what you want is that the row containing the columns msgBody, msgAddress and msgDate has to be unique within the table.
You can achieve that by placing all columns together in the UNIQUE clause:
UNIQUE(msgBody, msgAddress, msgDate) ON CONFLICT REPLACE
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 am adding a new column to an existing table and adding a new entry to the table with valid data present only in new column (other column being 0 by default)
Adding Column :
final String DB_ADD_COLUMN_STATEMENT_TABLE_SHOP_NAME =
"ALTER TABLE "+ shopName + " ADD COLUMN "+ "D" + time + " FLOAT";
try {
mDB.beginTransaction();
//SQLiteStatement statement = mDB.compileStatement(DB_ADD_COLUMN_STATEMENT_TABLE_SHOP_NAME);
//statement.execute();
mDB.execSQL(DB_ADD_COLUMN_STATEMENT_TABLE_SHOP_NAME);
mDB.setTransactionSuccessful();
}
catch (Exception e) {
Log.d(LOG_TAG,"addItemSample : Exception while adding column to table!!");
}
finally {
mDB.endTransaction();
}
Adding a new entry to the table with data only in this column succeeds.
But when I query the table , this new column doesn't show up in the cursor.
Though the adding column and querying happen in different threads, they are serialized from the way they are being called from my code (ie first column is added and then db is queried) and also the I am using a single connection to db.
I wondering what might be reason for this?
PS:When db query is performed immediately after inserting the column , it shows up.
depends on your query statement.
is it like
String query="select id, column1, column 2 from "+shopName+" where yourcondition";
?
may be you have to add column?
String query="select id, column1, column2, D192200 from "+shopName+"";
or you may query all columns
String query="select * from "+shopName+"";
The issue could be that you are adding a column that expects NOT NULL values
Try something like this:
ALTER TABLE "+ shopName + " ADD COLUMN "+ "D" + time + " FLOAT" default 0 NOT NULL;
Use which ever default value you need and update the values as needed.
I have an app that allows the user to save some chosen rows from a temporary table. The user is able to name the new table.
I am successfully creating a table using the name the user has input, and putting all the chosen rows from the temporary table into the new table.
However, if the table name they enter already exists, I want to notify them via Toast and have them choose another name. I am still learning sqlite - is there a way to do this?
In my head I am using some sort of if statement to check if the table exists, and then executing code, however half of it is in sqlite and half is in java. I'm not sure the correct way to do this. Any suggestions are greatly appreciated!
private void createTable() {
dbHandler.getWritableDatabase().execSQL("CREATE TABLE IF NOT EXISTS " + favoriteName + " ( _id INTEGER PRIMARY KEY AUTOINCREMENT , exercise TEXT , bodypart TEXT , equip TEXT );");
dbHandler.getWritableDatabase().execSQL("INSERT INTO " + favoriteName + " SELECT * FROM randomlypicked");
Try
Cursor cursor = dbHandler.getReadableDatabase().rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName +"'", null);
if(cursor!=null) {
if(cursor.getCount()>0) { //table already exists
//show toast
cursor.close();
return;
}
cursor.close();
}
//create table and insert normally
I have created a sqlite table for my android app, this table has 5 columns and multiple rows, the columns being: _id, column1, column2, column3, column4.
I want to delete a specific record, for instance the record stored in column3 corresponding to _id (in a different class are the getters and setters, for this I've named the class "TableHandler")
I guess that I'm a bit confused, following is what I was planning, but for column3 I'm not sure what should be the argument, I just want to delete whatever is in that column position corresponding to _id
public void deleteValueColumn3(TableHandler value){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + " = ? AND " + KEY_COLUMN3 + " = ?",
new String[] {String.valueOf(value.getID()), ?????????);
db.close();
}
The ???????? is that I'm stuck there, maybe the whole method needs to be rewritten, I would appreciate your input.
Thanks
If you want to delete the whole record, just use the _id of the record in delete method, because that is the primary key for your table and therefore is unique. If you'd rather keep the record, you con always use the SQLiteDatabase.update method, specifying null as the new value that will replace column3 value; check out that column3 declaration has no NOT NULL tag, otherwise that could easily throw exception at you.
SQLite does not allow you to delete columns for a specific row.
You can only delete ROWS of data (delete the row that has the column _ID = 1).
Here's a quick tutorial on SQL.
How about updating that column with a null value, rather than using delete()?
ContentValues cv = new ContentValues();
cv.putNull(KEY_COLUMN3);
db.getWritableDatabase().update(
TABLE_NAME,
cv,
KEY_ID + "=?",
new String[]{String.valueOf(keyIdValue)});
I have a database that is being filled by user defined EditTexts. None of the edit texts should allow empty fields. I know that I can check for this with a couple simple if-statements: if myEditText.getText().toString().equals("") // display error. However I would perfer to use this opportunity to brush up on my SQLite and error catching (as demonstrated in my add method). How would I go about altering the columns in the table below to NOT NULL and generating/catching an error when a user attempts to add/update with empty fields?
My database table:
db.execSQL("CREATE TABLE inventory (category TEXT, itemNum TEXT, quantity INTEGER, price REAL, image INTEGER, UNIQUE(category, itemNum) ON CONFLICT FAIL);");
My add method:
... fill ContentValues values
try{
db.getWritableDatabase().insertWithOnConflict(DatabaseHelper.TABLE_NAME, DatabaseHelper.CATEGORY, values, SQLiteDatabase.CONFLICT_FAIL);
fillItemNumbers();
}
catch(SQLiteConstraintException e)
{
Toast
.makeText(MyActivity.this, etItemNum.getText().toString() + " already exists in " + catSpinner.getSelectedItem().toString() +". Consider using Update.",Toast.LENGTH_LONG)
.show();
}
My update method:
... fill ContentValues values
String[] args = {catSpinner.getSelectedItem().toString(), etItemNum.getText().toString()};
int rowsAffected = db.getWritableDatabase().update(DatabaseHelper.TABLE_NAME, values, DatabaseHelper.CATEGORY + "=? AND " + DatabaseHelper.ITEM_NUMBER + "=?" , args);
UPDATE:
I did a little digging and came up with this:
db.execSQL("CREATE TABLE inventory (category TEXT NOT NULL, itemNum TEXT NOT NULL, quantity INTEGER NOT NULL, price REAL NOT NULL, image INTEGER NOT NULL, UNIQUE(category, itemNum) ON CONFLICT FAIL);");
Is this what I am looking for? If so, how can I use this to my advantage (see above)?
I am not sure if you can actually Alter Column Definition for table. I know you can Alter Table itself, like adding new Column to Table. You might need little trick to modify your database if there is lot of data in it that you want to preserve.
One way to it to create new table and try copying data to new table and afterwards remove old table and rename new Table. It's not most efficient way to do it but it'll get the job done though.
http://www.sqlite.org/lang_altertable.html
EDIT
Here you go
CREATE TABLE inventory (category TEXT not null, itemNum TEXT not null, quantity INTEGER not null, price REAL not null, image INTEGER not null, UNIQUE(category, itemNum) ON CONFLICT FAIL);
EDIT 2
Try this
CREATE TABLE inventory (category TEXT not null ON CONFLICT FAIL, itemNum TEXT not null ON CONFLICT FAIL, quantity INTEGER not null ON CONFLICT FAIL, price REAL not null ON CONFLICT FAIL, image INTEGER not null ON CONFLICT FAIL, UNIQUE(category, itemNum) ON CONFLICT FAIL);
All you need to do is set the columns to NOT NULL.
Then use
insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)
and
updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)`
There are several constants you can use for the conflictAlgorithm, depending on exactly what you want to happen. If you want to simply not enter the data into the table, CONFLICT_IGNORE will do the trick. If you want a return code letting you know so you can act on it (let the user know) then you might want CONFLICT_FAIL.
See this for further information.
Hope this helps.