Making a better android sqlite query - java

Currently I have a query that looks at the table and returns the newest row, reads that row and sets the string to the value in the chosen column index.
At the moment I have 9 columns so I have end up making 9 methods for returning each column just to return a string and set it to each individual textview.
Do I make a cursor to return the row and then set the column index when I am setting the textviews. Something like
cursor.getString(1)
This is my current query
public String getName() {
// TODO Auto-generated method stub
String[] columns = new String[] { KEY_ROWID, KEY_NAME, KEY_COLUMN2,
KEY_COLUMN3, KEY_COLUMN4, KEY_COLUMN5, KEY_COLUMN6, KEY_COLUMN7, KEY_COLUMN8 };
Cursor c = mDb.query(true, DATABASE_TABLE, columns, null, null, null,
null, "_id DESC", "1");
if (c != null) {
c.moveToFirst();
String name = c.getString(1);
return name;
}
return null;
}

You could easily change getName() to something field-agnostic, such as:
public String getField(String fieldName) {
...
String s = cursor.getString(cursor.getColumnIndexOrThrow(fieldName));
}
And use it like:
String s = mDb.getField(mDb.KEY_NAME);
A problem with this approach is that you can't use getString() for a numerical column, so you wind up with multiple methods for each datatype supported in your table. A way to tackle this is to look into the cursor's getType() method or just return a complete data structure from your database access methods. Say you have:
DB Column Field Type
FOO varchar
BAR integer
BAZ varchar
If you define a class, say, MyRowMapper you can do something like this:
public MyRowMapper getRow(String... queryParameters) {
//query table based on queryParameters
MyRowMapper mapper = null;
if (cursor.moveToFirst()) {
String foo = cursor.getString(cursor.getColumnIndexOrThrow("FOO"));
Integer bar = cursor.getInteger(cursor.getColumnIndexOrThrow("BAR"));
String baz = cursor.getString(cursor.getColumnIndexOrThrow("BAZ"));
mapper = new MyRowMapper(foo, bar, baz);
}
cursor.close(); // NEVER FORGET TO CLOSE YOUR CURSOR!
return mapper;
}
This is just abstract mailercode, so take the syntaxt with a grain of salt. But hopefully you get the idea.

Related

How to get number of particular name in sqlite table by query

I have a table in which name and number of people are stored. Now I want to make a method in sqlite helper class which will return the number of particular person whose name I will pass in the method
There is something wrong with my code.
Here is my code
public String fetchGroup(SQLiteDatabase inDatabase, String valueCheck){
String query = "SELECT * FROM groups WHERE groupname='" + valueCheck;
Cursor cursor = inDatabase.rawQuery(query,null);
String place = cursor.getString(cursor.getColumnIndex("contactid"));
return place;
Take care to use cursor.moveToFirst() command before reading datas
Else, instead counting the number of people in Java, you can just modify your query to have only this number return.
Something like this :
public String fetchGroup(SQLiteDatabase inDatabase, String valueCheck){
String query = "SELECT COUNT(id) FROM groups WHERE groupname=\"" + valueCheck + "\"";
Cursor cursor = inDatabase.rawQuery(query, null);
cursor.moveToFirst();
int place = cursor.getInt(0);
return String.valueOf(place);
}
After your query do
int count = 0;
while (cursor.moveToNext()) {
// increment variable
count++;
}
after iterating you will get number of count

SQLITE update ROW not working

im trying to update specific row but no luck.
Im first time working with sqlite, maybe its true im confused with column/row
In ideal i want update text in field with name MESSAGE_HISTORY(id=5)
Same way and code works for field Item0 (id = 1)
public static void updateHistory(ArrayList<MessageModel> models, String id) {
if (database != null) {
Cursor c = database.query(TDatabaseHelper.DATABASE_TABLE,null,null, null, null, null, null);
if (c.moveToFirst()) {
do {
int index1 = c.getColumnIndex(MESSAGE_HISTORY);//return position 5
ContentValues data = new ContentValues();
data.put(MESSAGE_HISTORY, DatabaseHelper.chatHistoryModelsConvert(models, id).toString());
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=" + index1, null);
DBLogger.w("DATABASE UPDATE STATUS = "+k);
}while(!c.moveToFirst());
}else {
DBLogger.d("Error");
}
}
}
K always return 0
Any help ?
[UPD]
public static void CreateDB() {
if (database != null) {
Cursor c = database.query(TDatabaseHelper.DATABASE_TABLE, null, null, null, null, null, null);
if (!c.moveToFirst()) {
cv.put(TDatabaseHelper.ITEM0, "Item0"); // <---- this item update very good index = 1
cv.put(TDatabaseHelper.MESSAGE_HISTORY, "history"); <-- cant update, index = 5;
cv.put(TDatabaseHelper.ITEM1, "item1");
cv.put(TDatabaseHelper.ITEM2, "item2");
cv.put(TDatabaseHelper.ITEM3, "item3");
long rowID = database.insert(TDatabaseHelper.DATABASE_TABLE, null, cv);
DBLogger.i("row inserted, ID = " + rowID);
}
}
}
[UPD]
this not help :(
String[] args = new String[]{""+index1}; ??database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=?", args);
The following line gives you the index of the column named MESSAGE_HISTORY but it does not give you the value.
int index1 = c.getColumnIndex(MESSAGE_HISTORY);//return position 5
As a result of this, your line
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data, "id=" + index1, null);
updates a row that has an id of "5" and it seems that it does not exist. You need to get the value in column 5, so do something like the following:
String messageValue = c.getString(index1);
long k = database.update(TDatabaseHelper.DATABASE_TABLE, data,
MESSAGE_HISTORY + " = ?", new String[] {messageValue});
It is better to use the whereArgs here since just appending messageValue may cause problems. See the update documentation regarding the whereClause and whereArgs.
In any case, slap the debugger on that last line to see exactly what you are passing to the update method. You may be surprised.

RawQuery doesn't work when given null valueto args

I'm writing a basic android app in which personal information like name, email, etc. is filled in and stored in an SQLite database by pressing a "submit"-button (this all works perfectly). Then there's a search button which should search for a corresponding person in the database when one field is filled in (e.g. only the field name is given a string "harry" and the other fields keep a null-value). This is the corresponding code in my DatabaseHelper class:
public Person getPerson(String naam, String adres, String email, String geslacht,
String leeftijd, String geboortedatum){
Log.i("Main activity","Person to find: "+naam);
SQLiteDatabase db= this.getReadableDatabase();
Cursor curs=db.rawQuery("SELECT name FROM personen WHERE (name = ?) OR (adress = ?) "
+ "OR (email = ?) OR (gender = ?) OR (age = ?) OR (birthday = ?)",
new String[]{naam, adres, email, geslacht, leeftijd, geboortedatum});
Log.i("Main activity", "Query works");
I used the logs to make sure where the error is thrown and found that the rawQuery does work when all the args[] fields are given a value, but gives an error when one field (e.g. email) contains a null value. Isn't this why I should use the OR statement instead of the AND statement? If not, how can I make it work when not all fields are filled in in the app?
A fast fix should be to do something like that:
new String[]{naam == null? "''":naam, etc}
Check if your sting is initialized, if it is not, replace it by a dummy value.
rawQuery() expects a string array, but null is not a valid string.
You'd have to put the NULL directly into the SQL string, without a parameter.
But when you're constructing the string dynamically anyway, you can just as well leave out that comparison.
search by name:
// Getting single contact
Contact getContact(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID,
KEY_NAME, KEY_PH_NUM }, KEY_NAME + "=?",
new String[] { name }, null, null, null, null);
//...
for access:
Contact contact = null;
if (cursor.moveToFirst()) {
contact = new Contact(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2));
}
cursor.close();
// can return null if no contact was found.
return contact;

SQLite Cursor getColumnIndex() returning -16 even when column exists

I'm storing a number of objects for my app in an SQLite Database. The class for these objects has a constructor that takes a Cursor object, passed in from the Database class. Example:
public MyClass(Cursor cursor) {
this.id = cursor.getString(cursor.getColumnIndex(MyDatabase.KEY_ROWID));
this.nickname = cursor.getString(cursor.getColumnIndex(MyDatabase.KEY_NICKNAME));
...and so on.
However I've noticed that at random times I've been getting a crash when getColumnIndex for the ID column returns -16. (And if I comment out that line, whichever the first column I try to access is, it will also return -16). I've added some extra logging around it but it hasn't helped as it seems like the columns are fine:
public MyClass(Cursor cursor) {
Log.i("TEST", Column names are: " + Arrays.toString(cursor.getColumnNames()));
Log.i("TEST", Making object, id column index is " + cursor.getColumnIndex(MyDatabase.KEY_ROWID));
Which prints:
Column names are: [_id, nickname...]
Making object, id column index is -16
So it sees like everything should be fine, anyone got any clue why everything could be getting so messed up while reading from the Cursor?
EDIT: Here's how I'm getting the cursor, this is a method in the database class:
public MyObject getMyObject(String id) {
MyObject objectFound = null;
String[] whereArgs = { id };
Cursor cursor = db.query(true, getTableName(), null, WHERE_EQUALS, whereArgs, null, null, null, null);
if(cursor.moveToFirst()) {
//Should only return 1 entry from DB
while(cursor.isAfterLast() == false) {
objectFound = new MyObject(cursor);
cursor.moveToNext();
}
}
cursor.close();
return objectFound;
}

How to swap values in columns SQLite?

I have table ( id , text) and I need to swap two values in columns like this:
Before.
1 one.
2 two.
3 three.
After ( 1 and 3 swap)
1 three
2 two
3 one
To update each row, you need something like this:
void updateMyTableText (MyTableRow row)
{
ContentValues values = new ContentValues();
values.put ("text", MyTableRow.text);
String where = "id = ?";
String[] whereArgs = new String[1];
whereArgs[0] = Long.toString (row.id);
getDb().update ("MyTable", values, where, whereArgs);
}
where MyTableRow is
class MyTableRow
{
long id;
String text;
}
You'll also need some queries to get the "text" for rows 1 and 3.
Here's one way to do a query:
long getId (String text)
{
// do the query
String query = "select id from MyTable where text = ? ";
String[] args = new String[1];
args[0] = text;
Cursor cursor = getDb().rawQuery (query, args);
if (cursor == null)
throw new IllegalStateException ("cursor is null");
try
{
// get the results
if (!cursor.moveToNext())
return -1; // row not found
long id = cursor.getLong (0);
return id;
}
finally
{
cursor.close();
}
}
Are you trying to change the values in the rows themselves? Most databases systems don't let you arbitrarily swap values since there is an assumption that they are permanently associated. You could issue UPDATE commands to permanently modify the values, but doing this temporarily will probably be an issue handled once the data is returned.
UPDATE table_name
SET text=three
WHERE id=1;
UPDATE table_name
SET text=one
WHERE id=3;
// Assuming id1 < id2
void swap(id1,id2)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues CV = new ContentValues();
// First get the 2 rows
Cursor res = db.rawQuery("SELECT COLUMN_NAME FROM "+ TABLE_NAME +" WHERE ID IN ("+id1+","+id2+") ORDER BY ID ASC",null);
res.moveToFirst();
CV.put("COLUMN_NAME",res.getString(0));
//Update 1st row with 2nd item
db.update(TABLE_NAME,CV,"ID = ?",new String[]{id2+""});
res.moveToNext();
CV.put("COLUMN_NAME",res.getString(0));
//Update 2nd row with 1st item
db.update(TABLE_NAME,CV,"ID = ?",new String[]{id1+""});
}
Hope it helps!!

Categories

Resources