I have a Spinner which is showing SQLite data. For that I am using this select method:
public List<String> getAllProductsName(int id)
{
String buildSQL = "SELECT nome FROM " + DatabaseHelper.Produtos.TABELA + " WHERE id =" + id;
List<String> nomes = new ArrayList<String>();
SQLiteDatabase db = this.getDatabase();
Cursor cursor = database.rawQuery(buildSQL, null);
if (cursor.moveToFirst()) {
do {
nomes.add(cursor.getString(0));
} while (cursor.moveToNext());
}
return nomes;
}
The thing is, I am getting only the names but I need the ID as well. I know i could use "SELECT nome, _id FROM ", but how would I return that? Could i possibly return 2 lists (one with IDS and the other one with the Names) in the same method?
Or maybe I should create a new method that show the Names only (when i give the ID as a parameter)? Please help! thanks in advance! :)
How about something like this ... using and returning HashMap that contains ID as keys and nome as values
public HashMap<Integer,String> getAllProductsName(int id)
{
String buildSQL = "SELECT nome,_id FROM " + DatabaseHelper.Produtos.TABELA + " WHERE id =" + id;
HashMap<Integer,String> idAndNomes = new HashMap<Integer,String>();
SQLiteDatabase db = this.getDatabase();
Cursor cursor = database.rawQuery(buildSQL, null);
if (cursor.moveToFirst()) {
do {
idAndNomes.put(cursor.getInt(1), cursor.getString(0)));
} while (cursor.moveToNext());
}
return idAndNomes;
}
Then you can use:
idAndNomes.keySet() - Returns a set of the keys contained in this map. In our case ID.
idAndNomes.values() - Returns a collection of the values contained in this map. In our case nomes.
Related
I would to like to display data from a local database table according to a user condition.
Code to display:
public void viewContact(){
String name = getIntent().getStringExtra("name").toString();
tvName.setText(name);
String phone = db.getContacts(name).toString();
tvPhone.setText(phone);
String web = db.getContacts(name.toString();
tvWeb.setText(web);
}
DBHelper.class:
public Cursor getContacts(String therapist_name){
String selectQuery = " SELECT therapist_phone, therapist_web " +
" FROM " + THERAPIST_TABLE + " WHERE " + THERA_NAME + " = " + "'" + therapist_name + "'";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
return cursor;
}
Can anyone point out where I've gone wrong?
Explanation:
The activity receives contact name from previous activity (hence getIntent()). Then with that, it would like to view data from database relating to the contact and thus would like to view the phone_number and website columns.
So if therapist_name is equal that of selected contact from previous activity, it would only display the therapist_number and therapist_website of that contact in the next activity.
You should have an Object Contact with the properties you want, and everytime you run the query, go trough the steps Ana said of checking if the cursor is null and moving to first (i personally check the size of the cursor also, to Log an error if is empty).
And then return the created object, so when you call the method, you have everything there, something like this:
public List<Contact> getContacts(String therapist_name){
List<Contact> listOfContacts = new ArrayList<>();
String selectQuery = " SELECT therapist_phone, therapist_web " +
" FROM " + THERAPIST_TABLE + " WHERE " + THERA_NAME + " = " + "'" + therapist_name + "'";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//Save data in variables here
String ph_no = cursor.getString(0); // therapist contact
String web = cursor.getString(1); //therapist web
listOfContacts.add(new Contact(ph_no, web));
} while (cursor.moveToNext());
}
}
return listOfContacts;
}
This returns a list of objects, just in case there is more than one match. You can tweak it to get one, or the first match, and return just the Contact object, so you would have your data,
You are just returning cursor object. Read the data and then return the retrieved data.
Example:
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
//Save data in variables here
ph_no = cursor.getString(0); // therapist contact
web = cursor.getString(1); //therapist web
} while (cursor.moveToNext());
}
}
//pass an array of ph_no and web from here now
I'm writing an app that will allow users to read short stories that are stored in an SQLite database.
So far so good.
But now I want to add features that involve writing to the database (saving the Y location of a ScrollView so the user can pick up where they left off, bookmarking stories, etc).
Should I add these values to the books table, or should I create a separate table user_settings with columns like id (int), story_id (int), y_position (int), bookmarked (boolean)?
Note: I'm also thinking ahead to the possibility of storing stories on a non-local database in the future.
My other question is: do I need to move the database somewhere to be able to write to it? I'm using SQLiteAssetHelper and the database is currently at /assets/databases/database.db. I'm hearing some talk of a /data/data/mypackage folder but I can't see it in my project.
My database setup is currently as follows:
authors
id
name
name_alphanumeric
books
id
title
author_id
collection
body
If it's useful, here's my DatabaseHelper so far:
public class DatabaseHelper extends SQLiteAssetHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "database9.db";
private static final String BOOKS = "books";
private static final String AUTHORS = "authors";
public DatabaseHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// setForcedUpgrade();
}
// Getting all books
public ArrayList<Author> getAllAuthors() {
ArrayList<Author> authorList = new ArrayList<>();
// Select all query
String selectQuery = "SELECT id, name FROM " + AUTHORS + " ORDER BY name_alphabetic";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
// create new author object
Author author = new Author();
// set ID and name of author object
author.setID(Integer.parseInt(cursor.getString(0)));
author.setName(cursor.getString(1));
// pass author object to authorList array
authorList.add(author);
} while (cursor.moveToNext());
}
// return author list
return authorList;
}
// Getting all stories
public List<Book> getAllStories(int authorID) {
List<Book> storyList = new ArrayList<>();
// Select all query
String selectQuery = "SELECT id, title FROM " + BOOKS + " WHERE author_id = " + authorID;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Book book = new Book();
book.setStoryID(Integer.parseInt(cursor.getString(0)));
book.setTitle(cursor.getString(1));
storyList.add(book);
} while (cursor.moveToNext());
}
// return contact list
return storyList;
}
// Get all collections
public List<Book> getAllCollections(int authorID) {
List<Book> collectionsList = new ArrayList<>();
// Select all query
String selectQuery = "SELECT DISTINCT collection FROM " + BOOKS + " WHERE author_id = " + authorID;
Log.i("stories", selectQuery);
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Book book = new Book();
book.setCollection(cursor.getString(0));
// Log.i("stories", cursor.getString(0));
collectionsList.add(book);
} while (cursor.moveToNext());
}
return collectionsList;
// not sure how to log collectionsList here
}
// Get story
public String getStoryBody(int storyID) {
// Log.i("stories", Integer.toString(storyID));
String storyBody = "";
// String storyBody();
// Select all query
String selectQuery = "SELECT body FROM " + BOOKS + " WHERE id = " + storyID;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
storyBody = cursor.getString(0);
} while (cursor.moveToNext());
}
return storyBody;
}
public int setScrollPosition(int scrollY, int storyID) {
String insertQuery = "UPDATE " + BOOKS + " SET scroll_position = " + scrollY + " WHERE id = " + storyID;
Log.i("insert", insertQuery);
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(insertQuery);
return 0;
}
public int getScrollPosition(int storyID) {
int scrollPosition = 0;
String selectQuery = "SELECT scroll_position FROM " + BOOKS + " WHERE id = " + storyID;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
scrollPosition = cursor.getInt(0);
} while (cursor.moveToNext());
}
return scrollPosition;
}
}
But now I want to add features that involve writing to the database
(saving the Y location of a ScrollView so the user can pick up where
they left off, bookmarking stories, etc).
Should I add these values to the books table, or should I create a
separate table user_settings with columns like id (int), story_id
(int), y_position (int), bookmarked (boolean)?
I think you have made it clear that they are USER values, so it is very likely that a separate user table would be the better more manageable solution.
My other question is: do I need to move the database somewhere to be
able to write to it? I'm using SQLiteAssetHelper and the database is
currently at /assets/databases/database.db. I'm hearing some talk of a
/data/data/mypackage folder but I can't see it in my project.
In all likeliehood the database has been copied from the assets folder into data/data/yourpackage/databases/dbfilename by SQLiteAssetHelper (as I understand that's primarily what it's for. However I've never used it.) Such folders have limited access (normally only the Application (rooted device an exception)) so that could well be why you can't see it.
As such there is likely nothing required in the way of permissions for writing to/updating the database.
how to change this logic to work with more than 170 rows.
// Getting All test
public List<Test> getAllTests(String str) {
List<Test> testList = new ArrayList<Test>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_TESTS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
//select rows by input string
if(cursor.getString(1).equals(str)){
Test test = new Test();
test.setId(Integer.parseInt(cursor.getString(0)));
test.setTest(cursor.getString(1));
test .setResult(Integer.parseInt(cursor.getString(2)));
// Adding test to list
testList.add(test);
}
} while (cursor.moveToNext());
}
//close database
db.close();
//return list data
return testList;
}
I want to select all rows by input string. It logic work perfectly with 150 rows but after 160 work slowly and crash on 170 rows
how to change this logic to work with more than 170 rows?
// Getting All test
public List<Test> getAllTests(String str) {
List<Test> testList = new ArrayList<Test>();
// Select All Query
//String selectQuery = "SELECT * FROM " + TABLE_TESTS;
String selectQuery = "SELECT id,result FROM " + TABLE_TESTS + " where name ='" + str + "'";
// Now you are saving memory of one column.
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
Test test = new Test();
// moved outside loop to prevent creating new object every time.
do {
//select rows by input string
//if(cursor.getString(1).equals(str)){
// No need for if Codition any more
test.setId(Integer.parseInt(cursor.getString(0)));
//test.setTest(cursor.getString(1));
test.setTest(str);
test .setResult(Integer.parseInt(cursor.getString(2)));
// Adding test to list
testList.add(test);
//}
} while (cursor.moveToNext());
}
//close database
db.close();
//return list data
return testList;
}
EDITED: MISPELLED METHOD
Use
String selectQuery = "SELECT * FROM " + TABLE_TESTS + " WHERE " + your_id + " > " + String.valueOf(last_id) + " LIMIT 150";
as your query structure, and then keep track of the last row id like this`
int last_id;
do {
//select rows by input string
if(cursor.getString(1).equals(str)){
Test test = new Test();
last_id = Integer.parseInt(cursor.getString(0));
test.setId(last_id);
...
}
} while (cursor.moveToNext());
every time the loop ends, just query again your db; the rows will be fetched from the next one you need, because last_id variable dinamically change according to your progress.
Could try using same code differently in following way
// using sql query Differently
(SQliteDatabase) db.query(
"TABLE_TESTS" / table name /,
new String[] { "id", "result" } / columns names /,
"name = ?" / where or selection /,
new String[] { str } / selectionArgs i.e. value to replace ? /,
null / groupBy /,
null / having /,
null / orderBy /
);
Another approach could be to use LIMIT and OFFSET to get data in parts to improve performance
// using LIMIT AND OFFSET
public List<Test> getAllTests(String str) {
List<Test> testList = new ArrayList<Test>();
// Select All Query
Integer count = 0;
String countQuery = "SELECT count(id) FROM " + TABLE_TESTS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
if (cursor.moveToFirst()) {
count= c.getCount();
}
db.close();
int MAX_LENGTH = 150;
if ( count > 0 ) {
int total_length = ( count / MAX_LENGTH ) + 1;
for ( int i=0; i<total_length; i++) {
String selectQuery = "SELECT id,result FROM " + TABLE_TESTS + " LIMIT " + MAX_LENGTH + " OFFSET " + (i*MAX_LENGTH) ;
db = this.getWritableDatabase();
cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
Test test = new Test();
// moved outside loop to prevent creating new object every time.
do {
//select rows by input string
if(cursor.getString(1).equals(str)){
test.setId(Integer.parseInt(cursor.getString(0)));
//test.setTest(cursor.getString(1));
test.setTest(str);
test .setResult(Integer.parseInt(cursor.getString(2)));
// Adding test to list
testList.add(test);
}
} while (cursor.moveToNext());
}
//close database
db.close();
}
}
//return list data
return testList;
}
This code works, but the query is based on name. How can I use primary key instead of name without showing the primary key in listview?
This code is in my database file:
public ArrayList<String> data() {
ArrayList<String> ar = new ArrayList<String>();
ArrayList<String> av = new ArrayList<String>();
SQLiteDatabase db = helper.getReadableDatabase();
Cursor c = db.query(helper.TABLE_NAME, new String[] {helper.NAME,helper.DATE,helper.PEOPLE}, null, null, null, null,null );
c.moveToFirst();
do {
String db_name = c.getString(c.getColumnIndex(helper.NAME))+ " " + c.getString(c.getColumnIndex(helper.DATE))+" "+c.getString(c.getColumnIndex(helper.PEOPLE));
ar.add(db_name);//only ar will be show in listview
c.moveToNext();
} while (!c.isAfterLast());
return ar;
}
and The Activity code is:
lv = (ListView) findViewById(R.id.listView1);
ar = helper.data();
ArrayAdapter<String> ad = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, ar);
lv.setAdapter(ad);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
String s = parent.getItemAtPosition(position).toString();
String k = "";
String p[] = s.split(" ");
for (int i = 0; i < p.length-7; i++)
k = k + " " + p[i];
k = k.trim();//k contains the name string
Intent i = new Intent(getApplicationContext(), Details.class);
i.putExtra("name", k);//next activity will fetch all the details with the help of name.
startActivity(i);
}
}
Your question isn't very clear to me. But if its what I think you want to do, you can try something like this, this fetches a book in the database based on its ID (the primary key)
public Book getBook(int id){
// 1. get reference to readable DB
SQLiteDatabase db = this.getReadableDatabase();
// 2. build query
Cursor cursor =
db.query(TABLE_BOOKS, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
// 3. if we got results get the first one
if (cursor != null)
cursor.moveToFirst();
// 4. build book object
Book book = new Book();
book.setId(Integer.parseInt(cursor.getString(0)));
book.setTitle(cursor.getString(1));
book.setAuthor(cursor.getString(2));
//log
Log.d("getBook("+id+")", book.toString());
// 5. return book
return book;
}
Source
which was set using:
// SQL statement to create book table
String CREATE_BOOK_TABLE = "CREATE TABLE books ( " +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"title TEXT, "+
"author TEXT )";
How can I use primary key instead of name without showing the primary key in listview?
Aren't you supposed to be in charge of what you show in your ListView?
I have a page which can retrieve user data from database
but after whole day of trying, I am only able to get the table column name but not the value inside.
this is my code to create database
public static final String LASTLOGIN = "lastuser";
public static final String USER_ID = "suser_id";
public static final String USER_NAME = "suser_name";
public static final String USER_PASSWORD = "spassword";
public static final String PRIME_ID = "id";
private static final String TABLE_USER =
"create table "+ LASTLOGIN+" ("
+PRIME_ID+" integer primary key autoincrement, "
+ USER_ID + " text, "
+ USER_NAME +" text, "
+USER_PASSWORD+" text); ";
and here is the function implemented to get user data
public Cursor getuser()
{
String[] columns = new String[]{PRIME_ID, USER_NAME, USER_PASSWORD};
Cursor cursor = sqLiteDatabase.query(
LASTLOGIN, columns, null, null, null, null, PRIME_ID +" DESC");
Log.d("TAG", columns[1]);
return cursor;
}
and here is my code to display the result
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
cursor = mySQLiteAdapter.getuser();
String[] resultvalue = new String{
SQLiteAdapter.PRIME_ID,SQLiteAdapter.USER_NAME, SQLiteAdapter.USER_PASSWORD};
Toast.makeText(this, resultvalue[0]+resultvalue[1], Toast.LENGTH_LONG).show();
and the toast result only show the column name but not the value inside, is there any mistake i made? and I want to set limit to 1, but where to set it?
Thanks for helping me
the way you try reading the values is completly wrong.
you create an array
String[] resultvalue = new String[]{
SQLiteAdapter.PRIME_ID,
SQLiteAdapter.USER_NAME,
SQLiteAdapter.USER_PASSWORD};
after that you read the values 0 and 1 from this array.
Your toast works absolutly correctly becouse inside this array you define the column names!
If you want to show the values from your query do it this way:
while(cursor.moveToNext()){
Integer str1 = str 1 + cursor.getInteger(1);
String str2 =str2 + cursor.getString(2);
Toast.makeText(this, str1 + str2, Toast.LENGTH_LONG).show();
}
or a better way receiving the correct index:
cursor.getInteger( cursor.getColumnIndex(SQLiteAdapter.PRIME_ID) );
cursor.getString( cursor.getColumnIndex(SQLiteAdapter.USER_NAME) );
Please note when retrieving data from a database, you store it in a Cursor in the memory and hence can only access it using that particular Cursor object, which you have used in the following line of code.
Cursor cursor = mySQLiteAdapter.getuser();
The Following line retrieves the column names and not the values.
String[] resultvalue = new String[]{SQLiteAdapter.PRIME_ID,SQLiteAdapter.USER_NAME, SQLiteAdapter.USER_PASSWORD};
So the following is doing what you have asked it to do, retrieve column names not values
Toast.makeText(this, resultvalue[0]+resultvalue[1], Toast.LENGTH_LONG).show();
You need something like following:
if(cursor.getCount() != 0)
{
while(cursor.moveToNext())
{
resultvalue [0] = csr.getString(0);
resultvalue [1] = csr.getString(1);
//....
}
}
Hope this helps
here is my solution:
final String TABLE_NAME = "table_name";
String selectQuery = "SELECT Column FROM "+TABLE_NAME+" WHERE column='"+some_value+"'";
SQLiteDatabase db = this.openDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
String[] data = new String[cursor.getCount()];;
int i = 0;
if (cursor.moveToFirst()) {
do {
i=Integer.parseInt(cursor.getString(cursor.getColumnIndex("value")));
} while (cursor.moveToNext());
}
cursor.close();