So I'm trying to set up a basic database with clients that have 4 fields, id, firstname, lastname and age. I have one method that puts data in and one that logs it out to make sure it's working. Here is what I have:
Right at the beginning of the MainActivity class:
SQLiteDatabase clientsDatabase;
In my onCreate method:
try
{
clientsDatabase = this.openOrCreateDatabase("Clients", MODE_PRIVATE, null);
clientsDatabase.execSQL("CREATE TABLE IF NOT EXISTS clients (id INT(3), fName VARCHAR, lName VARCHAR, age INT(3))");
}
catch(Exception e)
{
e.printStackTrace();
}
And my method that puts new data in is:
public void addMember(int id, String f, String l, int a)
{
clientsDatabase.execSQL("INSERT INTO clients (id, fName, lName, age) VALUES (" + id + ", '" + f + "', '" + l + "', " + a + ")");
}
And my method that logs the data out based on the id you give to it is:
public void printMember(int id)
{
Cursor c = clientsDatabase.rawQuery("SELECT * FROM clients WHERE id = " + Integer.toString(id), null);
int idIndex = c.getColumnIndex("id");
int fNameIndex = c.getColumnIndex("fName");
int lNameIndex = c.getColumnIndex("lName");
int ageIndex = c.getColumnIndex("age");
c.moveToFirst();
while (c != null)
{
Log.i("Results - id", Integer.toString(c.getInt(idIndex)));
Log.i("Results - First name", c.getString(fNameIndex));
Log.i("Results - Last name", c.getString(lNameIndex));
Log.i("Results - Age", Integer.toString(c.getInt(ageIndex)));
c.moveToNext();
}
c.close();
}
And FINALLY! I set up a button with the 'onClick' method of:
public void logUser(View view)
{
addMember(1, "Clark", "Kent", 30);
printMember(1);
}
The emulator crashes when I press the button, and this is what shows up in the logs(It was A LOT, so I didn't wanna make this post any longer, so I put some screenshots):
http://imgur.com/a/LpDDd
The weird thing is IT IS logging the correct information. It just crashes afterward for some reason.
And I know this isn't the best way to do this, but I really need to get this way to work, so any help is appreciated
You should change your while loop to
while (!c.isAfterLast()) {
...
}
because c never gets null, it is just moved down and down until it's out of rows in the database.
Related
As the title, I am trying to update a specific data stored in SQLiteDatabase, but it updates every item in it.
What I am trying is making a note taking app. So far it saves what I want to save properly but when I try to edit a note, the problem comes.
It changes all the saved notes when I press the edit button, including the note I wanted to edit.
The note is defined as MemoItem object i.e. MemoItem memoItem = new MemoItem(), and has following variables: String savedTime, memo, and category.
When I tap the note I want to edit it takes saved values successfully but yeah.
And just in case it is needed, here are the things that are declared in my SQLiteOpenHelper class:
public class MemoListDbHelper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "MemoListDB.db";
public static class MemoEntry implements BaseColumns {
public static final String TABLE_NAME = "entry";
public static final String COLUMN_CATEGORY = "category";
public static final String COLUMN_SAVED_TIME = "savedTime";
public static final String COLUMN_MEMO = "memo";
}
private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + MemoEntry.TABLE_NAME + " (" +
MemoEntry._ID + " INTEGER PRIMARY KEY," +
MemoEntry.COLUMN_CATEGORY + " TEXT," +
MemoEntry.COLUMN_SAVED_TIME + " TEXT," +
MemoEntry.COLUMN_MEMO + " TEXT )";
}
I made a updateNote() method inside the Helper Class:
public void updateNote(MemoItem memoItem) {
if (memoItem == null) {
return;
}
SQLiteDatabase db = getReadableDatabase();
ContentValues values = new ContentValues();
values.put(MemoEntry.COLUMN_MEMO, memoItem.memo);
db.update(MemoEntry.TABLE_NAME, values, "_id=" + MemoEntry._ID, null);
}
And the edit button is inside a Fragment called MemoFragment.
The overridden onClick method has another method named updateMemoOnClick() in it, which I made.
When the button is clicked it will make a new MemoItem object that has category, memo, and saved time that user put in and pass the object to updateNote() method above:
private void updateMemoOnClick() {
MemoItem memoItem = new MemoItem();
memoItem.memo = memoEditText.getText().toString();
memoItem.category = selectedBodyPartTextView.getText().toString();
memoItem.startedTime = startTimeTextView.getText().toString();
memoListDbHelper.updateMemo(memoItem);
}
Why is my SQLite update() updating all the items the database has?
Can anyone please help? I have been on this problem for the half of the day already. Thanks in advance!
Here you making the mistake
db.update(MemoEntry.TABLE_NAME, values, "_id=" + MemoEntry._ID, null);
replace MemoEntry._ID with your row id . like memoItem.id
db.update(MemoEntry.TABLE_NAME, values, "_id=" + [row id should be here], null);
You can try different way to update
db.update(MemoEntry.TABLE_NAME, values, "_id=?", new String[]
{String.valueOf(memoItem._ID)});
OR
db.update(MemoEntry.TABLE_NAME, values, "_id='" + memoItem._ID+"'", null);
I'm assuming that you are displaying the memo entries in a recycler view, so in order to do that you need many MemoEntry objects. You do not need the memoItem object.
You can retrieve the list of entries through a method like this:
public ArrayList<MemoEntry> getMemoEntries(SQLiteDatabase db){
ArrayList<MemoEntry> entries = new ArrayList<>();
Cursor c;
c = db.rawQuery("SELECT * FROM " + ENTRY_TABLE, null)
if(c != null && c.moveToFirst()){
while(!c.isAfterLast()){
MemoEntry entry = new MemoEntry();
entry.setId(c.getInt(c.getColumnIndex(Memo_Entry._ID)));
entry.setCategory(c.getString(c.getColumnIndex(Memo_Entry.COLUMN_CATEGORY)));
entry.setMemo(c.getString(c.getColumnIndex(Memo_Entry.COLUMN_MEMO)));
entries.add(entry);
c.moveToNext();
}
c.close();
}
return entries;
When you go to edit an entry you can reference the objects id field.
Then you can use the below query once the user saves.
db.RawQuery("UPDATE " + MemoEntry.TABLE_NAME + " SET " + MemoEntry.COLUMN_MEMO + " = " MemoEntry.memo + " WHERE " + MemoEntry.COLUMN_ID+ " = " + memoEntry._id ,null);
I think the confusion here is that you are putting column names within the MemoEntry object?
It might also be a good idea to update the saved time.
I am using following to delete a number from call log. The method works fine, but for those number which contains () and - does not work fine.
public void deleteNumber(Context context, String mobile_number) {
String Calls = "content://call_log/calls";
Uri UriCalls = Uri.parse(Calls);
Cursor cur = context.getContentResolver().query(UriCalls, null, null, null, null);
Toast.makeText(context, "The number to be deleted is: " + mobile_number, Toast.LENGTH_LONG).show();
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String query = "NUMBER='" + mobile_number + "'";
int i = context.getContentResolver().delete(UriCalls, query, null);
if (i > 0) {
Toast.makeText(context, "The number " + mobile_number + " is deleted.", Toast.LENGTH_LONG).show();
break;
}
}
}
cur.close();
}
Number which are saved in this format are not deleted. Please help me to solve this.
Edit :
The following did the trick:
mobile_number = mobile_number.replaceAll("[^0-9]","");
I am using a method, which returns a mobile number. This number contains all characters including (), spaces etc. It need to be filtered.
Replace:
String query = "NUMBER='" + mobile_number + "'";
int i = context.getContentResolver().delete(UriCalls, query, null);
with:
String query = "NUMBER=?";
String[] args={ mobile_number };
int i = context.getContentResolver().delete(UriCalls, query, args);
and see if you have better luck. ( and ) are probably reserved characters and would need to be escaped. Using query parameters would solve that for you.
I am trying view data view by unique id, I want use phone as unique id
I created following database code
public String getEmpName(String empphone) throws SQLException {
String[] columns = new String[] { EMP_ID, EMP_NAME, EMP_DOB, EMP_ADDR, EMP_PHONE };
Cursor c = ourDatabase.query(EMPINFO_TABLE_NAME, columns, EMP_PHONE + "="
+ empphone, null, null, null, null, null);
String result = "";
int iRow = c.getColumnIndex(EMP_ID);
int iName = c.getColumnIndex(EMP_NAME);
int iADDR = c.getColumnIndex(EMP_ADDR);
int iPHONE = c.getColumnIndex(EMP_PHONE);
int iDOB = c.getColumnIndex(EMP_DOB);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
result = result + c.getString(iRow) + " " + c.getString(iName)
+ " " + c.getString(iADDR)+ " " + c.getString(iPHONE)+ " " + c.getString(iDOB)
+ "\n";
}
return result;
}
employee class
public void onClick(View view){
String empname=nameedittext.getText().toString();
String empdateofbirth=dateedittext.getText().toString();
String empaddress=addressedittext.getText().toString();
String empphone=phoneedittext.getText().toString();
dbhandle=new DBhandle(this);
dbhandle=dbhandle.open();
String data=dbhandle.getEmpName(empphone);
nameedittext.setText(data);
}
The problem is that when click the button i am able to get the data uniquely but whole data is shown in same edittext ie nameedittext but i want is that phone number should be seen in phoneedittext, name should be seen on nameedittext and so on
but whole data is shown in same edittext
Yes, because you are saving it all in one String variable and setting that String to one EditText. I'm not sure why you would expect anything different.
You would need to parse each one out of that String. I would suggest creating a class, maybe Person.java. In there, you would have attributes of the data you are getting from the db. So in your getEmpName() function, you would create an instance of the Person class and set the attributes accordingly instead of saving them all to a single String variable.
Then you can call a method at the end of getEmpName() to set each EditText with that instance you created.
Alternatively,
You could do something like a HashMap and save each one in there and pull them out to set in your EditTexts.
public boolean findContact(String phoneNumber) {
boolean exists = false;
Cursor mCursor = mDb.rawQuery("SELECT * FROM " + SQLITE_TABLE + " WHERE " + KEY_PHONENUMBER + " = " + phoneNumber, null);
if (mCursor.moveToFirst()) {
exists = true;
} else exists = false;
return exists;
}
It is supose to return true when a row with telephone number exists (format is +441212312312 - String ). The problem is that it always return false, even if such a row exists. I think that a problem is with WHERE clause, but LIKE don't work either. How can I do this ?
thanks for your response
i suggest you that use query, insert, update or delete clauses directly from SQLiteDatabase object instance ;)
And see link below to know which values you will have returned
SQLiteDatabase Object
And i suggest too that if you just want if it exists don't ask about * ... ask about _id because it's primary key it has a index ;)) <-- it means faster
Here i seek a specific row:
public Cursor getEnvio(final String empresa_p, final String albaran_p) {
return db.query(Envio.KEY_ENVIO, new String[] { Envio.KEY_ID,
Envio.KEY_ALBARAN, Envio.KEY_LINEA, Envio.KEY_TIPO,
Envio.KEY_DESTINATARIO, Envio.KEY_DIR, Envio.KEY_POBLACION,
Envio.KEY_POBLACION, Envio.KEY_PRIORIDAD, Envio.KEY_INCIDENCIA,
Envio.KEY_EMP, Envio.KEY_CPOSTAL }, Envio.KEY_EMP + " = ? AND "
+ Envio.KEY_ALBARAN + " = ? ", new String[] { empresa_p,
albaran_p }, null, null, Envio.KEY_LINEA);
}
I am trying to have the user select a value, then search my database for that value, and return information from all rows containing that value.
I tried the following, but I am not sure how to return the results correctly to the other activity to be viewed by the user.
Cursor c = ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME + " = '" + favoriteWorkoutName + "'", null);
I also tried this, where the int row is specifying the KEY_ROW I want to grab data from when querying. For example, the user enters the name of a favorite workout, it then searches the database for all rows containing that name, and then returns KEY_ROWS 1, 2, and 3 (which correspond to Exercise, Reps, etc). However, this only returns one row value from one row.
int row = 1;
Cursor c = ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME + " = '" + favoriteWorkoutName + "'", null);
do{c.moveToNext();
String data = c.getString(row);
return data;
}while (row <= 3);
Any suggestions?
**EDIT:
I had already had something in my activity like that. Here is what I have there. However, I am getting an error, and it asks me to either "Change type of listCursor to Cursor", which it already is...or to "Change return type of 'GetFavoriteData' to Cursor", which is also already is.
Also, when I do get that to not have an error, I'm not sure how to use that returned data and insert it into my TextView. It will not allow me to setText(listCursor).
I ideally need to get the information from each returned row as a separate String so that I can display them the way I need to in TextViews.
In my Activity:
String favoriteWorkoutName = cfdName.getText().toString();
ExerciseDatabase choosefavorite = new ExerciseDatabase(WorkMeOutActivity.this);
try {
choosefavorite.open();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Cursor listCursor = choosefavorite.GetFavoriteData(favoriteWorkoutName);
choosefavorite.close();
in my DBHelper class:
public Cursor GetFavoriteData(String favoriteWorkoutName){
return ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME + " = '" + favoriteWorkoutName + "'", null);
}
I think you misunderstood the getString() method. Have a look:
public abstract String getString (int columnIndex)
Since: API Level 1
Returns the value of the requested column as a String.
The result and whether this method throws an exception when the column value is null or the column type is not a string type is implementation-defined.
Parameters
columnIndex the zero-based index of the target column.
Returns
the value of that column as a String.
So, if you pass 1,2 or 3 inside with c.getString(row) it only gives you value of only one column(with index 1,2 or 3) from a specific row.
You can use c.getString(c.getColumnIndex(column_name)) if you are not sure about index of a column and want to get it from it's name.
Now I think you want to retrieve value of some columns(say first 3 column value of a row) from first few matching rows(like 3 rows) and use them if so use:
Cursor c = ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME + " = '" + favoriteWorkoutName + "'", null);
String fcv="";
String scv="";
String tcv="";
if(c.getCount() == 0)
{
//no data found
}
else {
int i=0;
c.moveToFirst();
do {
fcv = fcv + c.getString(0)); //or use fcv = fcv + c.getString(c.getColumnIndex(name of first column)));
scv = fcv + c.getString(1));
tcv = fcv + c.getString(2));
i++;
} while (c.moveToNext() && i<3);
c.close();
Use the value of the strings as you like according to your need :)
Your question is not clear...
If you are trying to search all your different columns for that value your query should look more like this:
Cursor c = ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME +
" LIKE '" + favoriteWorkoutName + "' OR " + COLUMN2 + " LIKE '" + favoriteWorkoutName +
"' OR " + COLUMN3 + " LIKE '" + favoriteWorkoutName + "'", null);
That will search columns KEY_FAVNAME, COLUMN2 and COLUMN3 and return any rows that contain favoriteWorkoutName's contents.
If you want only those from the specific column, what you first posted is correct.
EDIT
After re-reading, I'm getting a different idea of what your issue is.
You should call for the cursor in the activity in which you are going to use it. The normal method is to define a DB helper class that creates the db and contains all functions related to it (adding, deleting, updating info, getting cursors, etc). Then you instantiate that class and use it's methods to work with the db.
An example would be (used in the activity where you want to access the data):
mDbHelper = new WorkoutDB(getActivity()); // instantiate your dbhelper class
mDbHelper.open(); // use the dbhelper open method to open the db
Cursor listCursor = mDbHelper.fetchFavoriteWorkout(favoriteWorkoutName); // use the fetchFavoriteWorkout method to get your cursor
Your dbhelper class would contain a method (among many others) something like this:
public Cursor fetchFavoriteWorkout(String favoriteWorkoutName){
return ourDatabase.rawQuery("SELECT * FROM FavoriteTable WHERE " + KEY_FAVNAME + " = '" + favoriteWorkoutName + "'", null);
}