i am trying to build an application that save data in sqlite database.i have a class that search in the database searching by VendorName and Date. The problem is i want it to display the MeterNumbers that was saved on the same Date . to what i have tried it only gives me the first result it get in the database, lets say i search for Tom that was saved on 01/01/2013, it supposed to display both metereNumbers of Tom that was saved on 01/01/2013
here is an example of my table in sqlite
VendorName Date MeterNumber
...Tom.... 01/01/2013 ......2098957438902
...Tom... 01/01/2013........4786909876785
...Steven...18/01/2013.........8978978906542
This is the Code in Sqlite database
public String getMeterNUmber(String MeterNumber) throws SQLException
{
String[] whereArgs = new String[]{MeterNumber};
Cursor mCursor = db.rawQuery("SELECT MeterNumber FROM " + SCAN_TABLE + " WHERE Date = ?",whereArgs);
mCursor.moveToFirst();
if(mCursor.getCount() > 0){
MeterNumber = mCursor.getString(0);
}
return MeterNumber;
}
this is the code in the class that calls for the query in the sqlite database and take the result to another class by intent
Intent updateCustomerIntent = new Intent(Searching.this, Result.class);
updateCustomerIntent.putExtra("product", dbUser.getMeterNUmber(ss));
startActivity(updateCustomerIntent);
Firstly, your parameter should be date not number,Secondly you don't loop through the result you just pull your first record. I think you should revise some good tutorial first at using SQLite with android.Here are some good links that may help.
Android SQLite Database and ContentProvider - Tutorial!
Android SQLite Database Tutorial
First of all, your getMeterNumber method takes a meter number as an argument, as already pointed out in ggenglish's comment, this seems odd, it should be a date no? Also, your method only calls mCursor.getString(0) once, and then returns that, which means you will only get the meter number from the first row of your result set.
If you want all the results, you will need to iterate over the full recordset. When you receive the cursor, it will be positioned just before the first row, so, you can loop through it with the method moveToNext(). Then, you will also have to store your result in a appropriate data structs, such as a ArrayList
ArrayList<String> results = new ArrayList<String>();
while (mCursor.moveToNext()) {
results.add(mCursor.getString(0));
}
So, you will end up with something like this
public ArrayList<String> getMeterNUmber(String meterDate) throws SQLException
{
String[] whereArgs = new String[]{meterDate};
Cursor mCursor = db.rawQuery("SELECT MeterNumber FROM " + SCAN_TABLE + " WHERE Date = ?",whereArgs);
ArrayList<String> results = new ArrayList<String>();
while (mCursor.moveToNext()) {
results.add(mCursor.getString(0));
}
mCursor.close();
return results;
}
And then finally, use putStringArrayListExtra instead of putExtra when adding the data to the intent.
If you are expecting one value you should do this:
public String getMeterNUmber(String date) throws SQLException {
String meterNumber = null;
Cursor cursor = db.rawQuery("SELECT MeterNumber FROM " + SCAN_TABLE + " WHERE Date = ?", new String[]{date} );
if ( cursor.moveToNext() ) meterNumber = cursor.getString(0);
cursor.close();
return meterNumber;
}
if you are expecting multiple elements you should loop as mentioned by others
public ArrayList<String> getMeterNUmber(String date) throws SQLException {
ArrayList<String> meterNumbers = new ArrayList<String>();
Cursor cursor = db.rawQuery("SELECT MeterNumber FROM " + SCAN_TABLE + " WHERE Date = ?", new String[]{date} );
while ( cursor.moveToNext() ) meterNumbers.add( cursor.getString(0) );
cursor.close();
return meterNumbers;
}
you specify you are querying by name and date but your example code shows otherwise, hopefully this helps a bit though.
Related
I want to fetch phone number linked to particular email in the database. I am not able to find the query for it or how
public String getContactNumber(String email){
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " + COLUMN_USER_MOBILE_NUMBER + " FROM " + TABLE_USER + " WHERE " + email + " = " + COLUMN_USER_EMAIL;
Cursor cursor = db.rawQuery(query,null);
//What to put here to extract the data.
String contact = cursor.getString(get);
cursor.close();
return contact;
}
to extract the data. Completely a beginner
Try this ..
public List<String> getMyItemsD(String emailData) {
List<String> stringList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT COLUMN_USER_MOBILE_NUMBER FROM " + USER_TABLE_NAME + " WHERE email= " + emailData;
Cursor c = db.rawQuery(selectQuery, null);
if (c != null) {
c.moveToFirst();
while (c.isAfterLast() == false) {
String name = (c.getString(c.getColumnIndex("Item_Name")));
stringList.add(name);
c.moveToNext();
}
}
return stringList;
}
public String getContactNumber(String email){
String contact = "";
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " + COLUMN_USER_MOBILE_NUMBER + " FROM " + TABLE_USER + " WHERE " + email + " = " + COLUMN_USER_EMAIL;
Cursor cursor = db.rawQuery(query,null);
if(cursor.getCount()>0) {
cursor.moveToNext();
contact = cursor.getString(cursor.getColumnIndex(COLUMN_USER_MOBILE_NUMBER));
}
//What to put here to extract the data.
cursor.close();
return contact;
}
From this method you get phone number value of that email which you pass any other method easily.
I'd suggest the following :-
public String getContactNumber(String email){
String contact = "NO CONTACT FOUND"; //<<<<<<<<<< Default in case no row is found.
SQLiteDatabase db = this.getWritableDatabase(); //<<<<<<<<<< Generally getReadable gets a writable database
String[] columns_to_get = new String[]{COLUMN_USER_MOBILE_NUMBER};
String whereclause = COLUMN_USER_EMAIL + "=?";
String[] whereargs = new String[]{email};
Cursor cursor = db.query(TABLE_USER,columns_to_get,whereclause,whereargs,null,null,null);
//What to put here to extract the data.
if (cursor.moveToFirst()) {
contact = csr.getString(csr.getColumnIndex(COLUMN_USER_MOBILE_NUMBER));
}
cursor.close();
return contact;
}
The above does assumes that there will only be 1 row per email (which is most likely).
Explanations
A default value is set so that you can easily tell if an invalid/non-existent email is passed (you'd check the return value if need be (might be easier to simply have "" and check the length as a check)).
getReadableDatabase has been replaced with getWritableDatabase as unless there are issues with the database a writable database will be returned, as per :-
Create and/or open a database. This will be the same object returned
by getWritableDatabase() unless some problem, such as a full disk,
requires the database to be opened read-only. In that case, a
read-only database object will be returned. If the problem is fixed, a
future call to getWritableDatabase() may succeed, in which case the
read-only database object will be closed and the read/write object
will be returned in the future.
getReadableDatabase
Note no real problem either way;
The recommended query method has been used instead of the rawQuery method. This has distinct advantages, it builds the underlying SQL and also offers protection against SQL injection (just in case the email passed is input by a user).
this version of the method takes 7 parameters :-
The table name as a string
The columns to be extracted as an array of Strings (aka String array). null can be all columns.
The where clause less the WHERE keyword with ?'s to represent arguments (see next). null if no WHERE clause.
The arguments to be applied (replace ?'s 1 for 1) as a String array. null if none or no WHERE clause.
The GROUP BY clause, less the GROUP BY keywords. null if no GROUP BY clause.
The HAVING clause, less the HAVING keyword. null if no HAVING clause.
The ORDER BY clause, less the ORDER BY keywords. null if no ORDER BY clause.
SQLiteDatabase - query
- Note there are 4 query methods (see link for the subtle difference, I believe this is the most commonly used)
The data extraction is the new code. When a Cursor is returned it is at a position BEFORE THE FIRST ROW, so you need to move to a valid row. So the moveToFirst* method is suitable (note that if a move cannot be made by a move method that it will return false, hence how you can say if (cursor.moveToFirst())). The data is then extracted from the appropriate column use the **getString method, which takes an int as an argumnet for the column offset (0 in this case). However, using hard coded values can lead to issues so the getColumnIndex method is used to get the offset according to the column name (-1 is returned if the named column is not in the Cursor).
I don't know what's wrong with my code I follow the rule but I get wrong result. I want to search db and find all rows data but I only get last row from sqlite. my code to search database is bellow:
public ArrayList<ArrayList<ContractSaveDataFromDB>> ActiveContractData(String phone, String numberId)
{
ArrayList<ContractSaveDataFromDB> UserData = new ArrayList<ContractSaveDataFromDB>();
ArrayList<ArrayList<ContractSaveDataFromDB>> SendUserData =
new ArrayList<ArrayList<ContractSaveDataFromDB>>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
res2.moveToFirst();
do{
UserData.clear();
int index;
ContractSaveDataFromDB contractSaveDataFromDB=new ContractSaveDataFromDB();
index = res2.getColumnIndex("buyAmount");
String buyAmount = res2.getString(index);
contractSaveDataFromDB.setBuyAmount(buyAmount);
UserData.add(contractSaveDataFromDB);
SendUserData.add(UserData);
} while(res2.moveToNext());
res2.close();
db.close();
return SendUserData;
I don't know what's wrong. I appreciate if you help me to solve my problem.
you already added where clause so maybe it is filtering your results try to remove it by change this
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
to this
Cursor res2=db.query("usersAccount",null,null,null,null,null,orderBy);
I believe that your issues is that you are trying to use an ArrayList of ArrayList of ContractSaveDataFromDB objects.
I believe that an ArrayList of ContractSaveDataFromDB objects would suffice.
It would also help you if you learnt to do a bit of basic debugging, as an issue could be that you are not extracting multiple rows.
The following is an alternative method that :-
uses the ArrayList of ContractSaveDataFromDB objects,
introduces some debugging by the way of writing some potentially useful information to the log
and is more sound, as it will not crash if no rows are extracted
i.e. if you use moveToFirst and don't check the result (false means the move could not be accomplished) then you would get an error because you are trying to read row -1 (before the first row) as no rows exists in the cursor.
:-
public ArrayList<ContractSaveDataFromDB> ActiveContractData(String phone, String numberId) {
ArrayList<ContractSaveDataFromDB> SendUserData = new ArrayList<ContractSaveDataFromDB>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2 = db.query("usersAccount", null, whereClause, whereArgs, null, null, orderBy);
Log.d("RES2 COUNT", "Number of rows in Res2 Cursor is " + String.valueOf(res2.getCount()));
while (res2.moveToNext()) {
ContractSaveDataFromDB current_user_data = new ContractSaveDataFromDB();
current_user_data.setBuyAmount(res2.getString(res2.getColumnIndex("buyAmount")));
Log.d("NEWROW", "Adding data from row " + String.valueOf(res2.getPosition()));
SendUserData.add(current_user_data);
}
res2.close();
db.close();
Log.d("EXTRACTED", "The number of rows from which data was extracted was " + String.valueOf(SendUserData.size()));
return SendUserData;
}
If after running you check the log you should see :-
A line detailing how many rows were extracted from the table
A line for each row (if any were extracted) saying Adding data from row ? (where ? will be the row 0 being the first)
A line saying The number of rows from which data was extracted was ? (? will be the number of elements in the array to be returned)
I have a list of items queried from my database. This list has two words in each item, the two words are separated by a space. I now want to get access to only the last word after the space.
This the query from my database
public List<String> getList(){
List<String> array = new ArrayList<String>();
String selectQuery = "SELECT * FROM " + TABLE_LIST;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
ArrayList<ArrayList<String>> row = new ArrayList<ArrayList<String>>();
if (cursor .moveToFirst()) {
;
do {
String listName = cursor.getString(cursor.getColumnIndex(ITEM_A));
array.add(listName);
}while(cursor.moveToNext());
}
cursor.close();
return array;
}
Accessing the items from the query
List<String> m = new ArrayList<String>();
m = dbHelper.getList();
System.out.println(m);
This gives the below output
[itemOA AITEME,itemOD BITEMD,itemOC CITEMS, itemOB DTEM]
I however wants to get the last words of the list,
[AITEME, BITEMD, CITEMS ,DTEM]
Thanks for helping.
I think you could restructure your code to save from having to do this, but:
String substr = myString.substring(startIndex);
Will work as long as you always have a known starting point (if it's always going to start with "itemOA" or 6 characters + a single whitespace)
I have large number of strings, approximately 15,000 that I stored in a SQLite database using the following code:
void addKey(String key, String value, String table) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_KEY, key); // Contact Name
values.put(KEY_VALUE, value); // Contact Phone
// Inserting Row
db.insert(table, null, values);
db.close(); // Closing database connection
}
And then i search through that database using the following method in order to pick out any strings that match the key im looking for:
public String searchKeyString(String key, String table){
String rtn = "";
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Log.d("searchKeyString","searching");
if(cursor.getString(1).equals(key))
rtn = rtn + "," + cursor.getString(2);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
Log.d("searchKeyString","finish search");
return rtn;
}
The goal is to do this in real time as the user is typing on the keep board so response time is key and the way it stands now it takes over a second to run through the search.
I considered reading all of the items into an array list initially and sorting through that which might be faster, but i thought an array list of that size might cause memory issues. What is the best way to search through these entries in my database?
A couple of things you can do...
Change the return to a StringBuilder until the end.
Only use a readable version of the database (that's probably not making much difference though)
Do not get a new instance of the database every time, keep it opened until you don't need it anymore
Query for only what you need with the "WHERE" argument in the SQL query.
See the code below with some changes:
// move this somewhere else in your Activity or such
SQLiteDatabase db = this.getReadableDatabase();
public String searchKeyString(String key, String table){
StringBuilder rtn = new StringBuilder();
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table + " WHERE KEY_KEY=?";
Cursor cursor = db.rawQuery(selectQuery, new String[] {key});
// you can change it to
// db.rawQuery("SELECT * FROM "+table+" WHERE KEY_KEY LIKE ?", new String[] {key+"%"});
// if you want to get everything starting with that key value
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Log.d("searchKeyString","searching");
rtn.append(",").append(cursor.getString(2));
} while (cursor.moveToNext());
}
cursor.close();
Log.d("searchKeyString","finish search");
return rtn.toString();
}
Note even if you want this to happen in "real-time" for the user, you will still need to move this to a separate Thread or ASyncTask or you are going to run into problems....
You should consider using SELECT * FROM your-table LIMIT 50, for example. And you can put two buttons "Back", "Next" on your view. If every page has max 50 items, the user is at page 1, and he taps "Next", then you can use this query:
SELECT * FROM your-table LIMIT 50 OFFSET 50
If your table contains most of text-data, and you want to integrate search deeply into your app, consider using virtual table with FTS.
Let sqlite do the hard lifting.
First off, add an index to the field you're searching for, if you don't have one already. Secondly, don't do a SELECT all with manual table scan, but rather use a query in the form
SELECT column_value
FROM my_table
WHERE column_key LIKE "ABC%"
This returns the least amount of data, and the sql engine uses the index.
i dunno about better but maybe it'd be faster to make queries for the selected strings one by one.
public String searchKeyString(String key, String table){
String rtn = "";
Log.d("searchKeyString",table);
// Select All Query
String selectQuery = "SELECT * FROM " + table + "WHERE column_1 = " + key;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
rtn = rtn + "," + cursor.getString(2);
}
cursor.close();
db.close();
Log.d("searchKeyString","finish search");
return rtn;
}
EDIT:
Well i dunno how those custom keyboard apps do it, but those AutoCompleteTextViews are hooked up to adapters. you could just as easily make a cursorAdapter and hook your auto-complete view to it.
http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/
http://www.opgenorth.net/blog/2011/09/06/using-autocompletetextview-and-simplecursoradapter-2/
My SQLite query returning only one record, However, the table has multiple rows
cursor=mydb.rawQuery("Select category from items;", null);
I have even tried GROUP BY but still wont work.
I am new to SQLite, would appreciate any help. Thanks.
First of all your string query must not be terminated so instead of passing it as:
"Select category from items;"
you should try passing it as:
"Select category from items"
as mentioned on this page.
Also, are you looping over the cursor? Here is an example of how to get data out of a cursor with a while loop:
ArrayList<String> results = new ArrayList<String>()
while (cursor.moveNext()) {
results.add(cursor.getString(0)); // 0 is the first column
}
First, search:
Cursor cs = myDataBase.rawQuery("Your query", null);
if (cs.moveToFirst()) {
String a = cs.getString(cs.getColumnIndex("your_column_name"));
cs.close();
return a;
}
cs.close();
return "";
Get the information from cursor:
if (cs.moveToFirst()) {
ArrayList<String> results = new ArrayList<String>()
do {
results.add(cs.getString(cs.getColumnIndex("your_column_name")));
} while (cs.moveNext());
}
Without if, I took error in my project. But this worked for me. By the way, your query doesn't look good. If you give some information about your database, we can help much more.
Use this to select all items from the table:
Cursor cursor = db.rawQuery("SELECT * FROM Tablename ,
null);
this can help you
public ArrayList<mydata> getallContents() {
ArrayList<mydata> lst = new ArrayList<mydata>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + GAMETABLE, null);
if (c.moveToFirst()) {
do {
lst.add(new mydata(c.getString(1),
c.getString(3),c.getString(4),c.getString(5),c.getString(6)));
} while (c.moveToNext());
}
db.close();
return lst;
}
you don't need raw query method. i think that the android way is better in this case:
db.query(items, category, null, null, null, null, null);
than use the cursor how already is written in the other comment.