I have a database (sqlite on Android) with several columns:
_id, datum, hour, note
The database is created by this:
private static final String DATABASE_CREATE =
"create table worked (_id integer primary key autoincrement, "
+ "datum text not null, hour text not null, "
+ "note text);";
At the end I want the total of hours and minutes out of my database and return it to my mainActivity.
I tried to do this:
public int getTotalHours(){
Cursor c = db.rawQuery("select hour from " + DATABASE_TABLE, null);
int total = 0;
Date hours = new Date();
SimpleDateFormat hourFormat = new SimpleDateFormat("HH:mm");
c.moveToFirst();
for(int i = 0; i<c.getCount(); i++){
String uur = c.getString(i);
try {
hours = hourFormat.parse(uur);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
total += hours.getHours();
}
return total;
}
But I'm already getting a error in my query. I also dont know how if the data is being extracted at the right way, I cant test that because of the query error...
The error I'm getting:
Failed to read row 0, column 1 from a cursorWindow which has 5 rows, 1 columns.
I hope I was in the right way, and that somebody can help me.
Thanks in advance!
Properly loop through your records, retrieve the proper column index, and close your cursor:
public int getTotalHours(){
Cursor c = db.rawQuery("select hour from " + DATABASE_TABLE, null);
if (c == null)
return 0;
try{
int total = 0;
Date hours = new Date();
SimpleDateFormat hourFormat = new SimpleDateFormat("HH:mm");
while(c.moveToNext())
{
String uur = c.getString(0);
try {
hours = hourFormat.parse(uur);
total += hours.getHours();
} catch (ParseException e) {
e.printStackTrace();
}
}
return hours;
}finally{
c.close();
}
}
use
String uur = c.getString(1);
In your for loop, start your int i off at 1 instead of 0
for(int i = 1; i<c.getCount(); i++){
String uur = c.getString(i);
try {
hours = hourFormat.parse(uur);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Calling c.moveToNext() at the end of the loop would help. Also c.getString(i) should be c.getString(0).
Please make sure that the hours row is the first one in the db table. if you're not sure this modified code should work
enter code here
public int getTotalHours(){
Cursor c = db.rawQuery("select hour from " + DATABASE_TABLE, null);
int total = 0;
Date hours = new Date();
SimpleDateFormat hourFormat = new SimpleDateFormat("HH:mm");
c.moveToFirst();
int column = c.getColumnIndex("id")
for(int i = 0; i<c.getCount(); i++){
String uur = c.getString(c);
try {
hours = hourFormat.parse(uur);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
total += hours.getHours();
}
return total;
}
First, it's a table in a database what you are creating so I suggest you use CREATE_TABLE variable name instead.
Second, you can do:
Cursor c = db.rawQuery("select sum(hour) from " + DATABASE_TABLE, null);
having defined hour as integer in you table.
If you define the correct columns and use the right operations sqlite can do it:
sqlite> .schema t1
CREATE TABLE t1 (hours time not null);
sqlite> select * from t1;
05:30:00
06:30:00
01:30:00
02:15:00
sqlite> select strftime('%H:%M', 946684800 + sum(strftime('%s', hours) - 946684800), 'unixepoch') from t1;
15:45
sqlite>
Related
May I know what's the problem with this? It should be "5555555556" instead. See the Total Amount is Not CORRECT.
Is My Code wrote wrong already?
Here is my CODE
//show total amount
try {
SQLiteDatabase db = mSQLiteHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT SUM (Amount) from Donation_Details WHERE strftime('%d %m %Y',CreatedDate) = strftime('%d %m %Y',date('now'))", null);
if (cursor.moveToFirst()) {
int sum = cursor.getInt(0);
DecimalFormat formatter = new DecimalFormat("#,###,###");
String yourFormattedString = formatter.format(sum);
total_Amount.setText("RM " + yourFormattedString);
}
} catch (Exception e) {
e.printStackTrace();
}
And It can't show Decimal if I wrote "555555.55". It will only show infront numbers. Can anyone help me?
Change int to double of sum variable and also change DecimalFormat like below code,
try {
SQLiteDatabase db = mSQLiteHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT SUM (Amount) from Donation_Details WHERE strftime('%d %m %Y',CreatedDate) = strftime('%d %m %Y',date('now'))", null);
if (cursor.moveToFirst()) {
double sum = cursor.getDouble(0);
DecimalFormat formatter = new DecimalFormat("#,###,###,###.00");
String yourFormattedString = formatter.format(sum);
total_Amount.setText("RM " + yourFormattedString);
}
} catch (Exception e) {
e.printStackTrace();
}
The solution is to change
int
to
double
and change your decimal format to
DecimalFormat formatter = new DecimalFormat("#,###,###,###");
I've been trying to make an SQLite database which creates a new table every year automatically with the name along the lines of abc_2018. The problem is that every time a new table has to be added (i.e. the year changes) I need to update the DATABASE_VERSION. This probably requires storage of the current DATABASE_VERSION and incrementing its value every time a new table has to be added. I tried using SharedPreferences but I keep getting random errors.
So my question is how do I make a mechanism that automatically creates a table when the user's system date changes, or more precisely, when a new year starts?
EDIT
Solved my problem by doing this:
try {
cur = db.query(TABLE_NAME, PROJECTION, SELECTION, ARGS, null, null, null);
} catch (SQLiteException e) {
if (e.getMessage().contains("no such table")){
// create new table and execute query
}
}
Instead of :-
try {
cur = db.query(TABLE_NAME, PROJECTION, SELECTION, ARGS, null, null, null);
} catch (SQLiteException e) {
if (e.getMessage().contains("no such table")){
// create new table and execute query
}
}
Regarding the potential issues as pointed out by pskink's comment:-
if (e.getMessage().contains("no such table")) no no no, its so ugly
workaround that i dont know what to say... what if they change it to
"No such table" someday? or "that table does not exist"?
The following would be more resilient (considering how SQLite caters for backwards compatibility) :-
cur = db.query(sqlite_master,new String{"tbl_name"},"tbl_name=?",new String[]{TABLE_NAME},null,null,null);
if (cur.getCount < 1) { // ==0 if you prefer
//Create new table
}
You can use broadcast receiver like ACTION_DATE_CHANGED
More details can be found at https://developer.android.com/reference/android/content/Intent.html#ACTION_DATE_CHANGED
Code:
public void createDynamicDatabase(Context context,String tableName,ArrayList<String> title) {
Log.i("INSIDE createLoginDatabase() Method","*************creatLoginDatabase*********");
try {
int i;
String queryString;
myDataBase = context.openOrCreateDatabase("Db",Context.MODE_WORLD_WRITEABLE, null); //Opens database in writable mode.
//System.out.println("Table Name : "+tableName.get(0));
queryString = title.get(0)+" VARCHAR(30),";
Log.d("**createDynamicDatabase", "in oncreate");
for(i = 1; i < title.size() - 1; i++)
{
queryString += title.get(i);
queryString +=" VARCHAR(30)";
queryString +=",";
}
queryString+= title.get(i) +" VARCHAR(30)";
queryString = "CREATE TABLE IF NOT EXISTS " + tableName + "("+queryString+");";
System.out.println("Create Table Stmt : "+ queryString);
myDataBase.execSQL(queryString);
} catch (SQLException ex) {
Log.i("CreateDB Exception ",ex.getMessage());
}
}
public void insert(Context context,ArrayList<String> array_vals,ArrayList<String> title,String TABLE_NAME) {
Log.d("Inside Insert","Insertion starts for table name: "+TABLE_NAME);
myDataBase = context.openOrCreateDatabase("Db",Context.MODE_WORLD_WRITEABLE, null); //Opens database in writable mode.
String titleString=null;
String markString= null;
int i;
titleString = title.get(0)+",";
markString = "?,";
Log.d("**createDynamicDatabase", "in oncreate");
for(i = 1; i < title.size() - 1; i++)
{
titleString += title.get(i);
titleString +=",";
markString += "?,";
}
titleString+= title.get(i);
markString += "?";
//System.out.println("Title String: "+titleString);
//System.out.println("Mark String: "+markString);
INSERT="insert into "+ TABLE_NAME + "("+titleString+")"+ "values" +"("+markString+")";
System.out.println("Insert statement: "+INSERT);
//System.out.println("Array size iiiiii::: "+array_vals.size());
//this.insertStmt = this.myDataBase.compileStatement(INSERT);
int s=0;
while(s<array_vals.size()){
System.out.println("Size of array1"+array_vals.size());
//System.out.println("Size of array"+title.size());
int j=1;
this.insertStmt = this.myDataBase.compileStatement(INSERT);
for(int k =0;k< title.size();k++)
{
//System.out.println("Value of column "+title+" is "+array_vals.get(k+s));
//System.out.println("PRINT S:"+array_vals.get(k+s));
System.out.println("BindString: insertStmt.bindString("+j+","+ array_vals.get(k+s)+")");
insertStmt.bindString(j, array_vals.get(k+s));
j++;
}
s+=title.size();
}
insertStmt.executeInsert();
}
I have a ListView which displays items in my shopping cart from my existing database and at the bottom i have created TextView of total price of all the items in my cart,but the total price that displays at the bottom does not get updated according to the products in my cart.I am not getting where am I making mistake,please help me out.
xml code for TextView of Total price:
<TextView
android:id="#+id/totalItemPrice"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="RS "
android:textSize="20dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:textColor="#FFFFFF"/>
AddToCartFragment.java :
private ArrayList<GenieCart_List_Model> mAddList;
private void getCart_Data() {
try {
db = new DataBasehelper1(getActivity());
mAddList = new ArrayList<GenieCart_List_Model>();
mAddList = db.getAllCotacts();
long sum = db.sum_Of_Rs();
mTotalItemPrice.setText("Total Rs : " + sum);
db.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
DataBaseHelper1.java:
public long sum_Of_Rs() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery(" select * from " +CONTACTS_TABLE_NAME + " ORDER BY " + CONTACTS_PRODUCT_ID + " DESC " , null);
ArrayList<GenieCart_List_Model> list = new ArrayList<GenieCart_List_Model>();
try {
res.moveToFirst();
for (int i = 0; i < res.getCount(); i++) {
GenieCart_List_Model Prod_Details = new GenieCart_List_Model();
Prod_Details.setPrice(res.getString(res.getColumnIndex(CONTACTS_PRODUCT_RS)));
Prod_Details.setProdID(res.getString(res.getColumnIndex(CONTACTS_PRODUCT_ID)));
try {
int total = Integer.parseInt(res.getString(res.getColumnIndex(CONTACTS_PRODUCT_RS)));
Sum = Sum + total;
return Sum;
} catch (Exception e) {
e.printStackTrace();
}
list.add(Prod_Details);
res.moveToNext();
}
}
catch (Exception e) {
e.printStackTrace();
}
return Sum;
}
I think this is a conversion issue.
Set Text like that
mTotalItemPrice.setText("Total Rs : " + String.valueOf(sum));
Remove the line " return sum; " from try catch .
Your method sum_Of_Rs() is right. To update the total cost call your method sum_Of_Rs() and set the result to the TextView every time you add or delete an item in the cart i.e. if you are using ListView always do these steps when you notify the listview about the data changes using notifyDataSetChanged() you can also improve your method sum_Of_Rs() by changing your method to the following:
public long sum_Of_Rs() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT SUM (" + CONTACTS_PRODUCT_RS + ") FROM " + CONTACTS_TABLE_NAME , null);
cursor.moveToFirst();
int sum = cursor.getInt(0);
cursor.close();
return sum;
}
I Suggest to change your SQL Query to :
public long sum_Of_Rs() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("SELECT SUM ( " +CONTACTS_PRODUCT_RS + ") FROM " + CONTACTS_TABLE_NAME , null);
c.moveToFirst();
int i = c.getInt(0);
c.close();
return i;
}
PS: SUM() will return a number in the same format of the column that you are reading. if CONTACTS_PRODUCT_RS is a float/double use
float i = c.getFloat(0);
double i = c.getDouble(0);
Hope it help !! :))
In my application i am showing data from database in a table view.My requirement is that from database i have to retrieve the data which will fall in the current month.I Have written the query but it is coming as 0.Actually i have 1 entry in the database with today's date,so my query should return that data,but it is showing as 0.Please help me.Thanks in advance.
My query is as follows:
public String addgroupincome(String grp) throws SQLException
{
long sum=0;
Cursor cursor1 = db.rawQuery(
"SELECT SUM("+(KEY_TOTAL)+") FROM incomexpense WHERE date= Strftime('%Y-%m','now') AND category='Income' AND groups='"+grp+"'",null);
if(cursor1.moveToFirst())
{
sum = cursor1.getLong(0);
}
cursor1.close();
String housetotal=String.valueOf((long)sum);
return housetotal;
}
I am getting that total and showing in atextview in table layout..
final String houtotal=db.addgroupincome(group1);
housetotal.setText(houtotal);
Most probably nothing wrong with the query but the way you pass the query result to ListView. Can you show how you do it? Perhaps I could help.
Or you could take a look here or here
public int getCount() {
DBHelper dbHelper = DBHelper.getDBAdapterInstance(this);
int count = 0;
try {
dbHelper.openDataBase();
String query = "select count(1) from t_model where upper(brandName) = upper('"
+ selectedBrand + "') order by modelName ASC";
Cursor cursor = dbHelper.selectRecordsCursor(query, null);
if (cursor.moveToFirst()) {
count = cursor.getInt(0);
}
cursor.close();
cursor = null;
} catch (Exception e) {
e.printStackTrace();
} finally {
dbHelper.close();
}
return count;
}
and for the TextView should be as simple as
TextView tvCount = (TextView) findViewById(R.id.tvCount);
tvCount.setText("Count : " + getCount);
If you are having trouble debugging your query. Try http://sqlitebrowser.sourceforge.net/ or http://www.sqliteexpert.com/
Why don't you try by giving column names of your table in your query..might it work out for you..specify the columns which you want to retrive..
if (cursor.moveToNext()) {
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
Log.i(ID, cursor.getInt(0) + "");
cursor.moveToNext();
}
cursor.close();
} else {
cursor.close();
return null;
}
Try This Method....
I have stored the date as string in sqlite database table. What i need i i have to retrieve the values which stored in last seven days. I have tried by using following but it doesn't showing any values.
My Database function
public Cursor paymentWeek(Activity activity)
{
String[] from = { _PAYMENTID, NAME, REQUESTEDDATE, FROMAD, TOADD, EMAILBODYPAYMENT, AMOUNT};
SQLiteDatabase db = getReadableDatabase();
String orderby = REQUESTEDDATE+" DESC";
Cursor cursor = db.rawQuery("select * from " + PAYMENTTABLE + " where " + REQUESTEDDATE + " BETWEEN "
+ "date('now')" + " AND " + "date('now','-7 days')", null);
activity.startManagingCursor(cursor);
return cursor;
}
Calling function
Cursor week = db.paymentWeek(this);
String[] weekly = new String[] { PaymentAppDataBase.REQUESTEDDATE,PaymentAppDataBase.PAYMENTNAME,PaymentAppDataBase.AMOUNT };
int[] sevendays = new int[] { R.id.Date,R.id.Name,R.id.Amount };
SimpleCursorAdapter weekcursor =
new SimpleCursorAdapter(this, R.layout.listview, week, weekly, sevendays);
setListAdapter(weekcursor);
db.close();
It would be helpful if you guys sort out this problem. I get stuck over here.
try Following query to get records for last week(7 days):
"select * from " + PAYMENTTABLE + " where " + REQUESTEDDATE + "DATE_SUB( CURDATE( ) ,INTERVAL 7 DAY ) AND CURDATE( )";
You don't have to change your db design.
Just write your own convert from dateString to long method, and put it in class like DateUtil.java, then call it wherever you want to do something with date type.
The method should look like this:
public static long convertStringDateToLong(String date, String yourDateFormat) {
Long time = 0L;
try {
SimpleDateFormat df = new SimpleDateFormat(yourDateFormat);
Date d = null;
try {
d = df.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
time = d.getTime();
} catch (Exception e) {
e.printStackTrace();
}
return time;
}
where yourDateFormat should be something like: "MM/dd/yyyy"