Android : SQLite check if data exist and update - java

I now sure what i'm doing wrong because java and SQLite for me new. So I need to make check when user is entering new data to DB if data with such "day" and "week_type" exists it need to be updated , else create new row.
public long creatEntry(int day2, int week_type2,
String desc2, String place2, String lessnum2) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues() ;
String update = "SELECT * FROM info WHERE day="+day2+" AND week_type="+week_type;
Cursor cr = ourDatabase.rawQuery(update, null);
if(cr!= null){
cv.put(day, day2);
cv.put(week_type, week_type2);
cv.put(desc, desc2);
cv.put(place, place2);
cv.put(lessnum, lessnum2);
return ourDatabase.update(DATABASE_TABLE,cv, day+ "=" +day2+ " AND "+week_type+ "=" +week_type2, null);
}
else{
cv.put(day, day2);
cv.put(week_type, week_type2);
cv.put(desc, desc2);
cv.put(place, place2);
cv.put(lessnum, lessnum2);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
}

Use replace. It'll try to insert first, and if it happens to conflict due to a key constraint, it'll delete and insert those values. In your case, these two columns must be unique. Check it out:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#replace(java.lang.String, java.lang.String, android.content.ContentValues)

Related

Is there a way when Migrating a Room Database to use Variables that are calculated during the Migration?

I'm writing an Android App in Java and I've changed my Database and now I want to migrate it to the new version but to do that I need to compute some of the old values and then insert those into one of the new tables into the db but when I call
database.execSQL()
with my variables and then access them it appears to not have set them as every value is 0.
Is it just not possible or did I simply miss something?
public void migrate(#NonNull SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE 'season' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
'spring' INTEGER DEFAULT 0, 'summer' INTEGER DEFAULT 0, 'autumn' INTEGER
DEFAULT 0, 'winter'
INTEGER DEFAULT 0, 'spook' INTEGER DEFAULT 0)");
database.execSQL("INSERT INTO 'Clothes' (type_of_clothing,clothing_name,description,seasonId,in_laundry,TypeList) " +
"SELECT type_of_clothing,clothing_name,description,type_of_clothing,in_laundry,TypeList " +
"FROM ClothesNew");
Cursor cursor = database.query("SELECT * FROM Clothes");
Cursor secondCursor = database.query("SELECT * FROM ClothesSeason");
ArrayList<Season> seasonsToBeAdded = new ArrayList<>();
while (cursor.moveToNext()) {
secondCursor.moveToNext();
int Sid = cursor.getInt(0);
String seasonString = secondCursor.getString(2);
Season season = new Season(seasonString);
int tempId = Sid;
boolean isInList = false;
for (Season tempSeason : seasonsToBeAdded) {
if (tempSeason.equals(season)) {
tempId = seasonsToBeAdded.indexOf(tempSeason);
isInList = true;
break;
}
}
if (!isInList) {
season.setId(seasonsToBeAdded.size());
tempId = season.getId();
seasonsToBeAdded.add(season);
}
if (seasonsToBeAdded.size() == 0) {seasonsToBeAdded.add(season);}
database.execSQL("UPDATE Clothes SET seasonId = :tempId WHERE uid = :Sid");
}
int id, spring, summer, autumn, winter, spook;
for (Season season : seasonsToBeAdded) {
id = season.getId();
spring = season.getSpring();
summer = season.getSummer();
autumn = season.getAutumn();
winter = season.getWinter();
spook = season.getSpook();
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
}
Cursor otherCursor = database.query("SELECT * FROM season");
ArrayList<Integer> springValues= new ArrayList<>();
while (otherCursor.moveToNext()) {
springValues.add(otherCursor.getInt(1));
}
}
When I look at the Values stored in springValues they are all 0 even though I add the correct ones in this query
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
Can I just not use the :var notation here?
I'd suggest utilising The SQLiteDatabase Insert convenience method along with a ContentValues object.
Instead of :-
for (Season season : seasonsToBeAdded) {
id = season.getId();
spring = season.getSpring();
summer = season.getSummer();
autumn = season.getAutumn();
winter = season.getWinter();
spook = season.getSpook();
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
}
Your code could then be :-
ContentValues cv = new ContentValues(); // Instantiate ContentValues object
for (Season season : seasonsToBeAdded) {
cv.clear();
cv.put("`id`",season.getId());
cv.put("`spring`",season.getSpring());
cv.put("`summer`",season.getSummer());
cv.put("`autumn`",season.getAutumn());
cv.put("`winter`",season.getWinter());
cv.put("`spook`",season.getSpook());
database.insert("season",null,cv); //<<<< Recommended Uses the convenience Insert Method
Note there should be no need to enclose the column names in grave accents `` as used above.
The above code is in-principle code and has not been tested, as such it may contain some errors.
As you can see the SQL is built for you. The insert method returns the rowid (id column) of the inserted row or -1 if the insert failed, you may wish to take advantage of this value.
You may also wish to utilise other insert methods e.g. insertWithOnConflict e.g. database.insertWithOnConflict("season",null,cv,SQLiteDatabase.CONFLICT_IGNORE);
It would also be advisable to utilise transactions by utilising the appropriate SQLiteDatabase transaction handling methods (see beginTransaction)
It also also recommended that you utilise constants for column names so the name is coded in just on place. So little chance of getting the column names wrong.

How to get the phone contacts in a hashmap and store it locally and use it anywhere in the project?

I am trying to get the phone contacts and store it in a Hashmap. I want to save that locally and use it anywhere in the project.
Following is my code to get phone contacts:
public HashMap getPhoneContacts() {
ArrayList contactList=null;
ContentResolver cr = getContext().getContentResolver(); //Activity/Application android.content.Context
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null
, null, null, null);
if(cursor.moveToFirst())
{
contactList = new ArrayList<String>();
do
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String contactName=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if(Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{ id }, null);
while (pCur.moveToNext())
{
String contactNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//String contactId = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String noramliseNum;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
noramliseNum = PhoneNumberUtils.normalizeNumber(contactNumber);
}else{
noramliseNum=contactNumber.replaceAll("\\s","");
}
phoneContacts.put(noramliseNum,contactName);
break;
}
pCur.close();
}
} while (cursor.moveToNext()) ;
}
return phoneContacts;
}
Its already taking lot of time to fetch all the contacts. So I dont want to call this function again and again from other classes. Instead I need to call the function only once,and then store it in a Hashmap locally and use it whenever we want,so that it wont take time to fetch the details again.
Please help.
You could put it into SharedPreferences if you don't want to re-download every time you start the app. Then, once the data is retreived, you could have a Singleton class to hold your Hashmap.
If you have many contacts, you should consider using a database.
Take a look at https://developer.android.com/guide/topics/data/data-storage.html
This would be more efficient than keeping everything in memory.

Cursor is only returning one value, not all values

I have encountered a problem in my Android application. I want to retrieve all values of a column, but I am only getting one of the values. I have tried everything, but I could still not find a solution. Here is my code in my database:
public Cursor returnAllColumns() {
Cursor cursor = mDb.query(FTS_VIRTUAL_TABLE,
new String[] {KEY_ROWID,
KEY_NAME,
KEY_CUSTOMER, PROTEIN, TOTAL_CARB}
, null, null, null, null, null);
if (cursor != null) {
cursor.moveToNext();
}
return cursor;
}
Here is my code in another class where it shows a toast with all the values.
mDbHelper = new DBAdapter(DatabaseFiller.this);
mDbHelper.open();
Cursor c = mDbHelper.returnAllColumns();
String protein = c.getString(c.getColumnIndexOrThrow("protein"));
Toast.makeText(getApplicationContext(), protein, Toast.LENGTH_SHORT).show();
All I am getting is Protein = 0. What I should be getting is 0, 0, 0, 0, 0, 0,.... I don't know what I am doing wrong here. In my ListView, I got it right. It worked perfectly there. Here is my ListView code:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
cursor = (Cursor) mListView.getItemAtPosition(position);
//mListView.setItemChecked(position, true);
// Get the state's capital from this row in the database.
String name = cursor.getString(cursor.getColumnIndexOrThrow("customer"));
String caloriescursor = cursor.getString(cursor.getColumnIndexOrThrow("name"));
String totalfat = cursor.getString(cursor.getColumnIndexOrThrow("address"));
String satfatcursor = cursor.getString(cursor.getColumnIndexOrThrow("city"));
String state = cursor.getString(cursor.getColumnIndexOrThrow("state"));
String zipCode = cursor.getString(cursor.getColumnIndexOrThrow("zipCode"));
And that returns a Toast with a bunch of values. Any help regarding this problem would be appreciated.
In getAllColumns(), your query statement is correct. It does in fact fetch all columns. The if statement that follows simply points it to the first result. Then you are returning the cursor while it is pointed to the first result. You should take out the if statement because it doesn't do anything useful.
When trying to show the toast, you want something like this:
Cursor c = mDbHelper.returnAllColumns();
ArrayList<String> protein = new ArrayList<>();
while (c.moveToNext()) {
protein.add(c.getString(c.getColumnIndexOrThrow("protein")));
}
Toast.makeText(getApplicationContext(), TextUtils.join(", ", protein), Toast.LENGTH_SHORT).show();
You need to loop over the cursor if the cursor is returning more than one row, and build your output in the loop.
Keep calling c.moveToNext() until it returns false.
I had the same problem until I did this:
if (!cursor.moveToFirst()) {
Log.d(LOG_TAG, "=== cursor not moveToFirst() ===");
return null;
}
Log.d(LOG_TAG, "=== reading cursor of getAll() ===");
Log.d(LOG_TAG, String.valueOf(cursor));
List<Trip> trips = new ArrayList<>();
while (!cursor.isAfterLast()) {
trips.add(cursorToTrip(cursor));
cursor.moveToNext();
}
The cursor.moveToNext() will never check the first element. So I check in the course is not in the last one and then I add the object and move to the next one.
That's it! :)

cursor.getCount always = 0

I need to implement an algorithm that access to the database to check the last elemnt in order to calculate the new one. Of course, the first time it would be impossible because the database is empty and I get
IndexOutOfBoundsException) index 0 requested with a size of 0
To avoid it, I tried to check if cursor.getCount==0, and then I introduce a default first element. The problem is that, even when I have stored it in the database, cursor.getCount keeps being 0. Here is the code of my method:
public Measures getLastMeasure(String date) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_MEASURES, new String[] { KEY_ID,
KEY_DATE, KEY_TIME_HOUR, KEY_TIME_MINUTE, KEY_BE_INTAKE,
KEY_GLUCOSE, KEY_BOLUS, KEY_BASAL }, KEY_DATE + "=?",
new String[] { date }, null, null, KEY_TIME_HOUR + " DESC, "
+ KEY_TIME_MINUTE + " DESC", "1");
if (cursor.getCount() == 0) {
Measures m = new Measures("nodate", 0, 0, 0, 0, 0, 0);
return m;
} else {
if (cursor != null)
cursor.moveToFirst();
Measures m = new Measures(Long.parseLong(cursor.getString(0)), // id
cursor.getString(1), // date
Integer.parseInt(cursor.getString(2)), // timeHour
Integer.parseInt(cursor.getString(3)), // timeMinute
Double.parseDouble(cursor.getString(4)), // BE intake
Double.parseDouble(cursor.getString(5)), // glucose
Double.parseDouble(cursor.getString(6)), // bolus
Double.parseDouble(cursor.getString(7)) // basal
);
// return m
return m;
}
}
I hope you can help me. Thanks in advance to everyone.
I could be missing something, but that code looks correct to me. Are you certain that the data you're looking for is actually in the database and that the argument you're passing to getLastMeasure() is correct?
Looks like your query returns no data matching your search. If you only want latest data by date, I suggest order by KEY_DATE desc and limit 1, or max(KEY_DATE) instead of KEY_DATE + "=?"
Side note: no need to check if cursor is null (SQLiteDatabase#query never returns a null Cursor), and anyway your check is useless because you're accessing cursor even if it's null. Also you're not closing the Cursor.

SQLite date query returns no record

I am developing an Android application where I search for records which are created after a given date. My code is some thing like this
public List<NPRMember> IncrementalData(String LastDtTime) {
List<NPRMember> results = new ArrayList<NPRMember>();
SQLiteDatabase db=getMyReadableDatabase();
String lastdt="datetime("+LastDtTime+")";
Cursor cursor = null;
try{
cursor = db.query(TABLE_NAME_NPR, new String[] { KEY_FULLNAME, KEY_FATHERNAME,
KEY_RCRD_SOURCE,KEY_RCRD_CRN_DATE},KEY_RCRD_CRN_DATE + ">? AND "+KEY_RCRD_SOURCE+">?",
new String[]{lastdt, "0"}, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
NPRMember nprmem = cursorToMemberDetails(cursor);
results.add(nprmem);
cursor.moveToNext();
}
}catch(Exception e){
Log.e(APP_NAME, "An error occurred while searching for "+LastDtTime+": "+e.toString(), e);
}finally{
if(cursor!=null && !cursor.isClosed()){
cursor.close();
}
}
return results;
}
The query does not return any value, although I have at least one record with KEY_RCRD_CRN_DATE 2013-07-25 18:59:19
The LastDtTime passed as parameter has value 2013-07-25 14:46:03.
One interesting thing is if I run the query at SQLite command prompt it returns the deisred record.
SELECT fullname, fathername, .... rcrdsource, rcrdcrtndate FROM nprmembers WHERE rcrdcrtndate>'2013-07-25
14:46:03' AND rcrdsource>0;
Any help would be appreciated.
Thanks
The parameter value (in lastdt) is wrong.
What you want is the string 2013-07-25 18:59:19, but you are actually using the string datetime(2013-07-25 18:59:19).
The letter d comes after 2, so no record matches.
Change the initialization of lastdt to:
String lastdt=LastDtTime;

Categories