I just coded this way:
Cursor cursor;
String sql = "SELECT l.acao, SUM(strftime('%s',l.data_fim) - strftime('%s',l.data_inicio)) AS total_time," +
"FROM logs AS l " +
"WHERE l.data_fim IS NOT NULL " +
"GROUP BY l.acao";
I need to sum the seconds between two dates and I named this sum total_time. But when I try to get the result of total_time it always returns null, see next code:
String totalTimeInSeconds = (String) cursor.getString(cursor.getColumnIndex("total_time"));
When I put this same query in SqlLiteStudio it works perfectly. What am I doing wrong?
Your problem is that the value in the cursor actually is NULL.
This can happen only when the original date values are not in one of the supported date formats. You have to change your database.
instead of using cursor.getColumnIndex(), you can enter the exact index in it. In your case the total_time index is 1. Ex : cursor.getString(1) or cursor.getInt(1)
Related
I have the following code:
#Query("select t from Training t join t.skills s join t.trainers tr join t.discipline d where " +
"(t.name in :names or :names is null) and (s.name in :skills or :skills is null) and" +
" (t.location = :location or :location is null) and " +
" (d.name = :discipline or :discipline is null) and " +
"(tr.firstName in :trainers or :trainers is null) and " +
" (((:endDate > t.endDate) and (:startDate < t.startDate)) or (:startDate is empty))")
public List<Training> filterTrainings(List<String> names, List<String> skills, String location,String discipline,List<String> trainers,Timestamp endDate,Timestamp startDate);
and i need to check if :startDate and :endDate are null. Is there a way to do that?
The error i get is nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
when trying to check :startDate is null where start date is a Timestamp.
Could you try passing a LocalDateTime as a parameter instead of a Timestamp? java.sql.Timestamp might be causing you issues here. You can convert to a LocalDateTime by calling timestamp.toLocalDateTime()
Alternatively you could try passing the timestamp as a string into filterTrainings. If the timestamp is null before calling the filterTrainings method, assign an empty string. String _timestamp = timestamp == null ? "" : timestamp.toString()
Then, in your sql statement check if the string is empty .. ""=:timestamp OR function("to_timestamp", :timestamp, "yyyy-mm-dd hh:mm:ss.fffffffff"). The problem here is that we are using function to access native db commands.
Maybe you can build your SQL query with a and COALESCE(field, default_value_for_datetime_field). So you will not get NULL values.
You can build a default value as the start of the current month, of the current week, or any datetime value which could be a fair substitution for your model domain.
I did a SQL query in Java as follows:
"SELECT A.ID_MACHINE, A.HEURODATAGE, A.COMPTEUR, B.LIBELLE_IDMACHINE, C.LIBELLE_STATUT, C.CODE_COULEUR FROM ROXJAVA.MACH0004 A " +
"JOIN ROXJAVA.MACH0003 B ON A.ID_MACHINE = B.ID_MACHINE " +
"JOIN ROXJAVA.MACH0002 C ON B.CODE_MACHINE = C.CODE_MACHINE " +
"WHERE A.ID_MACHINE = ? AND A.HEURODATAGE BETWEEN '?' AND '?' AND A.CODE_STATUT = C.CODE_STATUT AND C.CODE_COULEUR = ? " +
"ORDER BY A.HEURODATAGE DESC";
In my WHERE it finds "Heurodatage" which must contain a time and a date with this format:
'2018-07-03 09:30:00.000'
I then want to retrieve the results of this query with the help of a method that takes into account the different attributes that I need to replace the? in my request.
But now I can not determine the type of my dates.
I'm getting "type not match" when I try to run with a String.
If the column is a date column, you want to pass in a date type:
PreparedStatement ps = ...;
ps.setDate(N, java.sql.Date.valueOf(your_date_value));
where it would be best if your_date_value is a java.time.LocalDate, but could also be parsed from a String (in a valid format).
I'm working on a small program that lists local train stops in a numbered list then asks for the user to type the number of the station that they wish to see the next arrival time for.
The problem I have is I don't think the MySQL query is correct to retrieve the arrival time. The list returns empty. Using jdbc previously, this query worked fine:
"SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
And the current hibernate query:
public List<String> getArrivals() {
sessionFactoryBean.getCurrentSession().beginTransaction();
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
List<String> arrivals = query.list();
sessionFactoryBean.getCurrentSession().getTransaction().commit();
return arrivals;
}
Called from this method and where I get IndexOutOfBoundsException:
public String getNextArrival(int user_input) {
getStationName(user_input);
List<String> arrivals1 = arrival.getArrivals();
System.out.println(arrivals1);
System.out.println(arrivals1.size());
String arrivalTime = arrivals1.get(user_input);
return convertTime(arrivalTime);
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0,
Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.moeller.code.Stops.getNextArrival(Stops.java:73)
Line 73 String arrivalTime = arrivals1.get(user_input);'
The DataBase is stored locally.
There are several problems with this.
First, the query does not use parameters, which means you will likely make this mistake elsewhere where it will be a danger. You have to pass on variables like this:
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = ?"
+ " AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
query.setParameter(1, myStation.getID());
See the question mark? That is a positional parameter. You can also use named parameters.
String sql = "SELECT thing FROM table WHERE column1 LIKE :ptrn";
...
query.setParameter("ptrn", "%that%");
Notice how inside the query the parameter starts with :, but it does not when calling setParameter.
This way of safely inserting parameters is called using "Prepared Statements", or "Parameterized Queries". Find a quick tutorial on them, they are very important.
Secondly, in getNextArrival you forget to check if the list has that many elements.
if (arrivals1.size() <= user_input) {
return null;
}
Of course then you have to be careful when it returns a null to the function where it's used.
You are using a wrong method for the List.
when yo use List.get(param) param should be the position that you are looking for, no the userInput.
you need loop the list and compare each position of the list with the user input.
best Regards
It's been long fight between mysql and sql lite date issue. I have a complex query which returns multiple data.
I read server Json objects and store them in sql lite android was fine.
So i did a query which is like below one
"SELECT * FROM " + MAIN_TABLE + " LEFT OUTER JOIN " + SERVICE_INFO_TABLE + " ON ServiceInfo.main_id = MAIN_TABLE._ID"
+ " LEFT OUTER JOIN " + M_USER_TABLE + " ON M._ID = ServiceInfo.m_id"
+ " LEFT OUTER JOIN " + U_TABLE + " ON MAIN_TABLE.u_id = U_TABLE._ID"
The problem starts when i read the MAIN_TABLE which contains creation_time and upation_time, The SERVICE_INFO_TABLE also contains creation_time, updation_time.
However the table contains different date and time respectively. The cursor returns same date and time for all entity.
It seems the cursor method got confused and return same data and time read from ServiceInfo table.
I dig deeper into debugging mode while SQL lite read the query, i saw strange things happening over there. Below is the reading example
Cursor cursor = sqLiteDatabase.rawQuery(selectQuery, null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
do {
Log.d("dummy", "dummy stopper");
VParcelable vParcelable = new VParcelable();
vParcelable.setId(cursor.getInt(cursor.getColumnIndex(VEntry._ID)));
vParcelable.setModel(cursor.getString(cursor.getColumnIndex(VEntry.MODEL)));
vParcelable.setYearMdl(cursor.getInt(cursor.getColumnIndex(VEntry.YEAR_MODEL)));
vParcelable.setCreationTime(cursor.getString(cursor.getColumnIndex(VEntry.CRE_TIME)));
vParcelable.setUpdationTime(cursor.getString(cursor.getColumnIndex(VEntry.UPA_TIME)));
So the ServiceInfo table also contains the same creation_time and updation_time.
vParcelable.setCreationTime(cursor.getString(cursor.getColumnIndex(VEntry.CRE_TIME)));
mColumns from cursor debugging mode shows "updation_time" and "creation_time" for VTable and same as for ServiceInfo table.
Is that problem of sql lite couldn't differentiate table column names?
That really sucks.
Help please.
Thanks
Your date string '15-04-2015' is in a DD-MM-YYYY format but it appears it is being treated as MM-DD-YYYY at some point. You aren't showing ANY code in your question, so I can't tell you exactly how you need to solve this. In general you need to specify to the database the date format you are using, or switch to storing it as a string or integer in the database. You might look at some of the answers to this question: Best way to work with dates in Android SQLite
I have the following problem:
I have two tables in one data base which consist of the same columns besides the name of the last column. I want to write data into them using Java.
I want to use the same preparedStatement for both tables, where I check with an if-command whether it is table1 or table2. table2 has amount10 as the name for the last column, table1 has amount20 for it. This number is stored in a variable within my code.
Below you can see a (simplified) example and how I tried to let the column name variable but it doesn't work. Is there any way to fix this without copying the whole statement and manually changing the number variable?
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount`+"number") VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount`+"number" = ? ; ";
PreparedStatement insertDataStmt;
This will not work since variables number and table are not going to be magically injected into your insertData string while you are changing them.
I'd to a method prepareInsertstatement(String table, String number) that would return correct PreparedStatement:
public void prepareInsertStatement(Connection conn, Strint table, String number) {
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount+"number"') VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount+"number"' = ? ; ";
PreparedStatement insertDataStmt = conn.prepareStatement(insertData);
return insertDataStmt;
}
Just remember to close the PreparesStatement when you don't need it any more.
I suppose that reason for that is invalid syntax. When you concatenate string for last column name you use code 'amount' + number. If your number value is 20, than concat result will be
'amount'20 that cause invalid syntax exception. Just move one extra ' after number.
"'amount" + number + "'"
Note: log, or just error that appears during this statement execution would be very useful to find right answer for your question.