I'm currently developing an application for android and I'm trying to get the last entry in my database ordered by a column that contains a String with the date and time.
My problem is that the result of the query is always the first date and not the last one.
I already tried ordered my column by "date", "datetime" and by "DESC" and "ASC".
the following is the query to create the table that contains the date in question
private static final String CREATE_TABLE_TIMBRAGE="CREATE TABLE "
+ TABLE_TIMBRAGE + "(" + COLUMN_T_TIMBRAGE_PK_TIMBRAGE + " INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
+ COLUMN_T_TIMBRAGE_DATETIMBRAGE + " DATETIME NOT NULL, " + COLUMN_T_TIMBRAGE_INOUT + " INT NOT NULL, "
+ COLUMN_T_TIMBRAGE_FK_EMPLOYE + " INT NOT NULL, "+ "FOREIGN KEY(" + COLUMN_T_TIMBRAGE_FK_EMPLOYE + ") REFERENCES " + TABLE_EMPLOYE + "("+COLUMN_T_EMPLOYE_PK_EMPLOYE+") "
here is my formatter for the dates
SimpleDateFormat FORMATTER=new SimpleDateFormat("dd.MM.yyyy'-'HH:mm:ss", Locale.FRANCE);
here is how I'm adding into this table
ContentValues values = new ContentValues();
values.put(COLUMN_T_TIMBRAGE_DATETIMBRAGE, FORMATTER.format(timbrage.getDateTimbrage()));
values.put(COLUMN_T_TIMBRAGE_INOUT, timbrage.getInOut());
values.put(COLUMN_T_TIMBRAGE_FK_EMPLOYE, timbrage.getFK_Employe());
SQLiteDatabase db = this.getWritableDatabase();
db.insert(TABLE_TIMBRAGE, null, values);
db.close();
and finally here is my query that should get the last entry
String query2 = "Select * FROM " + TABLE_TIMBRAGE + " WHERE " + COLUMN_T_TIMBRAGE_FK_EMPLOYE + " = \"" + FK_Employe + "\"" + " ORDER BY datetime("+ COLUMN_T_TIMBRAGE_DATETIMBRAGE +") ASC LIMIT 1 ";
Cursor cursor2 = db.rawQuery(query2, null);
The result that I get is
"Thu May 23 15:34:58 GMT+02:00 2019"
but I should get
"Thu May 23 15:56:32 GMT+02:00 2019"
Instead of saving date as a String, it is a good idea to convert said date to milliseconds since 01 Jan 1970. This way, the sorting is very straightforward and comparing numbers is more efficient. You can then, upon querying the data convert the milliseconds to a formatted Date.
Try this:
SELECT * FROM + YOUR_TABLE_NAME + ORDER BY + YOUR_DATETIME_COLUMN_NAME + DESC
And I have a suggestion that you should use DATETIME DEFAULT CURRENT_TIMESTAMP as your DATETIME column type. This auto-updates the DATETIME whenever you insert or update the row.
Related
I'm trying to update data in rows in my DB, but i catch error that there's no such column (no such column 'Moscow' or another)
This is DBHelper code:
public static final String tableName = "currentWeather";
public static final String KEY_ID = "_id";
public static final String cityName = "city";
public static final String cityTemp = "temperature";
And creating DB:
sqLiteDatabase.execSQL("create table " + tableName + "(" + KEY_ID + "
integer primary key autoincrement,"
+ cityName + " text," + cityTemp + " text, " + " UNIQUE(" + cityName +
"))");
and error shows when i try to execSQl in response:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " +
DBHelper.cityTemp + "=" +
response.body().getForecastMain().getTemp() + "
WHERE "
+ DBHelper.cityName + "=" + cityName);
I expect to update temperature data in rows by cityName
cityName and response.body().getForecastMain().getTemp() are strings and they should be passed surrounded with single quotes to the sql statement:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " + DBHelper.cityTemp + "='" + response.body().getForecastMain().getTemp() + "'" +
"WHERE " + DBHelper.cityName + " = '" + cityName + "'"
);
But the recommended and safe way of doing the update is with the use of ContentValues and ? as placeholders for the parameters:
ContentValues cv = new ContentValues();
cv.put(DBHelper.cityTemp, String.valueOf(response.body().getForecastMain().getTemp()));
int rows = sqLiteDatabase.update(
DBHelper.tableName,
cv,
DBHelper.cityName + " = ?",
new String[] {cityName}
);
You can examine the value of the integer variable rows.
If it is 1 this means that 1 row was updated (because cityName is unique) so the update was successful.
I think you have changed column name or add new one (city). So you can fix it by two ways
By uninstall the application from phone
Add column name in upgrade method.
Example:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}
The thing is you need to wrap the values after the = sign in single quotations in the UPDATE statement. As for digits they work in both cases.
For example here is the correct syntax
UPDATE currentWeather
SET temperature = 45
WHERE
city = 'Moscow'
But in your code I'm assuming cityName has the value Moscow without the single quotation marks so the converted SQL code will be like this
UPDATE currentWeather
SET temperature = 45
WHERE
city = Moscow
Now the sql interpreter will think Moscow is some database object or column or something and not a literal value. So you need to surround your values in single quotation marks.
Also consider What the data type of response.body().getForecastMain().getTemp() is.
If it's int you have to parse it or something, as the data type of the related column is Text.
I have database with 4 columns int id | String data | String date | int boot and i have some data in it. I have method getRow(String s) when i call it with string for id or data and change query to that option it works but when i´m trying to get row with equal date it won´t pass cursor.moveToFirst condition.
Here is my code:
String CREATE_TABLE = "CREATE TABLE "
+ TABLE_NAME + "(" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_DATA
+ " TEXT," + COLUMN_DATE + " TEXT," + COLUMN_BOOT + " Integer" + ")";
public String getRowID(String id){
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + TABLE_NAME + " where " + COLUMN_ID + " = " + id, null);
if (c != null && c.moveToFirst()) {
//loggin succes
return "string";
}else return null;
}
public String getRowDate(String date){
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = " + date, null);
if (c != null && c.moveToFirst()) {
//loggin succes
return "string";
}else return null;
}
myDb.getRowID("1"); returning something
myDb.getRowDate("02122016"); returning null
I have two rows in my database.
1 | 0.19 | 01122016 | 0
2 | 0.19 | 02122016 | 0
Be wary when comparing integers and strings. You may wonder why SQLite would be comparing integers at all since your arguments are strings, until you consider that your raw query looks like this:
select * from TABLE where DATE = 02122016
That value is interpreted as an integer and converted to text, but it loses the leading zero in the process. You can verify this with a sqlite3 shell:
sqlite> select 02122016;
2122016
sqlite> select '02122016' = 02122016;
0 -- false
sqlite> select cast(02122016 as text);
2122016
The simplest fix is to quote the value using a method from DatabaseUtils:
String escaped = DatabaseUtils.sqlEscapeString(date);
String query = "select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = " + escaped;
A better fix would be to use a placeholder argument instead. Note that Android binds all arguments as strings:
String query = "select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = ?";
db.rawQuery(query, new String[]{date});
However, my advice would be to not use rawQuery() and instead use one of the real query() methods. Here's a good example.
Lastly, perhaps you should consider a different format for storing dates. In practice I usually either store an INTEGER column with a unix timestamp (seconds or milliseconds since epoch), or I use a TEXT column with values in the yyyy-MM-dd format since this is implicitly supported by numerous datetime functions in SQLite.
i have a table "queue_in_progress" whose structure is like the following :
I want to update the DATE_TIME_TOKEN_TAKEN , CE_PK , Service_status of the table . For this , I have the following code :
String sqlQuery = "UPDATE queue_in_progress\n" +
"SET CE_PK="+ce_pk+" ,SERVICE_STATUS=1 \n" +
"WHERE CATEGORY_PK="+Category_PK+" AND TOKEN_NO="+ Token_PK+" "
+ " AND SERVICE_COUNTER="+service_counter+" AND SERVICE_CENTER_PK="+service_center+" ;";
java.util.Date utilDate = new Date(); // Convert it to java.sql.Date
java.sql.Date date = new java.sql.Date(utilDate.getTime());
PreparedStatement stmt = con.prepareStatement(sqlQuery);
stmt.setDate(1, date);
success = stmt.executeUpdate();
But the success flag is returning -1 and the table is not updated . What is the problem ? What can I do to fix this problem ?
I don't see DATE_TIME_TOKEN_TAKEN=? in your query (the bind parameter), I think you wanted
String sqlQuery = "UPDATE queue_in_progress SET DATE_TIME_TOKEN_TAKEN=?, "
+ "CE_PK=" + ce_pk
+ ", SERVICE_STATUS=1 WHERE CATEGORY_PK="
+ Category_PK
+ " AND TOKEN_NO="
+ Token_PK
+ " AND SERVICE_COUNTER="
+ service_counter + " AND SERVICE_CENTER_PK=" + service_center;
OR if you want DATE_TIME_TOKEN_TAKEN to ALWAYS hold Current Time value, you can Set it on your Database side, no need to set it in your code.
ALTER TABLE queue_in_progress
MODIFY DATE_TIME_TOKEN_TAKEN DEFAULT CURRENT_TIMESTAMP;
This is in the Main class
Contest c = new Contest();
c.setAnnouncementDate("2014-03-02");
Contest.addContest(c);
I am trying to insert this date in my mysql table. But it gives type incompatibility.
So we tried this code:
Contest c = new Contest();
SimpleDateFormat f = new SimpleDateFormat("yyyy-mm-dd");
java.sql.Date da = new java.sql.Date(f.parse("2014-04-02").getTime());
c.setAnnouncementDate(da);
Contest.addContest(c);
there is a addContest(Contest cont) method in Contest class which is used to insert the dates in mysql table:
code used is:
PreparedStatement s = con.prepareStatement("Insert into " + TABLENAME + " ( " + CONTESTID + " , " + ANNOUNCEMENTDATE + " , " + RESULTDECLARATIONDATE + " , " + SUBMISSIONSTARTDATE + " , " + SUBMISSIONENDDATE + " , " + REWARD + " ) VALUES ( ?,?,?,?,?,?)");
we inserted date using :
s.setDate(2, (java.sql.Date) cont.getAnnouncementDate());
here, it always inserts 2014-01-02 date in mysql table, irrespective of our argument that we pass.
please help me.
I retrieve data between two dates some how it get correct result and some how it output empty listview when i select dates with month it work properly but when i select dates between more than one month it output empty listview below is my codes
here i declare the variable in DB class
public static final String EX_RowID = "_id";
public static final String EX_Cattype = "Ecattype";
public static final String EX_Date = "Ecdate";
public static final String EX_Price = "Ecprice";
public static final String EX_Type = "itype";
creat table statement
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + Food_TABLE +"(" +
EX_RowID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
EX_Cattype + " TEXT NOT NULL, " +
EX_Date + " TEXT NOT NULL," +
EX_Price + " INTEGER NOT NULL," +
EX_Type + " TEXT NOT NULL UNIQUE );"
);
}
enter data Method
public long ExEntry(String Ecatgtype, String Edate, String Eprice, String Eitype) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues();
cv.put(EX_Cattype, Ecatgtype);
cv.put(EX_Date, Edate );
cv.put(EX_Price, Eprice);
cv.put(EX_Type, Eitype);
return ourdatabase.insertOrThrow(Food_TABLE, null, cv);
}
here i access the ExEntry Method
ExMgDB Expentry = new ExMgDB(ADD_EX.this);
Expentry.open();
Expentry.ExEntry(cate, date, price, itype);
Expentry.close();
here i am facing the problem between these two dates variables
public Cursor CstmRpot(String fd, String td) {
// TODO Auto-generated method stub
String[] columns = new String[] {EX_RowID,EX_Cattype, EX_Date, EX_Price, EX_Type };
Cursor c= ourdatabase.query(Food_TABLE, columns, EX_Date + " BETWEEN '" + fd + "'
AND '" + td + "'" , null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
i access it like below
CustemRpt dbcs = new CustemRpt();
Cursor cursor = CstDB.CstmRpot(frmdate,tondate);
There are two major solutions. All solutions have in common, that the column containing the date has to be ordered somehow. If this order is destroyed your data is corrupt and your queries cannot return the expected results!
1. Save your Dates as INTEGER in your database and use a method to map Dates to a number:
A possible way is to use Date.getTime () to map Dates to numbers, but there are many others. Important is that
equal dates get the same number and
that a date that is after another date gets a bigger number.
This way ordering will be correct for sure.
To achieve this with `Java.util.Date.getTime() you only have to set the time to 0:00:00:000 if you want to store date only.
For example:
"CREATE TABLE " + Food_TABLE +"(" +
EX_RowID + "INTEGER PRIMARY KEY AUTOINCREMENT, " +
EX_Cattype + " TEXT NOT NULL, " +
EX_Date + " INTEGER NOT NULL," +
EX_Price + " INTEGER NOT NULL," +
EX_Type + " TEXT NOT NULL UNIQUE );"
private static String dateOnly(java.util.Date d) {
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return Long.toString(cal.getTimeInMillis());
}
public Cursor CstmRpot(java.util.Date fd, java.util.Date td) {
// TODO Auto-generated method stub
String[] columns = new String[]{EX_RowID,EX_Cattype, EX_Date, EX_Price, EX_Type };
Cursor c= ourdatabase.query(Food_TABLE, columns, EX_Date + " > " + dateOnly (fd) + " AND " + EX_Date + " < " + dateOnly(td), null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
If you don't use different timezones the dateOnly(java.util.Date d) can be optimized.
Of course you can also use JODA-time.
2. Save your Dates as TEXT
If you choose this method your queries that are comparing the date-column are going to be a bit slower, but the entries in the database are human readable which doesn't have t be the case with method 1.
TEXT-columns are ordered with BINARY by default, which means memcmp() is used to compare the values and to determine which value is greater or if the values are equal. (Remember x BETWEEN a AND b means x <= a AND x >= b.)
You can examine the work of memcmp() with this function memcmp().
To ensure you get the right results you have to ensure the following:
All date-values in your database have to have the same text length.
All date-values in your database have to be in the same Format. The bigger date-parts (year) have to be before the smaller date-parts (month).
All Parameters for date-values in queries have to follow these rules too.
A possible date-format may look like this: yyyy-MM-dd (for example 2014-02-04 or 2000-12-24).
Advices
Use android.widget.DatePicker instead of Edittext for getting dates as input.
Never use any texts you got from user inputs directly in your query, but validate them before (see sql-injection).
Read some articles about how Strings are compared.
Try SELECT * FROM "your table" WHERE date BETWEEN "from date" AND "to date";
you need to store date inform of yyyy-mm-dd and then use this method simply call getWeekData(start_date, end_date);
public Object getWeekData(String start_date, String end_date) {
if (!mDataBase.isOpen())
openDataBase();
Object data = new Object ();
// Select All Query
String query = (String) ("Select * from " + TBL_NAME
+ " where " + (COL_DATE + " between '" + start_date + "' AND '" + end_date + "'"));
Cursor cursor = mDataBase.rawQuery(query, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
//get data over here
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
close();
return data;
}
we have Two solution for this question
one is we need to convert date and time into milliseconds, and take long data type in
Sqllite database and save values(converted date and time). And the write query like "SELECT
data, start_date, end_date from tablename WHERE start_date > end_date".
Second way is you need to save start and end date+time(yyy-MM-dd HH:mm:ss) in string format
in Sqllite database, and you need to query like this,
"SELECT datetime_start,datetime_end FROM tablename WHERE(( DATETIME(atetime_start) >=
DATETIME ("+"'"+entry_start_time+"'"+")" +" AND DATETIME(datetime_end) < DATETIME
("+"'"+entry_end_time+"'"+")); .