SQLite Check Duplicate Records - android

public class LocalCached extends SQLiteOpenHelper{
public boolean insertNewDataSet(ArrayList<Obstacle> newObs) {
if (newObs.size() > 0) {
db = this.getWritableDatabase();
getRowsCount();
switch (checkFlag) {
case NO_RECORDS:
// this.onCreate(db);
// for (int i = 0; i < newObs.size(); i++) {
// insertNewObstacle(newObs.get(i));
// }
// break;
case THERE_IS_RECORDS:
checkDublicate(newObs.get(0), newObs.get(newObs.size() - 1));
break;
case DATA_MATCHED:
if (MatabbatManager.DEBUG)
Log.i(MatabbatManager.TAG, "Data Already Exist");
break;
case DATA_NOT_MATCHED:
// db = this.getWritableDatabase();
for (int i = 0; i < newObs.size(); i++) {
insertNewObstacle(newObs.get(i));
}
break;
default:
break;
}
db.close();
}
return true;
}
public void getRowsCount() {
dblocs = this.getReadableDatabase();
dblocs.rawQuery("SELECT * FROM " + OBSTACLES_TABLE, new String[] {});
if (cur.getCount() != 0) {
checkFlag = THERE_IS_RECORDS;
} else {
checkFlag = NO_RECORDS;
}
cur.close();
dblocs.close();
}
public void checkDublicate(Obstacle firstObstacle, Obstacle lastObstacle) {
dblocs = this.getReadableDatabase();
dblocs.rawQuery("SELECT * FROM " + OBSTACLES_TABLE, new String[] {});
cur.moveToFirst();
if (cur.getDouble(0) == firstObstacle.getLongitude()
&& cur.getDouble(1) == firstObstacle.getLatitude()) {
cur.moveToLast();
if (cur.getDouble(0) == lastObstacle.getLongitude()
&& cur.getDouble(1) == lastObstacle.getLatitude()) {
checkFlag = DATA_MATCHED;
}
} else {
checkFlag = DATA_NOT_MATCHED;
}
cur.close();
dblocs.close();
}
public void insertNewObstacle(Obstacle newObstacle) {
// db = this.getWritableDatabase();
//
db.execSQL("Insert into " + OBSTACLES_TABLE + " Values ( ' "
+ newObstacle.getLongitude() + "' , ' "
+ newObstacle.getLatitude() + "' , ' "
+ newObstacle.getDirection() + "' , ' " + newObstacle.getType()
+ "' , ' " + newObstacle.getAddress() + "' , '"
+ newObstacle.getSubmissionTime() + "' , '"
+ newObstacle.getSubmitterName() + "' )");
db.close();
}
The question is how to get read and write database or it's not possible ?
The error says that to close the connection before opening new one that's happen when i'm trying to check duplicate records(it's an array of data so i'm checking the first and the last record only).
Update:
The Exception:
A SQLiteConnection object for database '/data/data/com.nilecode.matabat/databases/localobstaclesdb' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.

The question is how to get read and write database or it's not possible ?
You can also do reads on the database returned by getWritableDatabase(). From the documentation:
Create and/or open a database that will be used for reading and writing.

As you didnt post full/compileable code i can only guess. But this should be working just fine.
public class LocalCached extends SQLiteOpenHelper {
SqlDataBase db = this.getReadableDatabase(); //Method 1
Cursor cursor = cursor.rawQuery("",null);
// check duplicate
cursor.close();
db.close();
db = this.getWritableeDatabase(); //Method 2
// do whatever
db.close();
}
You can do the check in a seperate Method, but you have to make sure that Method 1 is called before Method 2 calls getWriteableDatabase.
And if you are doing your db work in background, which seems like the smartest thing to do, since you dont want you app to hang, you might want to make your Methods synchronized to avoid multithread issues.

Related

How can I repeat a ListView item a certain number of times using Android and SQLite data and changing one column each iteration?

I am trying to repeat certain data from a table in a ListView with one row changing each iteration of the item. I want to have a user input an int of the times to repeat and press a button to update the list.
I am working with dates as the updating item. So if a user inputs '3', I want 3 rows added to the list, and inserted into the table, adding 1 month to the date for the 3 months.
Main Activity
planAheadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (planAheadMonths.getText().toString().trim().isEmpty()) {
Toast.makeText(getBaseContext(), "Add months to plan by", Toast.LENGTH_SHORT).show();
} else {
int plan = Integer.parseInt(planAheadMonths.getText().toString());
mDBHelper.updateCheckingPlanner(plan, mChecking.getCheckingId());
planAheadMonths.setText("");
mDBHelper.getTransRepeater(plan, mChecking.getCheckingId());
}
}
});
DBHelper
public void getTransactionRepeater(int repeat, int id) {
SQLiteDatabase db = this.getWritableDatabase();
String whereclause = TRANSACTION_DATE + " BETWEEN " + getCurrentMonth() + " AND " + getFutureMonth() + " AND " +
TRANSACTION_CHECKING_ID + " = " + id + " AND " + TRANSACTION_REPEAT + " != 'NONE' ";
String[] whereargs = new String[1];
Cursor res = db.query(TABLE_TRANSACTIONS, null, whereclause, null, null, null, TRANSACTION_DATE + " ASC, " + TRANSACTION_ID);
db.beginTransaction();
while (res.moveToNext()) {
if (res.getString(res.getColumnIndex(TRANSACTION_REPEAT)).equals("MONTH")) {
for (int i = 0; i < repeat; i++) {
+ i);
ContentValues cv = new ContentValues();
cv.put(TRANSACTION_NAME, res.getString(res.getColumnIndex(TRANSACTION_NAME)));
cv.put(TRANSACTION_TYPE, res.getString(res.getColumnIndex(TRANSACTION_TYPE)));
cv.put(TRANSACTION_DATE, sdf.format(cFuture.getTime()) + res.getString(res.getColumnIndex(TRANSACTION_NAME)) + i);
cv.put(TRANSACTION_AMOUNT, res.getInt(res.getColumnIndex(TRANSACTION_AMOUNT)));
cv.put(TRANSACTION_NOTES, res.getString(res.getColumnIndex(TRANSACTION_NOTES)));
cv.put(TRANSACTION_REPEAT, res.getString(res.getColumnIndex(TRANSACTION_REPEAT)));
cv.put(TRANSACTION_CHECKING_ID, res.getInt(res.getColumnIndex(TRANSACTION_CHECKING_ID)));
cv.put(TRANSACTION_NEW_BALANCE, res.getInt(res.getColumnIndex(TRANSACTION_NEW_BALANCE)));
cv.put(TRANSACTION_CREDIT_ID, res.getString(res.getColumnIndex(TRANSACTION_CREDIT_ID)));
whereargs[0] = res.getString(res.getColumnIndex(TRANSACTION_DATE));
db.insert(TABLE_TRANSACTIONS, null, cv);
}
}
}
res.close();
db.setTransactionSuccessful();
db.endTransaction();
}

Android SQLite input duplicates

I'm working on an SQLite Android app. I want to get rid of any duplicates while inserting data to the table.
My code:
Method from DatabaseHelper class (RCOL_2 is String):
public Cursor getResourceName(String condition) {
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
Cursor cursor = sqLiteDatabase.rawQuery("SELECT " + RCOL_2 + " FROM " + RESOURCE_TABLE + " WHERE " + RCOL_2 + " = " + "'" + condition + "'", null);
return cursor;
}
MainActivity:
public boolean checkResourceDuplicates(String insert) {
Cursor result = databaseHelper.getResourceName(insert);
StringBuffer buffer = new StringBuffer();
ArrayList<StringBuffer> values = new ArrayList<>();
while (result.moveToNext()) {
buffer.append(result.getString(0));
}
values.add(buffer);
for (int i=0; i < values.size(); i++) {
if(values.get(i).toString().equals(insert)){
return true;
}
}return false;
}
public void addResource() {
btnAddResource.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
if(checkResourceDuplicates(editResourceName.getText().toString())) {
Toast.makeText(MainActivity.this, "Duplicate", Toast.LENGTH_LONG).show();
}else{
boolean isInserted = databaseHelper.insertResource(editResourceName.getText().toString(), addCategoryID(spinner.getSelectedItem().toString()));
if (isInserted == true) {
editResourceName.setText(null);
Toast.makeText(MainActivity.this, "Resource added", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Resource not added", Toast.LENGTH_LONG).show();
}
}
}
}
);
}
For now, it allows to add to the database for example: 'a' and 'A'.
I tried with equalsIgnoreCase method, selecting lower from the database... and nothing. In the best case I managed to prevent adding 'AaAa' after adding 'aaaa', but adding 'aaaa' after 'AaAa' was allowed.
I tried SELECT LOWER(column_name), adding it to array list, converting insert value to lowerCase and matching these. Didn't work. I don't want to make additional trash table in my database to validate this.
if i follow your question.. you need to convert your text to lowercase then insert it into a separate column >> apply unique attribute on it.. and insert with insertWithOnConflict.. something like that.
while creating table..
KEY_NAME+" TEXT UNIQUE"
and insert data as.
db.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_IGNORE);

How to delete a row from sqlite table in recycler view items in Android?

I am trying to delete a row in sqlite database from recyclerview adapter. Based on the position of the adapter, I am deleting my row in sqlite like this :
helper = new DBHelper(v.getContext());
database = helper.getWritableDatabase();
//statement = database.compileStatement("update result set ANS =? where SNO ='" + pos + "'");
// statement = database.compileStatement("delete result where SNO ='" + pos + "'");
//statement.bindString(1, ANS);
// statement.executeInsert();
database.delete("result",
"SNO = ? ",
new String[]{Integer.toString(pos)});
Log.d("pos", "" + pos);
// helper.Delete(pos);
database.close();
but it is not deleting in my table, and I am not getting any error. What am I doing wrong?
db = this.getWritableDatabase();
int l;
l = db.delete("result", SNO = ? " , new String[]{pos+1});
if (l > 0) {
Toast.makeText(context, "Removed "+(pos+1), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
}
db.close();
Here you have pass "pos" so you have not passed right SNO(pos).
Please check SNO is passes on delete query
Try this method ,
public int deleteItem(String id) {
open();
int b = 0;
try {
b = db.delete(DATABASE_TABLE_POST_ITEMS, TAG_PLUS + " = '" + id + "'", null);
} catch (Exception e) {
e.printStackTrace();
}
close();
return b;
}
call this by using this sentence,
holder.img_plus.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
dbhelper.deleteItem((chatMessageList.get((int) v.getTag()).getListid()));
chatMessageList.remove(position);
notifyDataSetChanged();
}
});

Android sqlite how to check if a record exists

I would like to check whether a record exists or not.
Here is what I've tried:
MainActivity.class
public void onTextChanged(CharSequence s, int start, int before, int count) {
System.out.println("Ontext changed " + new String(s.toString()));
strDocumentFrom = s.toString();
if(s.toString().isEmpty()){
} else {
try{
strTransactionDate = dbHelper.getTransactionDateByDocumentNumber(strDocumentFrom);
//strTotalAmount = dbHelper.getTotalAmountByDocumentNumber(strDocumentFrom);
//strVan = dbHelper.getVanByDocumentNumber(strDocumentFrom);
//etTransactionDate.setText(strTransactionDate);
//etTotalAmount.setText(strTotalAmount);
//Log.d("Van", "" + strVan);
//etVan.setText(strVan);
} catch (SQLiteException e) {
e.printStackTrace();
Toast.makeText(ReceivingStocksHeader.this,
"Document number does not exist.", Toast.LENGTH_SHORT).show();
}
}
DBHelper.class
// TODO DISPLAYING RECORDS TO TRANSRCVHEADER
public String getTransactionDateByDocumentNumber(String strDocumentNumber){
String[] columns = new String[]{KEY_TRANSACTIONDATE};
Cursor c = myDataBase.query(TBL_INTRANS,
columns, null,
null, null, null, null, null);
if(c != null){
c.moveToFirst();
String date = c.getString(0);
return date;
} else {
Log.d("Error", "No record exists");
}
return null;
}
But it doesn't get it to the catch block to display the toast.
What am I doing wrong in here?
public static boolean CheckIsDataAlreadyInDBorNot(String TableName,
String dbfield, String fieldValue) {
SQLiteDatabase sqldb = EGLifeStyleApplication.sqLiteDatabase;
String Query = "Select * from " + TableName + " where " + dbfield + " = " + fieldValue;
Cursor cursor = sqldb.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
I hope this is useful to you...
This function returns true if record already exists in db. Otherwise returns false.
These are all good answers, however many forget to close the cursor and database. If you don't close the cursor or database you may run in to memory leaks.
Additionally: You can get an error when searching by String that contains non alpha/numeric characters. For example: "1a5f9ea3-ec4b-406b-a567-e6927640db40". Those dashes (-) will cause an unrecognized token error. You can overcome this by putting the string in an array. So make it a habit to query like this:
public boolean hasObject(String id) {
SQLiteDatabase db = getWritableDatabase();
String selectString = "SELECT * FROM " + _TABLE + " WHERE " + _ID + " =?";
// Add the String you are searching by here.
// Put it in an array to avoid an unrecognized token error
Cursor cursor = db.rawQuery(selectString, new String[] {id});
boolean hasObject = false;
if(cursor.moveToFirst()){
hasObject = true;
//region if you had multiple records to check for, use this region.
int count = 0;
while(cursor.moveToNext()){
count++;
}
//here, count is records found
Log.d(TAG, String.format("%d records found", count));
//endregion
}
cursor.close(); // Dont forget to close your cursor
db.close(); //AND your Database!
return hasObject;
}
Raw queries are more vulnerable to SQL Injection. I will suggest using query() method instead.
public boolean Exists(String searchItem) {
String[] columns = { COLUMN_NAME };
String selection = COLUMN_NAME + " =?";
String[] selectionArgs = { searchItem };
String limit = "1";
Cursor cursor = db.query(TABLE_NAME, columns, selection, selectionArgs, null, null, null, limit);
boolean exists = (cursor.getCount() > 0);
cursor.close();
return exists;
}
Source: here
SELECT EXISTS with LIMIT 1 is much faster.
Query Ex: SELECT EXISTS (SELECT * FROM table_name WHERE column='value' LIMIT 1);
Code Ex:
public boolean columnExists(String value) {
String sql = "SELECT EXISTS (SELECT * FROM table_name WHERE column='"+value+"' LIMIT 1)";
Cursor cursor = database.rawQuery(sql, null);
cursor.moveToFirst();
// cursor.getInt(0) is 1 if column with value exists
if (cursor.getInt(0) == 1) {
cursor.close();
return true;
} else {
cursor.close();
return false;
}
}
You can use SELECT EXISTS command and execute it for a cursor using a rawQuery,
from the documentation
The EXISTS operator always evaluates to one of the integer values 0
and 1. If executing the SELECT statement specified as the right-hand
operand of the EXISTS operator would return one or more rows, then the
EXISTS operator evaluates to 1. If executing the SELECT would return
no rows at all, then the EXISTS operator evaluates to 0.
I have tried all methods mentioned in this page, but only below method worked well for me.
Cursor c=db.rawQuery("SELECT * FROM user WHERE idno='"+txtID.getText()+"'", null);
if(c.moveToFirst())
{
showMessage("Error", "Record exist");
}
else
{
// Inserting record
}
One thing the top voted answer did not mention was that you need single quotes, 'like this', around your search value if it is a text value like so:
public boolean checkIfMyTitleExists(String title) {
String Query = "Select * from " + TABLE_NAME + " where " + COL1 + " = " + "'" + title + "'";
Cursor cursor = database.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
Otherwise, you will get a "SQL(query) error or missing database" error like I did without the single quotes around the title field.
If it is a numeric value, it does not need single quotes.
Refer to this SQL post for more details
SQLiteDatabase sqldb = MyProvider.db;
String Query = "Select * from " + TABLE_NAME ;
Cursor cursor = sqldb.rawQuery(Query, null);
cursor.moveToLast(); //if you not place this cursor.getCount() always give same integer (1) or current position of cursor.
if(cursor.getCount()<=0){
Log.v("tag","if 1 "+cursor.getCount());
return false;
}
Log.v("tag","2 else "+cursor.getCount());
return true;
if you not use cursor.moveToLast();
cursor.getCount() always give same integer (1) or current position of cursor.
Code :
private String[] allPushColumns = { MySQLiteHelper.COLUMN_PUSH_ID,
MySQLiteHelper.COLUMN_PUSH_TITLE, MySQLiteHelper.COLUMN_PUSH_CONTENT, MySQLiteHelper.COLUMN_PUSH_TIME,
MySQLiteHelper.COLUMN_PUSH_TYPE, MySQLiteHelper.COLUMN_PUSH_MSG_ID};
public boolean checkUniqueId(String msg_id){
Cursor cursor = database.query(MySQLiteHelper.TABLE_PUSH,
allPushColumns, MySQLiteHelper.COLUMN_PUSH_MSG_ID + "=?", new String [] { msg_id }, null, null, MySQLiteHelper.COLUMN_PUSH_ID +" DESC");
if(cursor.getCount() <= 0){
return false;
}
return true;
}
Here's a simple solution based on a combination of what dipali and Piyush Gupta posted:
public boolean dbHasData(String searchTable, String searchColumn, String searchKey) {
String query = "Select * from " + searchTable + " where " + searchColumn + " = ?";
return getReadableDatabase().rawQuery(query, new String[]{searchKey}).moveToFirst();
}
because of possible data leaks best solution via cursor:
Cursor cursor = null;
try {
cursor = .... some query (raw or not your choice)
return cursor.moveToNext();
} finally {
if (cursor != null) {
cursor.close();
}
}
1) From API KITKAT u can use resources try()
try (cursor = ...some query)
2) if u query against VARCHAR TYPE use '...' eg. COLUMN_NAME='string_to_search'
3) dont use moveToFirst() is used when you need to start iterating from beggining
4) avoid getCount() is expensive - it iterates over many records to count them. It doesn't return a stored variable. There may be some caching on a second call, but the first call doesn't know the answer until it is counted.
Try to use cursor.isNull method.
Example:
song.isFavorite = cursor.isNull(cursor.getColumnIndex("favorite"));
You can use like this:
String Query = "Select * from " + TABLE_NAME + " where " + Cust_id + " = " + cust_no;
Cursor cursorr = db.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursorr.close();
}
cursor.close();
private boolean checkDataExistOrNot(String columnName, String value) {
SQLiteDatabase sqLiteDatabase = getReadableDatabase();
String query = "SELECT * FROM" + TABLE_NAME + " WHERE " + columnName + " = " + value;
Cursor cursor = sqLiteDatabase.rawQuery(query, null);
if (cursor.getCount() <= 0) {
cursor.close();
return false; // return false if value not exists in database
}
cursor.close();
return true; // return true if value exists in database
}
I prefer to do it this way because it's fast and less expensive than other methods:
Cursor cursor = db.rawQuery("SELECT 1 FROM table WHERE condition = 1 LIMIT 1", null);
try {
if (cursor.moveToNext()) {
//Record exists
} else {
//Record doesn't exists
}
} finally {
cursor.close();
}
My version:
public boolean isTitleExists(String title, String type) {
int isExists = 0;
try {
String query = "SELECT EXISTS (SELECT 1 FROM titles WHERE title = ? and type = ?)";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, title);
statement.setString(2, type);
ResultSet rs = statement.executeQuery();
rs.next();
isExists = rs.getInt(1);
rs.close();
statement.close();
} catch (SQLException e) {
Common.console("isTitleExists error: " + e.getMessage());
}
return isExists == 1;
}

Android Application did not close cursor or database

Im running into an issue inserting items into my database. It really odd that the program will run through 4 rows and insert them fine, but on the 5th row it crashes and I got three reports of Application did not close cursor or database. In my code I am closing and reopening both the cursor and the database so I am really confused on how this is happening. Here is the code.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_CODE_NEW:
if (resultCode == -1) {
Integer chapterId = data.getIntExtra("chapterId", -1);
Toast toast = Toast.makeText(this, "Selected Chapter: " + chapterId.toString(), Toast.LENGTH_LONG);
if (chapterId != -1) {
DbHelper db = new DbHelper(this);
for (int i = 0; i < questions.getTitle().size(); i++) {
db.insertQuestion(chapterId.toString(), questions.getTitle().get(i), questions.getAnswer().get(i), questions.getAr().get(i));
}
}
toast.show();
}
break;
}
}
Thats calling the database to be created through a dbhelper class. Here is the database helper
public void insertQuestion(String cat_id, String title, String answer, String article) {
db.execSQL("INSERT INTO " + QUESTION_TABLE_NAME + " (title,answer,article,picture) VALUES ('" + title + "','" + answer + "','" + article + "','none')");
String id = getQuestionId(title);
db.execSQL("INSERT INTO " + REL_TABLE_NAME + " (question_id, cat_id) VALUES (" + id + "," + cat_id + ")");
}
public String getQuestionId(String title) {
String id;
cursor = this.db.rawQuery("SELECT question_id FROM " + QUESTION_TABLE_NAME + " WHERE title = '" + title + "' LIMIT 1", null);
cursor.moveToFirst();
id = cursor.getString(0);
cursor.close();
db.close();
return id;
}
I put the cursor at the class level so I can try to manage it better, but still to no avail. Its still crashing after 4 queries.
Try this "fix":
DbHelper db = new DbHelper(this);
try{
for (int i = 0; i < questions.getTitle().size(); i++) {
db.insertQuestion(chapterId.toString(), questions.getTitle().get(i), questions.getAnswer().get(i), questions.getAr().get(i));
}
}catch(Exception e1){
android.util.Log.v("DbHelper Error","Crash: "+e1.getMessage(), e1);
}finally{
db.close();
}

Categories

Resources