How to write a sqlite query to get specific data? - android

I want to get the first name, middle name and last name of a student whose userid is used for login. I have written this particular piece of code but it stops my application.
I have used both the ways like database.query() and .rawquery() also.
Cursor studentData(String userId) {
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.query(studentTable, new String[] { "First_Name", "Middle_Name", "Last_Name"}, "User_ID=?", new String[] { userId }, null, null, null, null);
// Cursor cursor = db.rawQuery("select First_Name, Middle_Name, Last_Name from Student_Table where User_ID =?", new String[]{userId});
String data = cursor.getString(cursor.getColumnIndex("First_Name"));
db.close();
return cursor;
}
I should get whole name in the string.

You have a number of issues.
Attempting to use String data = cursor.getString(cursor.getColumnIndex("First_Name"));,
will result in an error because you have not moved the cursor beyond BEFORE THE FIRST ROW and the attempt to access the row -1 will result in an exception (the likely issue you have encountered).
you can use various move??? methods e.g. moveToFirst, moveToNext (the 2 most common), moveToLast, moveToPosition.
Most of the Cursor move??? methods return true if the move could be made, else false.
You CANNOT close the database and then access the Cursor (this would happen if the issue above was resolved)
The Cursor buffers rows and then ONLY when required.
That is The Cursor is when returned from the query method (or rawQuery) at a position of BEFORE THE FIRST ROW (-1), it's only when an attempt is made to move through the Cursor that the CursorWindow (the buffer) is filled (getCount() included) and the actual data obtained. So the database MUST be open.
If you want a single String, the full name, then you could use :-
String studentData(String userId) { //<<<<<<<<<< returns the string rather than the Cursor
SQLiteDatabase db = getWritableDatabase();
String rv = "NO NAME FOUND"; //<<<<<<<<<< value returned if no row is located
Cursor cursor = db.query(studentTable, new String[] { "First_Name", "Middle_Name", "Last_Name"}, "User_ID=?", new String[] { userId }, null, null, null, null);
if (cursor.modeToFirst()) {
String rv =
cursor.getString(cursor.getColumnIndex("First_Name")) +
" " +
cursor.getString(cursor.getColumnIndex("Middle_Name")) +
" " +
cursor.getString(cursor.getColumnIndex("Last_Name"));
}
cursor.close(); //<<<<<<<<<< should close all cursors when done with them
db.close(); //<<<<<<<<<< not required but would result in an exception if returning a Cursor
return rv;
}
Or alternately :-
String studentData(String userId) { //<<<<<<<<<< returns the string rather than the Cursor
SQLiteDatabase db = getWritableDatabase();
String rv = "NO NAME FOUND"; //<<<<<<<<<< value returned if no row is located
Cursor cursor = db.query(studentTable, new String[] { "First_Name"||" "||"Middle_Name"||" "||"Last_Name" AS fullname}, "User_ID=?", new String[] { userId }, null, null, null, null);
if (cursor.modeToFirst()) {
String rv =
cursor.getString(cursor.getColumnIndex("fullname"));
}
cursor.close(); //<<<<<<<<<< should close all cursors when done with them
db.close(); //<<<<<<<<<< not required but would result in an exception if returning a Cursor
return rv;
}
the underlying query being SELECT First_Name||" "||Middle_Name||" "||LastName AS fullname FROM student_table; so you concatenate the names as part of the query which returns just one dynamically created column named fullname.

Related

Returning sqlite query as cursor or object/list

When I started my app years ago, I did some tutorials and always did my queries to the database returning the cursor (without closing it):
public Cursor querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
return db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
}
Now I am refactoring my code to MVVM and added models, so I changed my code to this:
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
c1.moveToFirst();
return new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
I read that cursors should always be closed (memory leak). Which is the best/most conform approach to return my data from the database? I'm also unsure if there are multiple results, should I stay with a cursor or change to a list?
public List<Card> queryAll() {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, null, null, null, null, null);
List<Card> list = new ArrayList<>();
if(c1.moveToFirst()){
do{
list.add(new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY))));
} while(c1.moveToNext());
}
c1.close();
return list;
}
Is this all just a matter of taste or are there reasons why it should return a cursor or a list/object? Depending where in my code I need the data, a list or a cursor is more convenient.
I'm just not sure what is the correct approach in sqlite queries. There are so many code examples and but it seems most is copy/paste without really digging into the topic.
If the query can return multiple rows then you should return a list.
If you are sure that the query will return just a single Card then returning that single Card would be OK (probably preferable) BUT you should close the Cursor.
However, there isn't an actual requirement/need to do so (e.g. if you your initial activity uses a Cursor for a ListView/Spinner then you may not want to close the Cursor but reuse it and use the adapter's swapCursor when the Activity resumes). The cursor would be effectively closed, as would the database when the App finishes.
As you have used the column _ID which is typically used for a column that is an alias of the rowid column, which is typically generated by SQLite then if used/defined as such (column has been defined explicitly or implicitly as INTEGER PRIMARY KEY with or without AUTOINCREMENT) then it will be a unique value and only return a single row as you have _ID = ?. As such there is a high likeliehood that a single row, or no row would be returned, and unlikely that multiple rows are returned.
So (for a single Card):-
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
c1.moveToFirst();
return new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
Should be something like :-
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Card rv = null;
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
if (c1.moveToFirst()) { //<<<<<< Should always check if the move moved
rv = new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
c1.close();
return rv; //<<<<< Note should check the returned Card for null
}
In addition to memory leaks not closing Cursors can result in a too many open connections (1K (1024) if memory serves correctly) and then a exception: unable to open database file (code 14); as underneath all the wrappers a Cursor has a file associated with it.

How to get specific value from DB by id

How to get specific value from DB by id.
This is my table: TABLE-RECORDS-(name of table) and KEY-ID , KEY-PRICE ... I'm trying to get KEY-PRICE by KEY-ID and can not. How to do it?
I don't know if this is exactly what you are looking for, but this is the query.
SELECT key-price FROM table-record WHERE key-id='id number you need';
// please change the column names of database if i have mistaken
public Cursor getCursor(int id) {
SQLiteDatabase db = this.getReadableDatabase();
String from[] = {"key-price"};//this is the edit1
String where = "key-id=?";//this is the edit2
String[] whereArgs = new String[]{String.valueOf(id)+""}; //this is the edit3
Cursor cursor = db.query(true, table-records, from, where, whereArgs, null, null, null, null);
return cursor;
}
//just call this function and see the magic
private int getPrice(int id) {
Cursor c = getCursor(id);
int price=-1;
if(c != null)
{
while(c.moveToNext){
//assuming price is an integer
price = c.getInt(0);//edit 4
// use these strings as you want
}
}
return price;
}

How to store a row from a cursor

I want to pull a row from a data-filled cursor and store it in another object for other use.
my code:
SQLiteDatabase db = dbOpener.getReadableDatabase();
Cursor dataSet = db.query(WPTemplateDB.PRODUCT_TABLE,
null, //all columns
null, //where clause
null, //where clause args
null, null, null);//groupBy, having, orderBy
while (dataSet.moveToNext()){
Product product = new Product(dataSet);
pArray.add(product);
}
my storing object:
public Product(Cursor cursor){
productData = cursor;
}
public String getData(String column){
Log.d(column, productData.getColumnIndex(column)+"");
return productData.getString(productData.getColumnIndex(column));
}
Now, I am facing an error of "index 10 requested with a size of 10". What can I do to this?
Don't should using cursor is contructors for Product objects. It will leak memory because cursor must close when not use.
You should read data from cursor then send data to contructor Product like:
String productName = cursor.getString(0);// 0 is column name
......
cursor.close();
Product product = new Product(name);
Indexes are zero-based. It means that is size is 10, max index will be 9. From the code you've posted, everything is fine, so the error in some other place of your code.
Actually, this answer is inspired from #cuasodayleo, I just translate it to be another code.
SQLiteDatabase db = dbOpener.getReadableDatabase();
Cursor dataSet = db.query(WPTemplateDB.PRODUCT_TABLE,
new String[]{WPTemplateDB.PRODUCT_ID},
null, //where clause
null, //where clause args
null, null, null);//groupBy, having, orderBy
while (dataSet.moveToNext()){
Product product = new Product(dataSet.getInt(0), db);
pArray.add(product);
}
dataSet.close();
The Product object:
public Product(int pid, SQLiteDatabase db){
productData = db.query(WPTemplateDB.PRODUCT_TABLE,
null, //all columns
WPTemplateDB.PRODUCT_ID+"=?", //where clause
new String[]{pid+""}, //where clause args
null, null, null);//groupBy, having, orderBy
}
public String getData(String column){
Log.d("count", productData.getCount()+"");
if (productData.getCount()>0){
Log.d(column, productData.getColumnIndex(column)+"");
productData.moveToFirst();
return productData.getString(productData.getColumnIndex(column));
} else {
return null;
}
}

Android- Getting a single value from a database table using cursor

I'm using cursors to retrieve data from a database. I know how to retrieve entire columns to use on listviews and such, but I'm struggling to find a way to retrieve a single value.
Let's say I have a table with two columns ("_id" and "Name") and I have ten records (rows) in that table. How would I get, for example, the Name in the third row? Considering I defined a cursor that reads that table:
public Cursor getMyNameInfo() {
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String sqlTables = "MyNames";
qb.setTables(sqlTables);
Cursor c = qb.query(db, null, null, null,
null, null, null);
c.moveToFirst();
return c;
}
Instead of c.moveToFirst() use c.moveToPosition(2) (Cursor indexes are zero-based hence '2' is the third record).
Remember to check that the Cursor has valid data first though.
EDIT:
Once you've moved the cursor to the 3rd record as I explain above, use the following to just get the value of the "Name" column.
String theName = c.getString(getColumnIndex("Name"));
Cursor cursor = dbHelper.getdata();
System.out.println("colo" + cursor.getColumnCount() + ""
+ cursor.getCount());
cursor.moveToFirst();
if (cursor != null) {
while (cursor.isAfterLast() == false) {
String chktitle = title.trim().toString();
String str = cursor.getString(cursor.getColumnIndex("title"));
System.out.println("title :: "
+ cursor.getString(cursor.getColumnIndex("title")));
System.out.println("date :: "
+ cursor.getString(cursor.getColumnIndex("date")));
System.out.println("desc :: "
+ cursor.getString(cursor.getColumnIndex("desc")));
if (chktitle.equals(str) == true) {
tvAddfavorite.setText("Remove Favorite");
break;
}
cursor.moveToNext();
}
}
cursor.close();
Add a WHERE clause:
qb.appendWhere("_id = 2");
Thanks to the answers above I created the following method to give the value of an item from another column but in the same row.
public String getValueFromColumn(int position, String tableName, String columnToGetValueFrom) {
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(tableName);
Cursor c = qb.query(db, null, null, null,
null, null, null);
c.moveToPosition(position);
String neededValue = c.getString(c.getColumnIndex(columnToGetValueFrom));
return neededValue;
}
Hope it helps anyone.

Get last inserted value from sqlite database Android

I am trying to get the last inserted rowid from a sqlite database in Android. I have read a lot of posts about it, but can't get one to work.
This is my method:
public Cursor getLastId() {
return mDb.query(DATABASE_TABLE, new String[] {KEY_WID}, KEY_WID + "=" + MAX(_id), null, null, null, null, null);}
I have tried with MAX, but I must be using it wrong. Is there another way?
Well actually the SQLiteDatabase class has its own insert method which returns the id of the newly created row. I think this is the best way to get the new ID.
You can check its documentation here.
I hope this helps.
Use
SELECT last_insert_rowid();
to get the last inserted rowid.
If you are using AUTOINCREMENT keyword then
SELECT * from SQLITE_SEQUENCE;
will tell you the values for every table.
To get the last row from the table..
Cursor cursor = theDatabase.query(DATABASE_TABLE, columns,null, null, null, null, null);
cursor.moveToLast();
Use moveToLast() in Cursor interface.
From android.googlesource.com
/**
* Move the cursor to the last row.
*
* <p>This method will return false if the cursor is empty.
*
* #return whether the move succeeded.
*/
boolean moveToLast();
Simple example:
final static String TABLE_NAME = "table_name";
String name;
int id;
//....
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
if(cursor.moveToLast()){
//name = cursor.getString(column_index);//to get other values
id = cursor.getInt(0);//to get id, 0 is the column index
}
Or you can get the last row when insertion(Which is #GorgiRankovski have mentioned):
long row = 0;//to get last row
//.....
SQLiteDatabase db= this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_NAME, name);
row = db.insert(TABLE_NAME, null, contentValues);
//insert() returns the row ID of the newly inserted row, or -1 if an error occurred
Also their is a multiple ways you can do this using query:
One is expressed by #DiegoTorresMilano
SELECT MAX(id) FROM table_name. or to get all columns values SELECT * FROM table_name WHERE id = (SELECT MAX(id) FROM table_name).
If your PRiMARY KEY have sat to AUTOINCREMENT, you can SELECT vaules occording to max to min and limit the rows to 1 using SELECT id FROM table ORDER BY column DESC LIMIT 1
(If you want each and every value, use * instead of id)
If you want the last_insert_id just afert a insert you can use that :
public long insert(String table, String[] fields, String[] vals )
{
String nullColumnHack = null;
ContentValues values = new ContentValues();
for (int i = 0; i < fields.length; i++)
{
values.put(fields[i], vals[i]);
}
return myDataBase.insert(table, nullColumnHack, values);
}
The insert method returns the id of row just inserted or -1 if there was an error during insertion.
long id = db.insert("your insertion statement");
db is an instance of your SQLiteDatabase.
Try this:
public Cursor getLastId() {
return mDb.query(DATABASE_TABLE, new String[] { **MAX(id)** }, null, null, null, null, null, null);}
/**
* #return
*/
public long getLastInsertId() {
long index = 0;
SQLiteDatabase sdb = getReadableDatabase();
Cursor cursor = sdb.query(
"sqlite_sequence",
new String[]{"seq"},
"name = ?",
new String[]{TABLENAME},
null,
null,
null,
null
);
if (cursor.moveToFirst()) {
index = cursor.getLong(cursor.getColumnIndex("seq"));
}
cursor.close();
return index;
}
I use this
public int lastId(){
SQLiteDatabase db =
this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from resep", null );
res.moveToLast();
return res.getInt(0);
}
In your DbHelper class,
public long getLastIdFromMyTable()
{
SQLiteDatabase db = this.getReadableDatabase();
SQLiteStatement st = db.compileStatement("SELECT last_insert_rowid() from " + MY_TABLE);
return st.simpleQueryForLong();
}

Categories

Resources